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

Unified Diff: cc/pinch_zoom_scrollbars_manager.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: Added missing files. Created 8 years 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_scrollbars_manager.cc
diff --git a/cc/pinch_zoom_scrollbars_manager.cc b/cc/pinch_zoom_scrollbars_manager.cc
new file mode 100644
index 0000000000000000000000000000000000000000..e1443dc6d53e68242016978df2608129ed7aab51
--- /dev/null
+++ b/cc/pinch_zoom_scrollbars_manager.cc
@@ -0,0 +1,446 @@
+// Copyright 2012 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_scrollbars_manager.h"
+
+#include "cc/renderer.h"
+#include "skia/ext/platform_canvas.h"
+#include "ui/gfx/rect.h"
+
+using WebKit::WebRect;
+using WebKit::WebScrollbar;
+using WebKit::WebScrollbarThemeGeometry;
+
+namespace cc {
+
+scoped_ptr<PinchZoomScrollbarsManager> PinchZoomScrollbarsManager::create()
+{
+ return make_scoped_ptr(new PinchZoomScrollbarsManager());
+}
+
+PinchZoomScrollbarsManager::PinchZoomScrollbarsManager()
+ : m_scrollbarVertical(this, WebKit::WebScrollbar::Vertical)
+ , m_scrollbarHorizontal(this, WebKit::WebScrollbar::Horizontal)
+ , m_pinchZoomScrollbarVertical(0)
+ , m_pinchZoomScrollbarHorizontal(0)
+ , m_viewportScale(1)
+ , m_deviceScaleFactor(1)
+ , m_enabled(false)
+{
+}
+
+PinchZoomScrollbarsManager::~PinchZoomScrollbarsManager()
+{
+}
+
+void PinchZoomScrollbarsManager::setScrollbarVertical(ScrollbarLayerImpl* scrollbar)
+{
+ if (m_pinchZoomScrollbarVertical == scrollbar)
+ return;
+ m_pinchZoomScrollbarVertical = scrollbar;
+ if (m_pinchZoomScrollbarVertical) {
+ m_pinchZoomScrollbarVertical->setScrollbarGeometry(PZScrollbarGeometry::create(make_scoped_ptr(new ScrollbarThemeGeometry(this)).PassAs<WebScrollbarThemeGeometry>(), this));
+ m_pinchZoomScrollbarVertical->setScrollbarData(&m_scrollbarVertical);
+ }
+}
+
+void PinchZoomScrollbarsManager::setScrollbarHorizontal(ScrollbarLayerImpl* scrollbar)
+{
+ if (m_pinchZoomScrollbarHorizontal == scrollbar)
+ return;
+
+ m_pinchZoomScrollbarHorizontal = scrollbar;
+ if (m_pinchZoomScrollbarHorizontal) {
+ m_pinchZoomScrollbarHorizontal->setScrollbarGeometry(PZScrollbarGeometry::create(make_scoped_ptr(new ScrollbarThemeGeometry(this)).PassAs<WebScrollbarThemeGeometry>(), this));
+ m_pinchZoomScrollbarHorizontal->setScrollbarData(&m_scrollbarHorizontal);
+ }
+}
+
+scoped_ptr<ScrollbarGeometryFixedThumb>
+PinchZoomScrollbarsManager::PZScrollbarGeometry::create(scoped_ptr<WebKit::WebScrollbarThemeGeometry> theme, PinchZoomScrollbarsManager* owner)
+{
+ return make_scoped_ptr(new PZScrollbarGeometry(theme.Pass(), owner)).PassAs<ScrollbarGeometryFixedThumb>();
+}
+
+PinchZoomScrollbarsManager::PZScrollbarGeometry::PZScrollbarGeometry(scoped_ptr<WebKit::WebScrollbarThemeGeometry> theme, PinchZoomScrollbarsManager* owner)
+ : ScrollbarGeometryFixedThumb(theme.Pass())
+ , m_owner(owner)
+{
+}
+
+PinchZoomScrollbarsManager::PZScrollbarGeometry::~PZScrollbarGeometry()
+{
+}
+
+WebKit::WebScrollbarThemeGeometry* PinchZoomScrollbarsManager::PZScrollbarGeometry::clone() const
+{
+ PZScrollbarGeometry* geometry =
+ new PZScrollbarGeometry(make_scoped_ptr(ScrollbarGeometryFixedThumb::clone()), m_owner);
+
+ return geometry;
+}
+
+int PinchZoomScrollbarsManager::PZScrollbarGeometry::thumbLength(WebKit::WebScrollbar* scrollbar)
+{
+ return m_owner->thumbLength(scrollbar);
+}
+
+int PinchZoomScrollbarsManager::PZScrollbarGeometry::thumbPosition(WebKit::WebScrollbar* scrollbar)
+{
+ return m_owner->position(scrollbar);
+}
+
+void PinchZoomScrollbarsManager::PZScrollbarGeometry::splitTrack(WebKit::WebScrollbar* scrollbar, const WebKit::WebRect& track, WebKit::WebRect& startTrack, WebKit::WebRect& thumb, WebKit::WebRect& endTrack)
+{
+ thumb = m_owner->thumbRect(scrollbar);
+ // PinchZoomScrollbarsManager encodes the thumb positions in the thumbRect,
+ // but callers to this function will expect a zero-offset rect.
+ thumb.x = 0;
+ thumb.y = 0;
+}
+
+bool PinchZoomScrollbarsManager::Scrollbar::isOverlay() const
+{
+ return true;
+}
+
+int PinchZoomScrollbarsManager::Scrollbar::value() const
+{
+ return m_owner->position(this);
+}
+
+WebKit::WebPoint PinchZoomScrollbarsManager::Scrollbar::location() const
+{
+ WebRect rect = m_owner->trackRect(this);
+ return WebKit::WebPoint(rect.x, rect.y);
+}
+
+WebKit::WebSize PinchZoomScrollbarsManager::Scrollbar::size() const
+{
+ WebRect rect = m_owner->trackRect(this);
+ return WebKit::WebSize(rect.width, rect.height);
+}
+
+bool PinchZoomScrollbarsManager::Scrollbar::enabled() const
+{
+ return true;
+}
+
+int PinchZoomScrollbarsManager::Scrollbar::maximum() const
+{
+ return m_owner->maximum(this);
+}
+
+int PinchZoomScrollbarsManager::Scrollbar::totalSize() const
+{
+ return m_owner->trackLength(this);
+}
+
+bool PinchZoomScrollbarsManager::Scrollbar::isScrollViewScrollbar() const
+{
+ return false;
+}
+
+bool PinchZoomScrollbarsManager::Scrollbar::isScrollableAreaActive() const
+{
+ return true;
+}
+
+void PinchZoomScrollbarsManager::Scrollbar::getTickmarks(WebKit::WebVector<WebKit::WebRect>& tickmarks) const
+{
+ // Our overlay pinch-zoom scroll bars do not have tick marks.
+}
+
+WebScrollbar::ScrollbarControlSize PinchZoomScrollbarsManager::Scrollbar::controlSize() const
+{
+ return WebScrollbar::RegularScrollbar;
+}
+
+WebScrollbar::ScrollbarPart PinchZoomScrollbarsManager::Scrollbar::pressedPart() const
+{
+ return WebScrollbar::NoPart;
+}
+
+WebScrollbar::ScrollbarPart PinchZoomScrollbarsManager::Scrollbar::hoveredPart() const
+{
+ return WebScrollbar::NoPart;
+}
+
+WebScrollbar::ScrollbarOverlayStyle PinchZoomScrollbarsManager::Scrollbar::scrollbarOverlayStyle() const
+{
+ return WebScrollbar::ScrollbarOverlayStyleDefault;
+}
+
+WebScrollbar::Orientation PinchZoomScrollbarsManager::Scrollbar::orientation() const
+{
+ return m_orientation;
+}
+
+bool PinchZoomScrollbarsManager::Scrollbar::isCustomScrollbar() const
+{
+ return true;
+}
+
+WebScrollbarThemeGeometry* PinchZoomScrollbarsManager::ScrollbarThemeGeometry::clone() const
+{
+ return new ScrollbarThemeGeometry(m_owner);
+}
+
+int PinchZoomScrollbarsManager::ScrollbarThemeGeometry::thumbPosition(WebScrollbar* scrollbar)
+{
+ return m_owner->position(scrollbar);
+}
+
+int PinchZoomScrollbarsManager::ScrollbarThemeGeometry::thumbLength(WebScrollbar* scrollbar)
+{
+ return m_owner->thumbLength(scrollbar);
+}
+
+int PinchZoomScrollbarsManager::ScrollbarThemeGeometry::trackPosition(WebScrollbar*)
+{
+ return 0;
+}
+
+int PinchZoomScrollbarsManager::ScrollbarThemeGeometry::trackLength(WebScrollbar*)
+{
+ return 0;
+}
+
+bool PinchZoomScrollbarsManager::ScrollbarThemeGeometry::hasButtons(WebScrollbar*)
+{
+ return false;
+}
+
+bool PinchZoomScrollbarsManager::ScrollbarThemeGeometry::hasThumb(WebScrollbar*)
+{
+ return true;
+}
+
+WebRect PinchZoomScrollbarsManager::ScrollbarThemeGeometry::trackRect(WebScrollbar* scrollbar)
+{
+ return m_owner->trackRect(scrollbar);
+}
+
+WebRect PinchZoomScrollbarsManager::thumbRect(const WebScrollbar* scrollbar) const
+{
+ WebRect rect;
+ if (scrollbar->orientation() == WebScrollbar::Vertical) {
+ rect = gfx::Rect(m_layoutViewportSize.width() - trackWidth(), position(scrollbar), trackWidth(), thumbLength(scrollbar));
+ } else {
+ rect = gfx::Rect(position(scrollbar), m_layoutViewportSize.height() - trackWidth(), thumbLength(scrollbar), trackWidth());
+ }
+ return rect;
+}
+
+WebRect PinchZoomScrollbarsManager::trackRect(const WebScrollbar* scrollbar) const
+{
+ if (scrollbar->orientation() == WebScrollbar::Vertical)
+ return WebRect(m_layoutViewportSize.width() - trackWidth(), 0, trackWidth(), m_layoutViewportSize.height());
+ else
+ return WebRect(0, m_layoutViewportSize.height() - trackWidth(), m_layoutViewportSize.width(), trackWidth());
+}
+
+int PinchZoomScrollbarsManager::thumbLength(const WebScrollbar* scrollbar) const
+{
+ if (scrollbar->orientation() == WebScrollbar::Vertical) {
+ float thumbFraction = static_cast<float>(m_layoutViewportSize.height())
+ / m_layoutDocumentSize.height() * m_deviceScaleFactor;
+ return thumbFraction * trackLength(scrollbar);
+ } else {
+ float thumbFraction = static_cast<float>(m_layoutViewportSize.width())
+ / m_layoutDocumentSize.width() * m_deviceScaleFactor;
+ return thumbFraction * trackLength(scrollbar);
+ }
+}
+
+int PinchZoomScrollbarsManager::trackLength(const WebScrollbar* scrollbar) const
+{
+ if (scrollbar->orientation() == WebScrollbar::Vertical)
+ return m_layoutViewportSize.height() - trackWidth();
+ else
+ return m_layoutViewportSize.width() - trackWidth();
+}
+
+int PinchZoomScrollbarsManager::position(const WebScrollbar* scrollbar) const
+{
+ if (scrollbar->orientation() == WebScrollbar::Vertical) {
+ float maxOffset = m_rootMaxScrollOffset.y() + (m_viewportScale - 1) / m_viewportScale * m_layoutViewportSize.height();
+ if (maxOffset < 1)
+ return 0;
+
+ float offset = m_rootScrollOffset.y() + m_layoutViewportPosition.y();
+ int scrollPosition = offset / maxOffset * maximum(scrollbar);
+ return scrollPosition;
+ } else {
+ float maxOffset = m_rootMaxScrollOffset.x() + (m_viewportScale - 1) / m_viewportScale * m_layoutViewportSize.width();
+ if (maxOffset < 1)
+ return 0;
+
+ float offset = m_rootScrollOffset.x() + m_layoutViewportPosition.x();
+ int scrollPosition = offset / maxOffset * maximum(scrollbar);
+ return scrollPosition;
+ }
+}
+
+int PinchZoomScrollbarsManager::maximum(const WebScrollbar* scrollbar) const
+{
+ return trackLength(scrollbar) - thumbLength(scrollbar);
+}
+
+WebRect PinchZoomScrollbarsManager::ScrollbarThemeGeometry::thumbRect(WebScrollbar* scrollbar)
+{
+ return m_owner->thumbRect(scrollbar);
+}
+
+int PinchZoomScrollbarsManager::ScrollbarThemeGeometry::minimumThumbLength(WebScrollbar*)
+{
+ return 0;
+}
+
+int PinchZoomScrollbarsManager::ScrollbarThemeGeometry::scrollbarThickness(WebScrollbar*)
+{
+ return 0;
+}
+
+WebRect PinchZoomScrollbarsManager::ScrollbarThemeGeometry::backButtonStartRect(WebScrollbar*)
+{
+ return WebRect();
+}
+
+WebRect PinchZoomScrollbarsManager::ScrollbarThemeGeometry::backButtonEndRect(WebScrollbar*)
+{
+ return WebRect();
+}
+
+WebRect PinchZoomScrollbarsManager::ScrollbarThemeGeometry::forwardButtonStartRect(WebScrollbar*)
+{
+ return WebRect();
+}
+
+WebRect PinchZoomScrollbarsManager::ScrollbarThemeGeometry::forwardButtonEndRect(WebScrollbar*)
+{
+ return WebRect();
+}
+
+WebRect PinchZoomScrollbarsManager::ScrollbarThemeGeometry::constrainTrackRectToTrackPieces(WebScrollbar*, const WebRect&)
+{
+ return WebRect();
+}
+
+void PinchZoomScrollbarsManager::ScrollbarThemeGeometry::splitTrack(WebScrollbar* scrollbar, const WebRect& track, WebRect& startTrack, WebRect& thumb, WebRect& endTrack)
+{
+ NOTREACHED() << "This call is supposed to be overridden by PZScrollbarGeometry.";
+}
+
+void allocateTextureResourceIfNeeded(scoped_ptr<ScopedResource>& texture, const gfx::Size& size, ResourceProvider* resourceProvider)
+{
+ if (!texture)
+ texture = ScopedResource::create(resourceProvider);
+
+ if (texture->size() != size)
+ texture->Free();
+
+ if (!texture->id())
+ texture->Allocate(Renderer::ImplPool, size, GL_RGBA, ResourceProvider::TextureUsageAny);
+}
+
+void PinchZoomScrollbarsManager::updateOneThumb(ScrollbarLayerImpl* scrollbarImpl,
+ Scrollbar& scrollbar,
+ scoped_ptr<ScopedResource>& thumbTexture,
+ scoped_ptr<SkCanvas>& thumbCanvas,
+ ResourceProvider* resourceProvider)
+{
+ gfx::Rect thumbRect = this->thumbRect(&scrollbar);
+ thumbRect = gfx::Rect(thumbRect.width() * m_deviceScaleFactor, thumbRect.height() * m_deviceScaleFactor);
+
+ allocateTextureResourceIfNeeded(thumbTexture, thumbRect.size(), resourceProvider);
+ scrollbarImpl->setThumbResourceId(thumbTexture->id());
+
+ SkISize canvasSize;
+ if (thumbCanvas)
+ canvasSize = thumbCanvas->getDeviceSize();
+ else
+ canvasSize.set(0, 0);
+
+ if (canvasSize.fWidth == thumbRect.width() && canvasSize.fHeight == thumbRect.height() && thumbCanvas)
+ return;
+
+ thumbCanvas = make_scoped_ptr(skia::CreateBitmapCanvas(thumbRect.width(), thumbRect.height(), false /* opaque */));
+
+ thumbCanvas->clear(SkColorSetARGB(0, 0, 0, 0));
+ SkPaint paint;
+ // WJM: the 255 below refers to blue, not red, but I haven't applied a swizzle.
+ paint.setColor(SkColorSetARGB(128, 255, 0, 0));
+ SkScalar border = m_deviceScaleFactor;
+ SkScalar cornerRadius = m_deviceScaleFactor * 5;
+
+ SkRect rect = SkRect::MakeXYWH(border, border,
+ thumbRect.width() - 2 * border,
+ thumbRect.height() - 2 * border);
+ thumbCanvas->drawRoundRect(rect, cornerRadius, cornerRadius, paint);
+
+ const SkBitmap* bitmap = &thumbCanvas->getDevice()->accessBitmap(false);
+ SkAutoLockPixels locker(*bitmap);
+ gfx::Rect layerRect(gfx::Point(), thumbRect.size());
+ DCHECK(bitmap->config() == SkBitmap::kARGB_8888_Config);
+ resourceProvider->setPixels(thumbTexture->id(), static_cast<const uint8_t*>(bitmap->getPixels()), layerRect, layerRect, gfx::Vector2d());
+}
+
+void PinchZoomScrollbarsManager::updateThumbTextures(ResourceProvider* resourceProvider)
+{
+ if (m_pinchZoomScrollbarVertical)
+ updateOneThumb(m_pinchZoomScrollbarVertical, m_scrollbarVertical, m_verticalThumbTexture,
+ m_verticalThumbCanvas, resourceProvider);
+ if (m_pinchZoomScrollbarHorizontal)
+ updateOneThumb(m_pinchZoomScrollbarHorizontal, m_scrollbarHorizontal, m_horizontalThumbTexture,
+ m_horizontalThumbCanvas, resourceProvider);
+}
+
+void PinchZoomScrollbarsManager::updateScrollbarImpl(ScrollbarLayerImpl* scrollbarLayerImpl,
+ WebScrollbar* scrollbar)
+{
+ if (!scrollbarLayerImpl || !scrollbar)
+ return;
+
+ scrollbarLayerImpl->setCurrentPos(scrollbar->value());
+ scrollbarLayerImpl->setMaximum(scrollbar->maximum());
+ scrollbarLayerImpl->setTotalSize(scrollbar->totalSize());
+ WebRect rect = thumbRect(scrollbar);
+ scrollbarLayerImpl->setPosition(gfx::PointF(rect.x, rect.y));
+ scrollbarLayerImpl->setBounds(gfx::Size(rect.width, rect.height));
+ scrollbarLayerImpl->setContentBounds(gfx::Size(rect.width, rect.height));
+ scrollbarLayerImpl->setDrawsContent(m_enabled);
+}
+
+void PinchZoomScrollbarsManager::setContentBounds(const gfx::Size& size)
+{
+ m_layoutDocumentSize = size;
+ updateScrollbarImpl(m_pinchZoomScrollbarVertical, &m_scrollbarVertical);
+ updateScrollbarImpl(m_pinchZoomScrollbarHorizontal, &m_scrollbarHorizontal);
+}
+
+void PinchZoomScrollbarsManager::setPinchZoomViewportPosition(const gfx::Vector2dF& location, float scale)
+{
+ m_layoutViewportPosition = location;
+ m_viewportScale = scale;
+ updateScrollbarImpl(m_pinchZoomScrollbarVertical, &m_scrollbarVertical);
+ updateScrollbarImpl(m_pinchZoomScrollbarHorizontal, &m_scrollbarHorizontal);
+}
+
+void PinchZoomScrollbarsManager::setPinchZoomViewportBounds(const gfx::Size& size)
+{
+ m_layoutViewportSize = size;
+ updateScrollbarImpl(m_pinchZoomScrollbarVertical, &m_scrollbarVertical);
+ updateScrollbarImpl(m_pinchZoomScrollbarHorizontal, &m_scrollbarHorizontal);
+}
+
+void PinchZoomScrollbarsManager::setRootScrollLayerOffset(const gfx::Vector2d& offset, const gfx::Vector2d& maxOffset)
+{
+ m_rootScrollOffset = offset;
+ m_rootMaxScrollOffset = maxOffset;
+ updateScrollbarImpl(m_pinchZoomScrollbarVertical, &m_scrollbarVertical);
+ updateScrollbarImpl(m_pinchZoomScrollbarHorizontal, &m_scrollbarHorizontal);
+}
+
+}

Powered by Google App Engine
This is Rietveld 408576698