summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/platform
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2011-09-21 15:43:37 +0100
committerSteve Block <steveblock@google.com>2011-09-22 22:57:10 +0100
commit8782ca1236bac0bb13e08a6b63f8743e0b01e75a (patch)
treeb3bf345515df5bf26b7df393ac4458c9dd57be86 /Source/WebCore/platform
parent06ab37f33e994114ce0ec9fbb35fe48249ed6dbc (diff)
downloadexternal_webkit-8782ca1236bac0bb13e08a6b63f8743e0b01e75a.zip
external_webkit-8782ca1236bac0bb13e08a6b63f8743e0b01e75a.tar.gz
external_webkit-8782ca1236bac0bb13e08a6b63f8743e0b01e75a.tar.bz2
Fix find-in-page to scroll scrollable layers
This requires the addition of the following methods ... - Layer::contentIsScrollable() - Layer::localToParent() - ScrollableLayerAndroid::scrollRectIntoView() Bug: 5262656 Change-Id: I2f1cf3342f73890f98a172f1b4e3f440c02dd9f4
Diffstat (limited to 'Source/WebCore/platform')
-rw-r--r--Source/WebCore/platform/graphics/android/Layer.cpp31
-rw-r--r--Source/WebCore/platform/graphics/android/Layer.h20
-rw-r--r--Source/WebCore/platform/graphics/android/LayerAndroid.h1
-rw-r--r--Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.cpp29
-rw-r--r--Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.h7
5 files changed, 81 insertions, 7 deletions
diff --git a/Source/WebCore/platform/graphics/android/Layer.cpp b/Source/WebCore/platform/graphics/android/Layer.cpp
index 361cb4e..f650c52 100644
--- a/Source/WebCore/platform/graphics/android/Layer.cpp
+++ b/Source/WebCore/platform/graphics/android/Layer.cpp
@@ -124,23 +124,34 @@ void Layer::getLocalTransform(SkMatrix* matrix) const {
matrix->preTranslate(-tx, -ty);
}
-void Layer::localToGlobal(SkMatrix* matrix) const {
+void Layer::localToAncestor(const Layer* ancestor, SkMatrix* matrix) const {
+ if (this == ancestor) {
+ matrix->setIdentity();
+ return;
+ }
+
getLocalTransform(matrix);
+ // Fixed position layers simply use the root layer's transform.
if (shouldInheritFromRootTransform()) {
+ ASSERT(!ancestor);
matrix->postConcat(getRootLayer()->getMatrix());
return;
}
- const Layer* layer = this;
- while (layer->fParent != NULL) {
- layer = layer->fParent;
-
+ // Apply the local and child transforms for every layer between this layer
+ // and ancestor.
+ ASSERT(isAncestor(ancestor));
+ for (const Layer* layer = this->fParent; layer != ancestor; layer = layer->fParent) {
SkMatrix tmp;
layer->getLocalTransform(&tmp);
tmp.preConcat(layer->getChildrenMatrix());
matrix->postConcat(tmp);
}
+
+ // If ancestor is not the root layer, apply its child transformation too.
+ if (ancestor)
+ matrix->postConcat(ancestor->getChildrenMatrix());
}
///////////////////////////////////////////////////////////////////////////////
@@ -204,3 +215,13 @@ void Layer::draw(SkCanvas* canvas, SkScalar opacity) {
}
}
}
+
+bool Layer::isAncestor(const Layer* possibleAncestor) const {
+ if (!possibleAncestor)
+ return true;
+ for (const Layer* layer = getParent(); layer; layer = layer->getParent()) {
+ if (layer == possibleAncestor)
+ return true;
+ }
+ return false;
+}
diff --git a/Source/WebCore/platform/graphics/android/Layer.h b/Source/WebCore/platform/graphics/android/Layer.h
index 7b27349..24302ce 100644
--- a/Source/WebCore/platform/graphics/android/Layer.h
+++ b/Source/WebCore/platform/graphics/android/Layer.h
@@ -104,7 +104,21 @@ public:
from this layer's root parent to the layer itself.
This is the matrix that is applied to the layer during drawing.
*/
- void localToGlobal(SkMatrix* matrix) const;
+ void localToGlobal(SkMatrix* matrix) const { localToAncestor(0, matrix); }
+
+ /** Return, as a matrix, the transform that converts from this layer's local
+ space to the space of the given ancestor layer. Use NULL for ancestor to
+ represent the root layer. Note that this method must not be called on a
+ fixed position layer with ancestor != NULL.
+
+ For non-fixed position layers, the following holds (in pseudo-code for
+ brevity) ...
+ SkMatrix localToAncestor = layer->localToAncestor(ancestor);
+ SkMatrix ancestorToGlobal = ancestor->localToAncestor(NULL);
+ SkMatrix localToGlobal = layer->localToGlobal();
+ ASSERT(localToAncestor * ancestorToGlobal == localToGlobal);
+ */
+ void localToAncestor(const Layer* ancestor, SkMatrix* matrix) const;
// paint method
@@ -115,12 +129,16 @@ public:
void setHasOverflowChildren(bool value) { m_hasOverflowChildren = value; }
+ virtual bool contentIsScrollable() const { return false; }
+
protected:
virtual void onDraw(SkCanvas*, SkScalar opacity);
bool m_hasOverflowChildren;
private:
+ bool isAncestor(const Layer*) const;
+
Layer* fParent;
SkScalar m_opacity;
SkSize m_size;
diff --git a/Source/WebCore/platform/graphics/android/LayerAndroid.h b/Source/WebCore/platform/graphics/android/LayerAndroid.h
index 31bb185..5bed7e5 100644
--- a/Source/WebCore/platform/graphics/android/LayerAndroid.h
+++ b/Source/WebCore/platform/graphics/android/LayerAndroid.h
@@ -243,7 +243,6 @@ public:
void bounds(SkRect*) const;
- virtual bool contentIsScrollable() const { return false; }
virtual LayerAndroid* copy() const { return new LayerAndroid(*this); }
void needsRepaint() { m_pictureUsed++; }
diff --git a/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.cpp
index 2bb8b5c..bca2fd4 100644
--- a/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.cpp
@@ -31,6 +31,35 @@ void ScrollableLayerAndroid::getScrollRect(SkIRect* out) const
out->fBottom = getSize().height() - m_scrollLimits.height();
}
+bool ScrollableLayerAndroid::scrollRectIntoView(const SkIRect& rect)
+{
+ // Apply the local transform to the rect to get it relative to the parent
+ // layer.
+ SkMatrix localTransform;
+ getLocalTransform(&localTransform);
+ SkRect transformedRect;
+ transformedRect.set(rect);
+ localTransform.mapRect(&transformedRect);
+
+ // Test left before right to prioritize left alignment if transformedRect is wider than
+ // visible area.
+ int x = m_scrollLimits.fLeft;
+ if (transformedRect.fLeft < m_scrollLimits.fLeft)
+ x = transformedRect.fLeft;
+ else if (transformedRect.fRight > m_scrollLimits.fRight)
+ x = transformedRect.fRight - std::max(m_scrollLimits.width(), transformedRect.width());
+
+ // Test top before bottom to prioritize top alignment if transformedRect is taller than
+ // visible area.
+ int y = m_scrollLimits.fTop;
+ if (transformedRect.fTop < m_scrollLimits.fTop)
+ y = transformedRect.fTop;
+ else if (transformedRect.fBottom > m_scrollLimits.fBottom)
+ y = transformedRect.fBottom - std::max(m_scrollLimits.height(), transformedRect.height());
+
+ return scrollTo(x - getPosition().fX, y - getPosition().fY);
+}
+
} // namespace WebCore
#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.h b/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.h
index b59b4e1..a2486a5 100644
--- a/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.h
+++ b/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.h
@@ -58,6 +58,13 @@ public:
m_scrollLimits.set(x, y, x + width, y + height);
}
+ // Given a rect in the layer, scrolls to bring the rect into view. Uses a
+ // lazy approach, whereby we scroll as little as possible to bring the
+ // entire rect into view. If the size of the rect exceeds that of the
+ // visible area of the layer, we favor the top and left of the rect.
+ // Returns whether or not any scrolling was required.
+ bool scrollRectIntoView(const SkIRect&);
+
friend void android::serializeLayer(LayerAndroid* layer, SkWStream* stream);
friend LayerAndroid* android::deserializeLayer(SkStream* stream);