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); |
+} |
+ |
+} |