summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
Diffstat (limited to 'Source')
-rw-r--r--Source/WebCore/Android.mk4
-rw-r--r--Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp2
-rw-r--r--Source/WebCore/platform/graphics/android/DumpLayer.cpp83
-rw-r--r--Source/WebCore/platform/graphics/android/DumpLayer.h67
-rw-r--r--Source/WebCore/platform/graphics/android/FixedPositioning.cpp106
-rw-r--r--Source/WebCore/platform/graphics/android/FixedPositioning.h128
-rw-r--r--Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp50
-rw-r--r--Source/WebCore/platform/graphics/android/IFrameContentLayerAndroid.cpp42
-rw-r--r--Source/WebCore/platform/graphics/android/IFrameContentLayerAndroid.h78
-rw-r--r--Source/WebCore/platform/graphics/android/IFrameLayerAndroid.cpp42
-rw-r--r--Source/WebCore/platform/graphics/android/IFrameLayerAndroid.h68
-rw-r--r--Source/WebCore/platform/graphics/android/Layer.cpp6
-rw-r--r--Source/WebCore/platform/graphics/android/Layer.h3
-rw-r--r--Source/WebCore/platform/graphics/android/LayerAndroid.cpp414
-rw-r--r--Source/WebCore/platform/graphics/android/LayerAndroid.h139
-rw-r--r--Source/WebCore/platform/graphics/android/LayerGroup.cpp193
-rw-r--r--Source/WebCore/platform/graphics/android/LayerGroup.h43
-rw-r--r--Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.cpp23
-rw-r--r--Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.h9
-rw-r--r--Source/WebCore/platform/graphics/android/SurfaceCollection.cpp24
-rw-r--r--Source/WebCore/rendering/RenderLayer.h9
-rw-r--r--Source/WebCore/rendering/RenderLayerCompositor.cpp7
-rw-r--r--Source/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp11
-rw-r--r--Source/WebKit/android/jni/AndroidHitTestResult.cpp4
-rw-r--r--Source/WebKit/android/jni/ViewStateSerializer.cpp135
-rw-r--r--Source/WebKit/android/jni/WebViewCore.cpp51
-rw-r--r--Source/WebKit/android/jni/WebViewCore.h4
-rw-r--r--Source/WebKit/android/nav/WebView.cpp2
28 files changed, 1254 insertions, 493 deletions
diff --git a/Source/WebCore/Android.mk b/Source/WebCore/Android.mk
index bae08c1..4884e5b 100644
--- a/Source/WebCore/Android.mk
+++ b/Source/WebCore/Android.mk
@@ -640,6 +640,8 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \
platform/graphics/android/BaseTileTexture.cpp \
platform/graphics/android/BitmapAllocatorAndroid.cpp \
platform/graphics/android/ClassTracker.cpp \
+ platform/graphics/android/DumpLayer.cpp \
+ platform/graphics/android/FixedPositioning.cpp \
platform/graphics/android/FontAndroid.cpp \
platform/graphics/android/FontCacheAndroid.cpp \
platform/graphics/android/FontCustomPlatformData.cpp \
@@ -654,6 +656,8 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \
platform/graphics/android/GradientAndroid.cpp \
platform/graphics/android/GraphicsContextAndroid.cpp \
platform/graphics/android/GraphicsLayerAndroid.cpp \
+ platform/graphics/android/IFrameContentLayerAndroid.cpp \
+ platform/graphics/android/IFrameLayerAndroid.cpp \
platform/graphics/android/ImageAndroid.cpp \
platform/graphics/android/ImageBufferAndroid.cpp \
platform/graphics/android/ImageSourceAndroid.cpp \
diff --git a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp
index fee94d3..3cf863e 100644
--- a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp
@@ -292,7 +292,7 @@ void BaseLayerAndroid::updateLayerPositions(const SkRect& visibleRect)
if (!compositedRoot)
return;
TransformationMatrix ident;
- compositedRoot->updateFixedLayersPositions(visibleRect);
+ compositedRoot->updateLayerPositions(visibleRect);
FloatRect clip(0, 0, content()->width(), content()->height());
compositedRoot->updateGLPositionsAndScale(
ident, clip, 1, m_state->zoomManager()->layersScale());
diff --git a/Source/WebCore/platform/graphics/android/DumpLayer.cpp b/Source/WebCore/platform/graphics/android/DumpLayer.cpp
new file mode 100644
index 0000000..5551965
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/DumpLayer.cpp
@@ -0,0 +1,83 @@
+#include "config.h"
+#include "DumpLayer.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+namespace WebCore {
+
+void lwrite(FILE* file, const char* str)
+{
+ fwrite(str, sizeof(char), strlen(str), file);
+}
+
+void writeIndent(FILE* file, int indentLevel)
+{
+ if (indentLevel)
+ fprintf(file, "%*s", indentLevel*2, " ");
+}
+
+void writeln(FILE* file, int indentLevel, const char* str)
+{
+ writeIndent(file, indentLevel);
+ lwrite(file, str);
+ lwrite(file, "\n");
+}
+
+void writeIntVal(FILE* file, int indentLevel, const char* str, int value)
+{
+ writeIndent(file, indentLevel);
+ fprintf(file, "%s = %d;\n", str, value);
+}
+
+void writeHexVal(FILE* file, int indentLevel, const char* str, int value)
+{
+ writeIndent(file, indentLevel);
+ fprintf(file, "%s = %x;\n", str, value);
+}
+
+void writeFloatVal(FILE* file, int indentLevel, const char* str, float value)
+{
+ writeIndent(file, indentLevel);
+ fprintf(file, "%s = %.3f;\n", str, value);
+}
+
+void writePoint(FILE* file, int indentLevel, const char* str, SkPoint point)
+{
+ writeIndent(file, indentLevel);
+ fprintf(file, "%s = { x = %.3f; y = %.3f; };\n", str, point.fX, point.fY);
+}
+
+void writeIntPoint(FILE* file, int indentLevel, const char* str, IntPoint point)
+{
+ writeIndent(file, indentLevel);
+ fprintf(file, "%s = { x = %d; y = %d; };\n", str, point.x(), point.y());
+}
+
+void writeSize(FILE* file, int indentLevel, const char* str, SkSize size)
+{
+ writeIndent(file, indentLevel);
+ fprintf(file, "%s = { w = %.3f; h = %.3f; };\n", str, size.width(), size.height());
+}
+
+void writeRect(FILE* file, int indentLevel, const char* str, SkRect rect)
+{
+ writeIndent(file, indentLevel);
+ fprintf(file, "%s = { x = %.3f; y = %.3f; w = %.3f; h = %.3f; };\n",
+ str, rect.fLeft, rect.fTop, rect.width(), rect.height());
+}
+
+void writeMatrix(FILE* file, int indentLevel, const char* str, const TransformationMatrix& matrix)
+{
+ writeIndent(file, indentLevel);
+ fprintf(file, "%s = { (%.2f,%.2f,%.2f,%.2f),(%.2f,%.2f,%.2f,%.2f),"
+ "(%.2f,%.2f,%.2f,%.2f),(%.2f,%.2f,%.2f,%.2f) };\n",
+ str,
+ matrix.m11(), matrix.m12(), matrix.m13(), matrix.m14(),
+ matrix.m21(), matrix.m22(), matrix.m23(), matrix.m24(),
+ matrix.m31(), matrix.m32(), matrix.m33(), matrix.m34(),
+ matrix.m41(), matrix.m42(), matrix.m43(), matrix.m44());
+}
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/android/DumpLayer.h b/Source/WebCore/platform/graphics/android/DumpLayer.h
new file mode 100644
index 0000000..5b30952
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/DumpLayer.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef DumpLayer_h
+#define DumpLayer_h
+
+#include "IntPoint.h"
+#include "SkPoint.h"
+#include "SkRect.h"
+#include "SkSize.h"
+#include "TransformationMatrix.h"
+
+// Debug tools : dump the layers tree in a file.
+// The format is simple:
+// properties have the form: key = value;
+// all statements are finished with a semi-colon.
+// value can be:
+// - int
+// - float
+// - array of elements
+// - composed type
+// a composed type enclose properties in { and }
+// an array enclose composed types in { }, separated with a comma.
+// exemple:
+// {
+// x = 3;
+// y = 4;
+// value = {
+// x = 3;
+// y = 4;
+// };
+// anarray = [
+// { x = 3; },
+// { y = 4; }
+// ];
+// }
+
+namespace WebCore {
+
+void lwrite(FILE* file, const char* str);
+void writeIndent(FILE* file, int indentLevel);
+void writeln(FILE* file, int indentLevel, const char* str);
+void writeIntVal(FILE* file, int indentLevel, const char* str, int value);
+void writeHexVal(FILE* file, int indentLevel, const char* str, int value);
+void writeFloatVal(FILE* file, int indentLevel, const char* str, float value);
+void writePoint(FILE* file, int indentLevel, const char* str, SkPoint point);
+void writeIntPoint(FILE* file, int indentLevel, const char* str, IntPoint point);
+void writeSize(FILE* file, int indentLevel, const char* str, SkSize size);
+void writeRect(FILE* file, int indentLevel, const char* str, SkRect rect);
+void writeMatrix(FILE* file, int indentLevel, const char* str, const TransformationMatrix& matrix);
+
+}
+
+#endif // DumpLayer_h
diff --git a/Source/WebCore/platform/graphics/android/FixedPositioning.cpp b/Source/WebCore/platform/graphics/android/FixedPositioning.cpp
new file mode 100644
index 0000000..140411a
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/FixedPositioning.cpp
@@ -0,0 +1,106 @@
+#include "config.h"
+#include "FixedPositioning.h"
+
+#include "DumpLayer.h"
+#include "IFrameLayerAndroid.h"
+#include "TilesManager.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include <cutils/log.h>
+#include <wtf/CurrentTime.h>
+#include <wtf/text/CString.h>
+#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "FixedPositioning", __VA_ARGS__)
+
+namespace WebCore {
+
+// Called when copying the layer tree to the UI
+FixedPositioning::FixedPositioning(LayerAndroid* layer, const FixedPositioning& position)
+ : m_layer(layer)
+ , m_fixedLeft(position.m_fixedLeft)
+ , m_fixedTop(position.m_fixedTop)
+ , m_fixedRight(position.m_fixedRight)
+ , m_fixedBottom(position.m_fixedBottom)
+ , m_fixedMarginLeft(position.m_fixedMarginLeft)
+ , m_fixedMarginTop(position.m_fixedMarginTop)
+ , m_fixedMarginRight(position.m_fixedMarginRight)
+ , m_fixedMarginBottom(position.m_fixedMarginBottom)
+ , m_fixedRect(position.m_fixedRect)
+ , m_renderLayerPos(position.m_renderLayerPos)
+{
+}
+
+// Executed on the UI
+IFrameLayerAndroid* FixedPositioning::updatePosition(SkRect viewport,
+ IFrameLayerAndroid* parentIframeLayer)
+{
+ // So if this is a fixed layer inside a iframe, use the iframe offset
+ // and the iframe's size as the viewport and pass to the children
+ if (parentIframeLayer) {
+ viewport = SkRect::MakeXYWH(parentIframeLayer->iframeOffset().x(),
+ parentIframeLayer->iframeOffset().y(),
+ parentIframeLayer->getSize().width(),
+ parentIframeLayer->getSize().height());
+ }
+ float w = viewport.width();
+ float h = viewport.height();
+ float dx = viewport.fLeft;
+ float dy = viewport.fTop;
+ float x = dx;
+ float y = dy;
+
+ // It turns out that when it is 'auto', we should use the webkit value
+ // from the original render layer's X,Y, that will take care of alignment
+ // with the parent's layer and fix Margin etc.
+ if (!(m_fixedLeft.defined() || m_fixedRight.defined()))
+ x += m_renderLayerPos.x();
+ else if (m_fixedLeft.defined() || !m_fixedRight.defined())
+ x += m_fixedMarginLeft.calcFloatValue(w) + m_fixedLeft.calcFloatValue(w) - m_fixedRect.fLeft;
+ else
+ x += w - m_fixedMarginRight.calcFloatValue(w) - m_fixedRight.calcFloatValue(w) - m_fixedRect.fRight;
+
+ if (!(m_fixedTop.defined() || m_fixedBottom.defined()))
+ y += m_renderLayerPos.y();
+ else if (m_fixedTop.defined() || !m_fixedBottom.defined())
+ y += m_fixedMarginTop.calcFloatValue(h) + m_fixedTop.calcFloatValue(h) - m_fixedRect.fTop;
+ else
+ y += h - m_fixedMarginBottom.calcFloatValue(h) - m_fixedBottom.calcFloatValue(h) - m_fixedRect.fBottom;
+
+ m_layer->setPosition(x, y);
+
+ return parentIframeLayer;
+}
+
+void FixedPositioning::contentDraw(SkCanvas* canvas, Layer::PaintStyle style)
+{
+ if (TilesManager::instance()->getShowVisualIndicator()) {
+ SkPaint paint;
+ paint.setARGB(80, 255, 0, 0);
+ canvas->drawRect(m_fixedRect, paint);
+ }
+}
+
+void writeLength(FILE* file, int indentLevel, const char* str, SkLength length)
+{
+ if (!length.defined())
+ return;
+ writeIndent(file, indentLevel);
+ fprintf(file, "%s = { type = %d; value = %.2f; };\n", str, length.type, length.value);
+}
+
+void FixedPositioning::dumpLayer(FILE* file, int indentLevel) const
+{
+ writeLength(file, indentLevel + 1, "fixedLeft", m_fixedLeft);
+ writeLength(file, indentLevel + 1, "fixedTop", m_fixedTop);
+ writeLength(file, indentLevel + 1, "fixedRight", m_fixedRight);
+ writeLength(file, indentLevel + 1, "fixedBottom", m_fixedBottom);
+ writeLength(file, indentLevel + 1, "fixedMarginLeft", m_fixedMarginLeft);
+ writeLength(file, indentLevel + 1, "fixedMarginTop", m_fixedMarginTop);
+ writeLength(file, indentLevel + 1, "fixedMarginRight", m_fixedMarginRight);
+ writeLength(file, indentLevel + 1, "fixedMarginBottom", m_fixedMarginBottom);
+ writeRect(file, indentLevel + 1, "fixedRect", m_fixedRect);
+}
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/android/FixedPositioning.h b/Source/WebCore/platform/graphics/android/FixedPositioning.h
new file mode 100644
index 0000000..973113b
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/FixedPositioning.h
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef FixedPositioning_h
+#define FixedPositioning_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "LayerAndroid.h"
+
+namespace WebCore {
+
+class IFrameLayerAndroid;
+
+struct SkLength {
+ enum SkLengthType { Undefined, Auto, Relative,
+ Percent, Fixed, Static, Intrinsic, MinIntrinsic };
+ SkLengthType type;
+ SkScalar value;
+ SkLength()
+ {
+ type = Undefined;
+ value = 0;
+ }
+ bool defined() const
+ {
+ if (type == Undefined)
+ return false;
+ return true;
+ }
+ float calcFloatValue(float max) const
+ {
+ switch (type) {
+ case Percent:
+ return (max * value) / 100.0f;
+ case Fixed:
+ return value;
+ default:
+ return value;
+ }
+ }
+};
+
+class FixedPositioning {
+
+public:
+ FixedPositioning(LayerAndroid* layer = 0) : m_layer(layer) {}
+ FixedPositioning(LayerAndroid* layer, const FixedPositioning& position);
+ virtual ~FixedPositioning() {};
+
+ void setFixedPosition(SkLength left, // CSS left property
+ SkLength top, // CSS top property
+ SkLength right, // CSS right property
+ SkLength bottom, // CSS bottom property
+ SkLength marginLeft, // CSS margin-left property
+ SkLength marginTop, // CSS margin-top property
+ SkLength marginRight, // CSS margin-right property
+ SkLength marginBottom, // CSS margin-bottom property
+ const IntPoint& renderLayerPos, // For undefined fixed position
+ SkRect viewRect) { // view rect, can be smaller than the layer's
+ m_fixedLeft = left;
+ m_fixedTop = top;
+ m_fixedRight = right;
+ m_fixedBottom = bottom;
+ m_fixedMarginLeft = marginLeft;
+ m_fixedMarginTop = marginTop;
+ m_fixedMarginRight = marginRight;
+ m_fixedMarginBottom = marginBottom;
+ m_fixedRect = viewRect;
+ m_renderLayerPos = renderLayerPos;
+ }
+
+ IFrameLayerAndroid* updatePosition(SkRect viewPort,
+ IFrameLayerAndroid* parentIframeLayer);
+
+ void contentDraw(SkCanvas* canvas, Layer::PaintStyle style);
+
+ void dumpLayer(FILE*, int indentLevel) const;
+
+ // ViewStateSerializer friends
+ friend void android::serializeLayer(LayerAndroid* layer, SkWStream* stream);
+ friend LayerAndroid* android::deserializeLayer(int version, SkStream* stream);
+
+private:
+ LayerAndroid* m_layer;
+
+ SkLength m_fixedLeft;
+ SkLength m_fixedTop;
+ SkLength m_fixedRight;
+ SkLength m_fixedBottom;
+ SkLength m_fixedMarginLeft;
+ SkLength m_fixedMarginTop;
+ SkLength m_fixedMarginRight;
+ SkLength m_fixedMarginBottom;
+ SkRect m_fixedRect;
+
+ // When fixed element is undefined or auto, the render layer's position
+ // is needed for offset computation
+ IntPoint m_renderLayerPos;
+};
+
+}
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif // FixedPositioning_h
diff --git a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp
index c50f6a6..1ac90e9 100644
--- a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp
@@ -22,7 +22,10 @@
#include "AndroidAnimation.h"
#include "Animation.h"
#include "FloatRect.h"
+#include "FixedPositioning.h"
#include "GraphicsContext.h"
+#include "IFrameContentLayerAndroid.h"
+#include "IFrameLayerAndroid.h"
#include "Image.h"
#include "ImagesManager.h"
#include "Layer.h"
@@ -232,8 +235,12 @@ void GraphicsLayerAndroid::updateFixedPosition()
return;
// We will need the Iframe flag in the LayerAndroid tree for fixed position
- if (view->isRenderIFrame())
- m_contentLayer->setIsIframe(true);
+ if (view->isRenderIFrame() && !m_contentLayer->isIFrame()) {
+ LayerAndroid* layer = new IFrameLayerAndroid(*m_contentLayer);
+ m_contentLayer->unref();
+ m_contentLayer = layer;
+ }
+
// If we are a fixed position layer, just set it
if (view->isPositioned() && view->style()->position() == FixedPosition) {
// We need to get the passed CSS properties for the element
@@ -264,12 +271,20 @@ void GraphicsLayerAndroid::updateFixedPosition()
SkRect viewRect;
viewRect.set(paintingOffsetX, paintingOffsetY, paintingOffsetX + w, paintingOffsetY + h);
IntPoint renderLayerPos(renderLayer->x(), renderLayer->y());
- m_contentLayer->setFixedPosition(left, top, right, bottom,
- marginLeft, marginTop,
- marginRight, marginBottom,
- renderLayerPos,
- viewRect);
- }
+
+ FixedPositioning* fixedPosition = m_contentLayer->fixedPosition();
+ if (!fixedPosition) {
+ fixedPosition = new FixedPositioning();
+ m_contentLayer->setFixedPosition(fixedPosition);
+ }
+
+ fixedPosition->setFixedPosition(left, top, right, bottom,
+ marginLeft, marginTop,
+ marginRight, marginBottom,
+ renderLayerPos,
+ viewRect);
+ } else if (m_contentLayer->isFixed())
+ m_contentLayer->setFixedPosition(0);
}
void GraphicsLayerAndroid::setPosition(const FloatPoint& point)
@@ -508,6 +523,8 @@ void GraphicsLayerAndroid::updateScrollingLayers()
if (layerNeedsOverflow) {
ASSERT(!m_foregroundLayer && !m_foregroundClipLayer);
m_foregroundLayer = new ScrollableLayerAndroid(layer);
+
+ // TODO: can clip layer be set to not intrinsically composited?
m_foregroundClipLayer = new LayerAndroid(layer);
m_foregroundClipLayer->setMasksToBounds(true);
m_foregroundClipLayer->addChild(m_foregroundLayer);
@@ -518,8 +535,7 @@ void GraphicsLayerAndroid::updateScrollingLayers()
// No need to copy the children as they will be removed and synced.
m_contentLayer->removeChildren();
// Replace the content layer with a scrollable layer.
- LayerAndroid* layer = new ScrollableLayerAndroid(*m_contentLayer);
- layer->setIsIframe(true);
+ LayerAndroid* layer = new IFrameContentLayerAndroid(*m_contentLayer);
m_contentLayer->unref();
m_contentLayer = layer;
if (m_parent) {
@@ -563,10 +579,10 @@ void GraphicsLayerAndroid::updateScrollOffset() {
if (m_foregroundLayer) {
IntSize scroll = layer->scrolledContentOffset();
m_foregroundLayer->setScrollOffset(IntPoint(scroll.width(), scroll.height()));
- } else if (m_contentLayer->contentIsScrollable()) {
+ } else if (m_contentLayer->isIFrameContent()) {
IntPoint p(layer->renderer()->frame()->view()->scrollX(),
layer->renderer()->frame()->view()->scrollY());
- static_cast<ScrollableLayerAndroid*>(m_contentLayer)->setIFrameScrollOffset(p);
+ static_cast<IFrameContentLayerAndroid*>(m_contentLayer)->setIFrameScrollOffset(p);
}
askForSync();
}
@@ -653,9 +669,9 @@ bool GraphicsLayerAndroid::repaint()
m_contentLayer->checkForPictureOptimizations();
// Check for a scrollable iframe and report the scrolling
// limits based on the view size.
- if (m_contentLayer->contentIsScrollable()) {
+ if (m_contentLayer->isIFrameContent()) {
FrameView* view = layer->renderer()->frame()->view();
- static_cast<ScrollableLayerAndroid*>(m_contentLayer)->setScrollLimits(
+ static_cast<IFrameContentLayerAndroid*>(m_contentLayer)->setScrollLimits(
m_position.x(), m_position.y(), view->layoutWidth(), view->layoutHeight());
LOG("setScrollLimits(%.2f, %.2f, w: %d h: %d) layer %d, frame scroll position is %d, %d",
m_position.x(), m_position.y(), view->layoutWidth(), view->layoutHeight(),
@@ -1016,6 +1032,12 @@ void GraphicsLayerAndroid::gatherRootLayers(Vector<const RenderLayer*>& list)
void GraphicsLayerAndroid::syncCompositingStateForThisLayerOnly()
{
+ if (m_contentLayer) {
+ RenderLayer* renderLayer = renderLayerFromClient(m_client);
+ int intrinsicallyComposited = renderLayer ? renderLayer->intrinsicallyComposited() : true;
+ m_contentLayer->setIntrinsicallyComposited(intrinsicallyComposited);
+ }
+
updateScrollingLayers();
updateFixedPosition();
syncChildren();
diff --git a/Source/WebCore/platform/graphics/android/IFrameContentLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/IFrameContentLayerAndroid.cpp
new file mode 100644
index 0000000..70b5c67
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/IFrameContentLayerAndroid.cpp
@@ -0,0 +1,42 @@
+#include "config.h"
+#include "IFrameContentLayerAndroid.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include <cutils/log.h>
+#include <wtf/CurrentTime.h>
+#include <wtf/text/CString.h>
+#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "IFrameContentLayerAndroid", __VA_ARGS__)
+
+namespace WebCore {
+
+bool IFrameContentLayerAndroid::scrollTo(int x, int y)
+{
+ IntRect scrollBounds;
+ getScrollBounds(&scrollBounds);
+ if (!scrollBounds.width() && !scrollBounds.height())
+ return false;
+ SkScalar newX = SkScalarPin(x, scrollBounds.x(), scrollBounds.width());
+ SkScalar newY = SkScalarPin(y, scrollBounds.y(), scrollBounds.height());
+ // Check for no change.
+ if (newX == m_iframeScrollOffset.x() && newY == m_iframeScrollOffset.y())
+ return false;
+ newX = newX - m_iframeScrollOffset.x();
+ newY = newY - m_iframeScrollOffset.y();
+ setScrollOffset(IntPoint(newX, newY));
+ return true;
+}
+
+void IFrameContentLayerAndroid::getScrollRect(SkIRect* out) const
+{
+ const SkPoint& pos = getPosition();
+ out->fLeft = m_scrollLimits.fLeft - pos.fX + m_iframeScrollOffset.x();
+ out->fTop = m_scrollLimits.fTop - pos.fY + m_iframeScrollOffset.y();
+
+ out->fRight = getSize().width() - m_scrollLimits.width();
+ out->fBottom = getSize().height() - m_scrollLimits.height();
+}
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/android/IFrameContentLayerAndroid.h b/Source/WebCore/platform/graphics/android/IFrameContentLayerAndroid.h
new file mode 100644
index 0000000..64b2d06
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/IFrameContentLayerAndroid.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef IFrameContentLayerAndroid_h
+#define IFrameContentLayerAndroid_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "ScrollableLayerAndroid.h"
+
+namespace WebCore {
+
+class IFrameContentLayerAndroid : public ScrollableLayerAndroid {
+
+public:
+ IFrameContentLayerAndroid(RenderLayer* owner)
+ : ScrollableLayerAndroid(owner) {}
+ IFrameContentLayerAndroid(const ScrollableLayerAndroid& layer)
+ : ScrollableLayerAndroid(layer) {}
+ IFrameContentLayerAndroid(const LayerAndroid& layer)
+ : ScrollableLayerAndroid(layer) {}
+ IFrameContentLayerAndroid(const IFrameContentLayerAndroid& layer)
+ : ScrollableLayerAndroid(layer)
+ , m_iframeScrollOffset(layer.m_iframeScrollOffset) {}
+
+ virtual ~IFrameContentLayerAndroid() {};
+
+ // isIFrame() return true for compatibility reason (see ViewStateSerializer)
+ virtual bool isIFrame() const { return true; }
+ virtual bool isIFrameContent() const { return true; }
+
+ virtual LayerAndroid* copy() const { return new IFrameContentLayerAndroid(*this); }
+ virtual SubclassType subclassType() { return LayerAndroid::IFrameContentLayer; }
+
+ // Scrolls to the given position in the layer.
+ // Returns whether or not any scrolling was required.
+ virtual bool scrollTo(int x, int y);
+
+ // Fills the rect with the current scroll offset and the maximum scroll offset.
+ // fLeft = scrollX
+ // fTop = scrollY
+ // fRight = maxScrollX
+ // fBottom = maxScrollY
+ virtual void getScrollRect(SkIRect*) const;
+
+ void setIFrameScrollOffset(IntPoint offset) { m_iframeScrollOffset = offset; }
+
+private:
+ IntPoint m_iframeScrollOffset;
+};
+
+}
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif // IFrameContentLayerAndroid_h
diff --git a/Source/WebCore/platform/graphics/android/IFrameLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/IFrameLayerAndroid.cpp
new file mode 100644
index 0000000..dfff91b
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/IFrameLayerAndroid.cpp
@@ -0,0 +1,42 @@
+#include "config.h"
+#include "IFrameLayerAndroid.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include <cutils/log.h>
+#include <wtf/CurrentTime.h>
+#include <wtf/text/CString.h>
+
+#include "DumpLayer.h"
+
+#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "IFrameLayerAndroid", __VA_ARGS__)
+
+namespace WebCore {
+
+IFrameLayerAndroid* IFrameLayerAndroid::updatePosition(SkRect viewport,
+ IFrameLayerAndroid* parentIframeLayer)
+{
+ // As we are an iframe, accumulate the offset from the parent with
+ // the current position, and change the parent pointer.
+
+ // If this is the top level, take the current position
+ SkPoint parentOffset;
+ parentOffset.set(0,0);
+ if (parentIframeLayer)
+ parentOffset = parentIframeLayer->getPosition();
+
+ SkPoint offset = parentOffset + getPosition();
+ m_iframeOffset = IntPoint(offset.fX, offset.fY);
+
+ return this;
+}
+
+void IFrameLayerAndroid::dumpLayer(FILE* file, int indentLevel) const
+{
+ writeIntVal(file, indentLevel + 1, "m_isIframe", true);
+ writeIntPoint(file, indentLevel + 1, "m_iframeOffset", m_iframeOffset);
+}
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/android/IFrameLayerAndroid.h b/Source/WebCore/platform/graphics/android/IFrameLayerAndroid.h
new file mode 100644
index 0000000..e12188a
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/IFrameLayerAndroid.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef IFrameLayerAndroid_h
+#define IFrameLayerAndroid_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "LayerAndroid.h"
+
+namespace WebCore {
+
+class IFrameLayerAndroid : public LayerAndroid {
+
+public:
+ IFrameLayerAndroid(RenderLayer* owner)
+ : LayerAndroid(owner) {}
+ IFrameLayerAndroid(const LayerAndroid& layer)
+ : LayerAndroid(layer) {}
+ IFrameLayerAndroid(const IFrameLayerAndroid& layer)
+ : LayerAndroid(layer)
+ , m_iframeOffset(layer.m_iframeOffset) {}
+
+ virtual ~IFrameLayerAndroid() {};
+
+ virtual bool isIFrame() const { return true; }
+
+ virtual LayerAndroid* copy() const { return new IFrameLayerAndroid(*this); }
+ virtual SubclassType subclassType() { return LayerAndroid::IFrameLayer; }
+
+ virtual IFrameLayerAndroid* updatePosition(SkRect viewport,
+ IFrameLayerAndroid* parentIframeLayer);
+
+ virtual void dumpLayer(FILE*, int indentLevel) const;
+
+ const IntPoint& iframeOffset() const { return m_iframeOffset; }
+
+private:
+ IntPoint m_iframeOffset;
+};
+
+}
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif // IFrameLayerAndroid_h
diff --git a/Source/WebCore/platform/graphics/android/Layer.cpp b/Source/WebCore/platform/graphics/android/Layer.cpp
index f58d648..7453a24 100644
--- a/Source/WebCore/platform/graphics/android/Layer.cpp
+++ b/Source/WebCore/platform/graphics/android/Layer.cpp
@@ -158,10 +158,6 @@ void Layer::localToAncestor(const Layer* ancestor, SkMatrix* matrix) const {
///////////////////////////////////////////////////////////////////////////////
-void Layer::onDraw(SkCanvas*, SkScalar opacity, android::DrawExtra* extra) {
-// SkDebugf("----- no onDraw for %p\n", this);
-}
-
#include "SkString.h"
void Layer::draw(SkCanvas* canvas, android::DrawExtra* extra, SkScalar opacity) {
@@ -193,7 +189,7 @@ void Layer::draw(SkCanvas* canvas, android::DrawExtra* extra, SkScalar opacity)
canvas->concat(tmp);
}
- onDraw(canvas, opacity, extra);
+ onDraw(canvas, opacity, extra, FlattenedLayers);
#ifdef DEBUG_DRAW_LAYER_BOUNDS
{
diff --git a/Source/WebCore/platform/graphics/android/Layer.h b/Source/WebCore/platform/graphics/android/Layer.h
index 9165307..e872278 100644
--- a/Source/WebCore/platform/graphics/android/Layer.h
+++ b/Source/WebCore/platform/graphics/android/Layer.h
@@ -151,8 +151,9 @@ public:
virtual bool contentIsScrollable() const { return false; }
+ typedef enum { MergedLayers, UnmergedLayers, FlattenedLayers } PaintStyle;
protected:
- virtual void onDraw(SkCanvas*, SkScalar opacity, android::DrawExtra* extra);
+ virtual void onDraw(SkCanvas*, SkScalar opacity, android::DrawExtra* extra, PaintStyle style) {}
bool m_hasOverflowChildren;
diff --git a/Source/WebCore/platform/graphics/android/LayerAndroid.cpp b/Source/WebCore/platform/graphics/android/LayerAndroid.cpp
index 67d3dd3..f101208 100644
--- a/Source/WebCore/platform/graphics/android/LayerAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/LayerAndroid.cpp
@@ -6,6 +6,8 @@
#include "AndroidAnimation.h"
#include "ClassTracker.h"
#include "DrawExtra.h"
+#include "DumpLayer.h"
+#include "FixedPositioning.h"
#include "GLUtils.h"
#include "ImagesManager.h"
#include "InspectorCanvas.h"
@@ -24,6 +26,12 @@
#define LAYER_DEBUG // Add diagonals for debugging
#undef LAYER_DEBUG
+#define DISABLE_LAYER_MERGE
+#undef DISABLE_LAYER_MERGE
+
+#define LAYER_GROUPING_DEBUG
+#undef LAYER_GROUPING_DEBUG
+
#include <cutils/log.h>
#include <wtf/text/CString.h>
#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "LayerAndroid", __VA_ARGS__)
@@ -59,12 +67,11 @@ private:
LayerAndroid::LayerAndroid(RenderLayer* owner) : Layer(),
m_haveClip(false),
- m_isFixed(false),
- m_isIframe(false),
m_backfaceVisibility(true),
m_visible(true),
m_preserves3D(false),
m_anchorPointZ(0),
+ m_fixedPosition(0),
m_recordingPicture(0),
m_zValue(0),
m_uniqueId(++gUniqueId),
@@ -75,12 +82,12 @@ LayerAndroid::LayerAndroid(RenderLayer* owner) : Layer(),
m_owningLayer(owner),
m_type(LayerAndroid::WebCoreLayer),
m_hasText(true),
+ m_intrinsicallyComposited(true),
m_layerGroup(0)
{
m_backgroundColor = 0;
m_preserves3D = false;
- m_iframeOffset.set(0,0);
m_dirtyRegion.setEmpty();
#ifdef DEBUG_COUNT
ClassTracker::instance()->increment("LayerAndroid");
@@ -90,42 +97,36 @@ LayerAndroid::LayerAndroid(RenderLayer* owner) : Layer(),
LayerAndroid::LayerAndroid(const LayerAndroid& layer) : Layer(layer),
m_haveClip(layer.m_haveClip),
- m_isIframe(layer.m_isIframe),
+ m_fixedPosition(0),
m_zValue(layer.m_zValue),
m_uniqueId(layer.m_uniqueId),
m_owningLayer(layer.m_owningLayer),
m_type(LayerAndroid::UILayer),
- m_hasText(true),
+ m_hasText(layer.m_hasText),
+ m_intrinsicallyComposited(layer.m_intrinsicallyComposited),
m_layerGroup(0)
{
- m_isFixed = layer.m_isFixed;
m_imageCRC = layer.m_imageCRC;
if (m_imageCRC)
ImagesManager::instance()->retainImage(m_imageCRC);
- m_renderLayerPos = layer.m_renderLayerPos;
m_transform = layer.m_transform;
m_backfaceVisibility = layer.m_backfaceVisibility;
m_visible = layer.m_visible;
m_backgroundColor = layer.m_backgroundColor;
- m_fixedLeft = layer.m_fixedLeft;
- m_fixedTop = layer.m_fixedTop;
- m_fixedRight = layer.m_fixedRight;
- m_fixedBottom = layer.m_fixedBottom;
- m_fixedMarginLeft = layer.m_fixedMarginLeft;
- m_fixedMarginTop = layer.m_fixedMarginTop;
- m_fixedMarginRight = layer.m_fixedMarginRight;
- m_fixedMarginBottom = layer.m_fixedMarginBottom;
- m_fixedRect = layer.m_fixedRect;
- m_iframeOffset = layer.m_iframeOffset;
m_offset = layer.m_offset;
- m_iframeScrollOffset = layer.m_iframeScrollOffset;
m_recordingPicture = layer.m_recordingPicture;
SkSafeRef(m_recordingPicture);
m_preserves3D = layer.m_preserves3D;
m_anchorPointZ = layer.m_anchorPointZ;
+
+ if (layer.m_fixedPosition) {
+ m_fixedPosition = new FixedPositioning(this, *layer.m_fixedPosition);
+ Layer::setShouldInheritFromRootTransform(true);
+ }
+
m_drawTransform = layer.m_drawTransform;
m_childrenTransform = layer.m_childrenTransform;
m_pictureUsed = layer.m_pictureUsed;
@@ -141,8 +142,6 @@ LayerAndroid::LayerAndroid(const LayerAndroid& layer) : Layer(layer),
m_animations.add(it->first, it->second);
}
- m_hasText = layer.m_hasText;
-
#ifdef DEBUG_COUNT
ClassTracker::instance()->increment("LayerAndroid - recopy (UI)");
ClassTracker::instance()->add(this);
@@ -174,8 +173,7 @@ void LayerAndroid::checkForPictureOptimizations()
LayerAndroid::LayerAndroid(SkPicture* picture) : Layer(),
m_haveClip(false),
- m_isFixed(false),
- m_isIframe(false),
+ m_fixedPosition(0),
m_recordingPicture(picture),
m_zValue(0),
m_uniqueId(++gUniqueId),
@@ -185,11 +183,11 @@ LayerAndroid::LayerAndroid(SkPicture* picture) : Layer(),
m_owningLayer(0),
m_type(LayerAndroid::NavCacheLayer),
m_hasText(true),
+ m_intrinsicallyComposited(true),
m_layerGroup(0)
{
m_backgroundColor = 0;
SkSafeRef(m_recordingPicture);
- m_iframeOffset.set(0,0);
m_dirtyRegion.setEmpty();
#ifdef DEBUG_COUNT
ClassTracker::instance()->increment("LayerAndroid - from picture");
@@ -201,6 +199,8 @@ LayerAndroid::~LayerAndroid()
{
if (m_imageCRC)
ImagesManager::instance()->releaseImage(m_imageCRC);
+ if (m_fixedPosition)
+ delete m_fixedPosition;
SkSafeUnref(m_recordingPicture);
// Don't unref m_layerGroup, owned by BaseLayerAndroid
@@ -389,74 +389,32 @@ void LayerAndroid::clipInner(SkTDArray<SkRect>* region,
getChild(i)->clipInner(region, m_haveClip ? localBounds : local);
}
-bool LayerAndroid::updateFixedLayersPositions(SkRect viewport, LayerAndroid* parentIframeLayer)
+IFrameLayerAndroid* LayerAndroid::updatePosition(SkRect viewport,
+ IFrameLayerAndroid* parentIframeLayer)
+{
+ // subclasses can implement this virtual function to modify their position
+ if (m_fixedPosition)
+ return m_fixedPosition->updatePosition(viewport, parentIframeLayer);
+ return parentIframeLayer;
+}
+
+void LayerAndroid::updateLayerPositions(SkRect viewport, IFrameLayerAndroid* parentIframeLayer)
{
- bool hasFixedElements = false;
XLOG("updating fixed positions, using viewport %fx%f - %fx%f",
viewport.fLeft, viewport.fTop,
viewport.width(), viewport.height());
- // If this is an iframe, accumulate the offset from the parent with
- // current position, and change the parent pointer.
- if (m_isIframe) {
- // If this is the top level, take the current position
- SkPoint parentOffset;
- parentOffset.set(0,0);
- if (parentIframeLayer)
- parentOffset = parentIframeLayer->getPosition();
-
- m_iframeOffset = parentOffset + getPosition();
-
- parentIframeLayer = this;
- }
- if (m_isFixed) {
- hasFixedElements = true;
- // So if this is a fixed layer inside a iframe, use the iframe offset
- // and the iframe's size as the viewport and pass to the children
- if (parentIframeLayer) {
- viewport = SkRect::MakeXYWH(parentIframeLayer->m_iframeOffset.fX,
- parentIframeLayer->m_iframeOffset.fY,
- parentIframeLayer->getSize().width(),
- parentIframeLayer->getSize().height());
- }
- float w = viewport.width();
- float h = viewport.height();
- float dx = viewport.fLeft;
- float dy = viewport.fTop;
- float x = dx;
- float y = dy;
-
- // It turns out that when it is 'auto', we should use the webkit value
- // from the original render layer's X,Y, that will take care of alignment
- // with the parent's layer and fix Margin etc.
- if (!(m_fixedLeft.defined() || m_fixedRight.defined()))
- x += m_renderLayerPos.x();
- else if (m_fixedLeft.defined() || !m_fixedRight.defined())
- x += m_fixedMarginLeft.calcFloatValue(w) + m_fixedLeft.calcFloatValue(w) - m_fixedRect.fLeft;
- else
- x += w - m_fixedMarginRight.calcFloatValue(w) - m_fixedRight.calcFloatValue(w) - m_fixedRect.fRight;
-
- if (!(m_fixedTop.defined() || m_fixedBottom.defined()))
- y += m_renderLayerPos.y();
- else if (m_fixedTop.defined() || !m_fixedBottom.defined())
- y += m_fixedMarginTop.calcFloatValue(h) + m_fixedTop.calcFloatValue(h) - m_fixedRect.fTop;
- else
- y += h - m_fixedMarginBottom.calcFloatValue(h) - m_fixedBottom.calcFloatValue(h) - m_fixedRect.fBottom;
-
- this->setPosition(x, y);
- }
+ IFrameLayerAndroid* iframeLayer = updatePosition(viewport, parentIframeLayer);
int count = this->countChildren();
for (int i = 0; i < count; i++)
- hasFixedElements |= this->getChild(i)->updateFixedLayersPositions(viewport, parentIframeLayer);
-
- return hasFixedElements;
+ this->getChild(i)->updateLayerPositions(viewport, iframeLayer);
}
void LayerAndroid::updatePositions()
{
// apply the viewport to us
- if (!m_isFixed) {
+ if (!isFixed()) {
// turn our fields into a matrix.
//
// FIXME: this should happen in the caller, and we should remove these
@@ -482,7 +440,7 @@ void LayerAndroid::updateGLPositionsAndScale(const TransformationMatrix& parentM
float originX = anchorPoint.x() * layerSize.width();
float originY = anchorPoint.y() * layerSize.height();
TransformationMatrix localMatrix;
- if (!m_isFixed)
+ if (!isFixed())
localMatrix = parentMatrix;
localMatrix.translate3d(originX + position.x(),
originY + position.y(),
@@ -635,9 +593,9 @@ void LayerAndroid::showLayer(int indent)
IntRect visible = visibleArea();
IntRect clip(m_clippingRect.x(), m_clippingRect.y(),
m_clippingRect.width(), m_clippingRect.height());
- XLOGC("%s [%d:0x%x] - %s %s - area (%d, %d, %d, %d) - visible (%d, %d, %d, %d) "
+ XLOGC("%s %s (%d) [%d:0x%x] - %s %s - area (%d, %d, %d, %d) - visible (%d, %d, %d, %d) "
"clip (%d, %d, %d, %d) %s %s prepareContext(%x), pic w: %d h: %d",
- spaces, uniqueId(), m_owningLayer,
+ spaces, subclassName().latin1().data(), subclassType(), uniqueId(), m_owningLayer,
needsTexture() ? "needs a texture" : "no texture",
m_imageCRC ? "has an image" : "no image",
tr.x(), tr.y(), tr.width(), tr.height(),
@@ -654,22 +612,6 @@ void LayerAndroid::showLayer(int indent)
this->getChild(i)->showLayer(indent + 1);
}
-void LayerAndroid::setIsPainting(Layer* drawingTree)
-{
- XLOG("setting layer %p as painting, needs texture %d, drawing tree %p",
- this, needsTexture(), drawingTree);
- int count = this->countChildren();
- for (int i = 0; i < count; i++)
- this->getChild(i)->setIsPainting(drawingTree);
-
-
- LayerAndroid* drawingLayer = 0;
- if (drawingTree)
- drawingLayer = static_cast<LayerAndroid*>(drawingTree)->findById(uniqueId());
-
- obtainTextureForPainting(drawingLayer);
-}
-
void LayerAndroid::mergeInvalsInto(LayerAndroid* replacementTree)
{
int count = this->countChildren();
@@ -725,49 +667,90 @@ bool LayerAndroid::updateWithLayer(LayerAndroid* layer)
return false;
}
-void LayerAndroid::obtainTextureForPainting(LayerAndroid* drawingLayer)
+static inline bool compareLayerZ(const LayerAndroid* a, const LayerAndroid* b)
{
- if (!needsTexture())
- return;
-
- // layer group init'd with previous drawing layer
- m_layerGroup->initializeGroup(this, m_dirtyRegion, drawingLayer);
- m_dirtyRegion.setEmpty();
+ return a->zValue() > b->zValue();
}
-
-static inline bool compareLayerZ(const LayerAndroid* a, const LayerAndroid* b)
+bool LayerAndroid::canJoinGroup(LayerGroup* group)
{
- return a->zValue() > b->zValue();
+#if DISABLE_LAYER_MERGE
+ return false;
+#else
+ // returns true if the layer can be merged onto the layergroup
+ if (!group)
+ return false;
+
+ LayerAndroid* lastLayer = group->getFirstLayer();
+
+ // isolate non-tiled layers
+ // TODO: remove this check so that multiple tiled layers with a invisible
+ // one inbetween can be merged
+ if (!needsTexture() || !lastLayer->needsTexture())
+ return false;
+
+ // isolate clipped layers
+ // TODO: paint correctly with clip when merged
+ if (m_haveClip || lastLayer->m_haveClip)
+ return false;
+
+ // isolate intrinsically composited layers
+ if (m_intrinsicallyComposited || lastLayer->m_intrinsicallyComposited)
+ return false;
+
+ // TODO: investigate potential for combining transformed layers
+ if (!m_drawTransform.isIdentityOrTranslation()
+ || !lastLayer->m_drawTransform.isIdentityOrTranslation())
+ return false;
+
+ // currently, we don't group zoomable with non-zoomable layers (unless the
+ // group or the layer doesn't need a texture)
+ if (group->needsTexture() && needsTexture() && m_hasText != group->hasText())
+ return false;
+
+ // TODO: compare other layer properties - fixed? overscroll? transformed?
+ return true;
+#endif
}
-void LayerAndroid::assignGroups(Vector<LayerGroup*>* allGroups)
+void LayerAndroid::assignGroups(LayerMergeState* mergeState)
{
- // recurse through layers in draw order
- // if a layer needs isolation (e.g. has animation, is fixed, overflow:scroll)
- // create new layer group on the stack
+ // recurse through layers in draw order, and merge layers when able
- bool needsIsolation = false;
- LayerGroup* currentLayerGroup = 0;
- if (!allGroups->isEmpty())
- currentLayerGroup = allGroups->at(0);
+ bool needNewGroup = !mergeState->currentLayerGroup
+ || mergeState->nonMergeNestedLevel > 0
+ || !canJoinGroup(mergeState->currentLayerGroup);
- // TODO: compare layer with group on top of stack - fixed? overscroll? transformed?
- needsIsolation = m_isFixed || (m_animations.size() != 0);
+ if (needNewGroup) {
+ mergeState->currentLayerGroup = new LayerGroup();
+ mergeState->groupList->append(mergeState->currentLayerGroup);
+ }
- if (!currentLayerGroup || needsIsolation || true) {
- currentLayerGroup = new LayerGroup();
- allGroups->append(currentLayerGroup);
+#ifdef LAYER_GROUPING_DEBUG
+ XLOGC("%*slayer %p(%d) rl %p %s group %p, fixed %d, anim %d, intCom %d, haveClip %d scroll %d",
+ 4*mergeState->depth, "", this, m_uniqueId, m_owningLayer,
+ needNewGroup ? "NEW" : "joins", mergeState->currentLayerGroup,
+ m_isFixed, m_animations.size() != 0,
+ m_intrinsicallyComposited,
+ m_haveClip,
+ contentIsScrollable());
+#endif
+
+ mergeState->currentLayerGroup->addLayer(this, m_drawTransform);
+ m_layerGroup = mergeState->currentLayerGroup;
+
+ if (m_haveClip || contentIsScrollable() || isFixed()) {
+ // disable layer merging within the children of these layer types
+ mergeState->nonMergeNestedLevel++;
}
- currentLayerGroup->addLayer(this);
- m_layerGroup = currentLayerGroup;
// pass the layergroup through children in drawing order, so that they may
// attach themselves (and paint on it) if possible, or ignore it and create
// a new one if not
int count = this->countChildren();
if (count > 0) {
+ mergeState->depth++;
Vector <LayerAndroid*> sublayers;
for (int i = 0; i < count; i++)
sublayers.append(getChild(i));
@@ -775,7 +758,16 @@ void LayerAndroid::assignGroups(Vector<LayerGroup*>* allGroups)
// sort for the transparency
std::stable_sort(sublayers.begin(), sublayers.end(), compareLayerZ);
for (int i = 0; i < count; i++)
- sublayers[i]->assignGroups(allGroups);
+ sublayers[i]->assignGroups(mergeState);
+ mergeState->depth--;
+ }
+
+ if (m_haveClip || contentIsScrollable() || isFixed()) {
+ // re-enable joining
+ mergeState->nonMergeNestedLevel--;
+
+ // disallow layers painting after to join with this group
+ mergeState->currentLayerGroup = 0;
}
}
@@ -824,7 +816,7 @@ IntRect LayerAndroid::visibleArea()
return rect;
}
-bool LayerAndroid::drawCanvas(SkCanvas* canvas)
+bool LayerAndroid::drawCanvas(SkCanvas* canvas, bool drawChildren, PaintStyle style)
{
if (!m_visible)
return false;
@@ -843,11 +835,14 @@ bool LayerAndroid::drawCanvas(SkCanvas* canvas)
SkMatrix canvasMatrix = canvas->getTotalMatrix();
matrix.postConcat(canvasMatrix);
canvas->setMatrix(matrix);
- onDraw(canvas, m_drawOpacity, 0);
+ onDraw(canvas, m_drawOpacity, 0, style);
}
+ if (!drawChildren)
+ return false;
+
// When the layer is dirty, the UI thread should be notified to redraw.
- askScreenUpdate |= drawChildrenCanvas(canvas);
+ askScreenUpdate |= drawChildrenCanvas(canvas, style);
m_atomicSync.lock();
if (askScreenUpdate || m_hasRunningAnimations || m_drawTransform.hasPerspective())
addDirtyArea();
@@ -878,7 +873,7 @@ bool LayerAndroid::drawGL(bool layerTilesDisabled)
return askScreenUpdate;
}
-bool LayerAndroid::drawChildrenCanvas(SkCanvas* canvas)
+bool LayerAndroid::drawChildrenCanvas(SkCanvas* canvas, PaintStyle style)
{
bool askScreenUpdate = false;
int count = this->countChildren();
@@ -891,14 +886,14 @@ bool LayerAndroid::drawChildrenCanvas(SkCanvas* canvas)
std::stable_sort(sublayers.begin(), sublayers.end(), compareLayerZ);
for (int i = 0; i < count; i++) {
LayerAndroid* layer = sublayers[i];
- askScreenUpdate |= layer->drawCanvas(canvas);
+ askScreenUpdate |= layer->drawCanvas(canvas, true, style);
}
}
return askScreenUpdate;
}
-void LayerAndroid::contentDraw(SkCanvas* canvas)
+void LayerAndroid::contentDraw(SkCanvas* canvas, PaintStyle style)
{
if (m_recordingPicture)
canvas->drawPicture(*m_recordingPicture);
@@ -907,24 +902,29 @@ void LayerAndroid::contentDraw(SkCanvas* canvas)
float w = getSize().width();
float h = getSize().height();
SkPaint paint;
- paint.setARGB(128, 255, 0, 0);
+
+ if (style == MergedLayers)
+ paint.setARGB(255, 255, 255, 0);
+ else if (style == UnmergedLayers)
+ paint.setARGB(255, 255, 0, 0);
+ else if (style == FlattenedLayers)
+ paint.setARGB(255, 255, 0, 255);
+
canvas->drawLine(0, 0, w, h, paint);
canvas->drawLine(0, h, w, 0, paint);
- paint.setARGB(128, 0, 255, 0);
+
canvas->drawLine(0, 0, 0, h, paint);
canvas->drawLine(0, h, w, h, paint);
canvas->drawLine(w, h, w, 0, paint);
canvas->drawLine(w, 0, 0, 0, paint);
-
- if (m_isFixed) {
- SkPaint paint;
- paint.setARGB(80, 255, 0, 0);
- canvas->drawRect(m_fixedRect, paint);
- }
}
+
+ if (m_fixedPosition)
+ return m_fixedPosition->contentDraw(canvas, style);
}
-void LayerAndroid::onDraw(SkCanvas* canvas, SkScalar opacity, android::DrawExtra* extra)
+void LayerAndroid::onDraw(SkCanvas* canvas, SkScalar opacity,
+ android::DrawExtra* extra, PaintStyle style)
{
if (m_haveClip) {
SkRect r;
@@ -953,7 +953,7 @@ void LayerAndroid::onDraw(SkCanvas* canvas, SkScalar opacity, android::DrawExtra
}
ImagesManager::instance()->releaseImage(m_imageCRC);
}
- contentDraw(canvas);
+ contentDraw(canvas, style);
if (extra)
extra->draw(canvas, this);
}
@@ -981,6 +981,12 @@ bool LayerAndroid::prepareContext(bool force)
return m_recordingPicture;
}
+void LayerAndroid::setFixedPosition(FixedPositioning* position) {
+ if (m_fixedPosition && m_fixedPosition != position)
+ delete m_fixedPosition;
+ m_fixedPosition = position;
+}
+
SkRect LayerAndroid::subtractLayers(const SkRect& visibleRect) const
{
SkRect result;
@@ -1018,116 +1024,12 @@ SkRect LayerAndroid::subtractLayers(const SkRect& visibleRect) const
return result;
}
-// Debug tools : dump the layers tree in a file.
-// The format is simple:
-// properties have the form: key = value;
-// all statements are finished with a semi-colon.
-// value can be:
-// - int
-// - float
-// - array of elements
-// - composed type
-// a composed type enclose properties in { and }
-// an array enclose composed types in { }, separated with a comma.
-// exemple:
-// {
-// x = 3;
-// y = 4;
-// value = {
-// x = 3;
-// y = 4;
-// };
-// anarray = [
-// { x = 3; },
-// { y = 4; }
-// ];
-// }
-
-void lwrite(FILE* file, const char* str)
-{
- fwrite(str, sizeof(char), strlen(str), file);
-}
-
-void writeIndent(FILE* file, int indentLevel)
-{
- if (indentLevel)
- fprintf(file, "%*s", indentLevel*2, " ");
-}
-
-void writeln(FILE* file, int indentLevel, const char* str)
-{
- writeIndent(file, indentLevel);
- lwrite(file, str);
- lwrite(file, "\n");
-}
-
-void writeIntVal(FILE* file, int indentLevel, const char* str, int value)
-{
- writeIndent(file, indentLevel);
- fprintf(file, "%s = %d;\n", str, value);
-}
-
-void writeHexVal(FILE* file, int indentLevel, const char* str, int value)
+void LayerAndroid::dumpLayer(FILE* file, int indentLevel) const
{
- writeIndent(file, indentLevel);
- fprintf(file, "%s = %x;\n", str, value);
-}
-
-void writeFloatVal(FILE* file, int indentLevel, const char* str, float value)
-{
- writeIndent(file, indentLevel);
- fprintf(file, "%s = %.3f;\n", str, value);
-}
-
-void writePoint(FILE* file, int indentLevel, const char* str, SkPoint point)
-{
- writeIndent(file, indentLevel);
- fprintf(file, "%s = { x = %.3f; y = %.3f; };\n", str, point.fX, point.fY);
-}
-
-void writeSize(FILE* file, int indentLevel, const char* str, SkSize size)
-{
- writeIndent(file, indentLevel);
- fprintf(file, "%s = { w = %.3f; h = %.3f; };\n", str, size.width(), size.height());
-}
-
-void writeRect(FILE* file, int indentLevel, const char* str, SkRect rect)
-{
- writeIndent(file, indentLevel);
- fprintf(file, "%s = { x = %.3f; y = %.3f; w = %.3f; h = %.3f; };\n",
- str, rect.fLeft, rect.fTop, rect.width(), rect.height());
-}
-
-void writeLength(FILE* file, int indentLevel, const char* str, SkLength length)
-{
- if (!length.defined())
- return;
- writeIndent(file, indentLevel);
- fprintf(file, "%s = { type = %d; value = %.2f; };\n", str, length.type, length.value);
-}
-
-void writeMatrix(FILE* file, int indentLevel, const char* str, const TransformationMatrix& matrix)
-{
- writeIndent(file, indentLevel);
- fprintf(file, "%s = { (%.2f,%.2f,%.2f,%.2f),(%.2f,%.2f,%.2f,%.2f),"
- "(%.2f,%.2f,%.2f,%.2f),(%.2f,%.2f,%.2f,%.2f) };\n",
- str,
- matrix.m11(), matrix.m12(), matrix.m13(), matrix.m14(),
- matrix.m21(), matrix.m22(), matrix.m23(), matrix.m24(),
- matrix.m31(), matrix.m32(), matrix.m33(), matrix.m34(),
- matrix.m41(), matrix.m42(), matrix.m43(), matrix.m44());
-}
-
-void LayerAndroid::dumpLayers(FILE* file, int indentLevel) const
-{
- writeln(file, indentLevel, "{");
-
writeHexVal(file, indentLevel + 1, "layer", (int)this);
writeIntVal(file, indentLevel + 1, "layerId", m_uniqueId);
writeIntVal(file, indentLevel + 1, "haveClip", m_haveClip);
- writeIntVal(file, indentLevel + 1, "isFixed", m_isFixed);
- writeIntVal(file, indentLevel + 1, "m_isIframe", m_isIframe);
- writePoint(file, indentLevel + 1, "m_iframeOffset", m_iframeOffset);
+ writeIntVal(file, indentLevel + 1, "isFixed", isFixed());
writeFloatVal(file, indentLevel + 1, "opacity", getOpacity());
writeSize(file, indentLevel + 1, "size", getSize());
@@ -1138,23 +1040,21 @@ void LayerAndroid::dumpLayers(FILE* file, int indentLevel) const
writeMatrix(file, indentLevel + 1, "transformMatrix", m_transform);
writeRect(file, indentLevel + 1, "clippingRect", SkRect(m_clippingRect));
- if (m_isFixed) {
- writeLength(file, indentLevel + 1, "fixedLeft", m_fixedLeft);
- writeLength(file, indentLevel + 1, "fixedTop", m_fixedTop);
- writeLength(file, indentLevel + 1, "fixedRight", m_fixedRight);
- writeLength(file, indentLevel + 1, "fixedBottom", m_fixedBottom);
- writeLength(file, indentLevel + 1, "fixedMarginLeft", m_fixedMarginLeft);
- writeLength(file, indentLevel + 1, "fixedMarginTop", m_fixedMarginTop);
- writeLength(file, indentLevel + 1, "fixedMarginRight", m_fixedMarginRight);
- writeLength(file, indentLevel + 1, "fixedMarginBottom", m_fixedMarginBottom);
- writeRect(file, indentLevel + 1, "fixedRect", m_fixedRect);
- }
-
if (m_recordingPicture) {
writeIntVal(file, indentLevel + 1, "m_recordingPicture.width", m_recordingPicture->width());
writeIntVal(file, indentLevel + 1, "m_recordingPicture.height", m_recordingPicture->height());
}
+ if (m_fixedPosition)
+ return m_fixedPosition->dumpLayer(file, indentLevel);
+}
+
+void LayerAndroid::dumpLayers(FILE* file, int indentLevel) const
+{
+ writeln(file, indentLevel, "{");
+
+ dumpLayer(file, indentLevel);
+
if (countChildren()) {
writeln(file, indentLevel + 1, "children = [");
for (int i = 0; i < countChildren(); i++) {
diff --git a/Source/WebCore/platform/graphics/android/LayerAndroid.h b/Source/WebCore/platform/graphics/android/LayerAndroid.h
index 86d27bc..7f5d5e2 100644
--- a/Source/WebCore/platform/graphics/android/LayerAndroid.h
+++ b/Source/WebCore/platform/graphics/android/LayerAndroid.h
@@ -55,45 +55,20 @@ class ImageTexture;
namespace android {
class DrawExtra;
void serializeLayer(WebCore::LayerAndroid* layer, SkWStream* stream);
-WebCore::LayerAndroid* deserializeLayer(SkStream* stream);
+WebCore::LayerAndroid* deserializeLayer(int version, SkStream* stream);
void cleanupImageRefs(WebCore::LayerAndroid* layer);
}
using namespace android;
-struct SkLength {
- enum SkLengthType { Undefined, Auto, Relative, Percent, Fixed, Static, Intrinsic, MinIntrinsic };
- SkLengthType type;
- SkScalar value;
- SkLength()
- {
- type = Undefined;
- value = 0;
- }
- bool defined() const
- {
- if (type == Undefined)
- return false;
- return true;
- }
- float calcFloatValue(float max) const
- {
- switch (type) {
- case Percent:
- return (max * value) / 100.0f;
- case Fixed:
- return value;
- default:
- return value;
- }
- }
-};
-
namespace WebCore {
class AndroidAnimation;
class BaseTileTexture;
+class FixedPositioning;
class GLWebViewState;
+class IFrameLayerAndroid;
+class LayerMergeState;
class RenderLayer;
class TiledPage;
class PaintedSurface;
@@ -115,7 +90,24 @@ public:
class TEST_EXPORT LayerAndroid : public Layer {
public:
- enum LayerType { UndefinedLayer, WebCoreLayer, UILayer, NavCacheLayer };
+ typedef enum { UndefinedLayer, WebCoreLayer, UILayer, NavCacheLayer } LayerType;
+ typedef enum { StandardLayer, ScrollableLayer,
+ IFrameLayer, IFrameContentLayer } SubclassType;
+
+ String subclassName()
+ {
+ switch (subclassType()) {
+ case LayerAndroid::StandardLayer:
+ return "StandardLayer";
+ case LayerAndroid::ScrollableLayer:
+ return "ScrollableLayer";
+ case LayerAndroid::IFrameLayer:
+ return "IFrameLayer";
+ case LayerAndroid::IFrameContentLayer:
+ return "IFrameContentLayer";
+ }
+ return "Undefined";
+ }
LayerAndroid(RenderLayer* owner);
LayerAndroid(const LayerAndroid& layer);
@@ -148,8 +140,8 @@ public:
float getScale() { return m_scale; }
virtual bool drawGL(bool layerTilesDisabled);
- virtual bool drawCanvas(SkCanvas*);
- bool drawChildrenCanvas(SkCanvas*);
+ virtual bool drawCanvas(SkCanvas* canvas, bool drawChildren, PaintStyle style);
+ bool drawChildrenCanvas(SkCanvas* canvas, PaintStyle style);
void updateGLPositionsAndScale(const TransformationMatrix& parentMatrix,
const FloatRect& clip, float opacity, float scale);
@@ -168,34 +160,8 @@ public:
void setDrawClip(const FloatRect& rect) { m_clippingRect = rect; }
const FloatRect& drawClip() { return m_clippingRect; }
- void setFixedPosition(SkLength left, // CSS left property
- SkLength top, // CSS top property
- SkLength right, // CSS right property
- SkLength bottom, // CSS bottom property
- SkLength marginLeft, // CSS margin-left property
- SkLength marginTop, // CSS margin-top property
- SkLength marginRight, // CSS margin-right property
- SkLength marginBottom, // CSS margin-bottom property
- const IntPoint& renderLayerPos, // For undefined fixed position
- SkRect viewRect) { // view rect, can be smaller than the layer's
- m_fixedLeft = left;
- m_fixedTop = top;
- m_fixedRight = right;
- m_fixedBottom = bottom;
- m_fixedMarginLeft = marginLeft;
- m_fixedMarginTop = marginTop;
- m_fixedMarginRight = marginRight;
- m_fixedMarginBottom = marginBottom;
- m_fixedRect = viewRect;
- m_isFixed = true;
- m_renderLayerPos = renderLayerPos;
- setShouldInheritFromRootTransform(true);
- }
-
const IntPoint& scrollOffset() const { return m_offset; }
- const IntPoint& iframeScrollOffset() const { return m_iframeScrollOffset; }
void setScrollOffset(IntPoint offset) { m_offset = offset; }
- void setIFrameScrollOffset(IntPoint offset) { m_iframeScrollOffset = offset; }
void setBackgroundColor(SkColor color);
void setMaskLayer(LayerAndroid*);
void setMasksToBounds(bool masksToBounds)
@@ -222,6 +188,7 @@ public:
// in global space.
SkRect subtractLayers(const SkRect&) const;
+ virtual void dumpLayer(FILE*, int indentLevel) const;
void dumpLayers(FILE*, int indentLevel) const;
void dumpToLog() const;
@@ -231,7 +198,9 @@ public:
This call is recursive, so it should be called on the root of the
hierarchy.
*/
- bool updateFixedLayersPositions(SkRect viewPort, LayerAndroid* parentIframeLayer = 0);
+ void updateLayerPositions(SkRect viewPort, IFrameLayerAndroid* parentIframeLayer = 0);
+ virtual IFrameLayerAndroid* updatePosition(SkRect viewport,
+ IFrameLayerAndroid* parentIframeLayer);
/** Call this to update the position attribute, so that later calls
like bounds() will report the corrected position.
@@ -253,7 +222,6 @@ public:
return static_cast<LayerAndroid*>(this->INHERITED::getChild(index));
}
int uniqueId() const { return m_uniqueId; }
- bool isFixed() { return m_isFixed; }
/** This sets a content image -- calling it means we will use
the image directly when drawing the layer instead of using
@@ -272,31 +240,34 @@ public:
void clearDirtyRegion();
- void contentDraw(SkCanvas*);
+ virtual void contentDraw(SkCanvas* canvas, PaintStyle style);
virtual bool isMedia() const { return false; }
virtual bool isVideo() const { return false; }
+ bool isFixed() const { return m_fixedPosition; }
+ virtual bool isIFrame() const { return false; }
+ virtual bool isIFrameContent() const { return false; }
+
+ void setFixedPosition(FixedPositioning* position);
+ FixedPositioning* fixedPosition() { return m_fixedPosition; }
RenderLayer* owningLayer() const { return m_owningLayer; }
- void setIsIframe(bool isIframe) { m_isIframe = isIframe; }
- bool isIFrame() const { return m_isIframe; }
float zValue() const { return m_zValue; }
// ViewStateSerializer friends
friend void android::serializeLayer(LayerAndroid* layer, SkWStream* stream);
- friend LayerAndroid* android::deserializeLayer(SkStream* stream);
+ friend LayerAndroid* android::deserializeLayer(int version, SkStream* stream);
friend void android::cleanupImageRefs(LayerAndroid* layer);
- void obtainTextureForPainting(LayerAndroid* drawingLayer);
-
// Update layers using another tree. Only works for basic properties
// such as the position, the transform. Return true if anything more
// complex is needed.
bool updateWithTree(LayerAndroid*);
virtual bool updateWithLayer(LayerAndroid*);
- int type() { return m_type; }
+ LayerType type() { return m_type; }
+ virtual SubclassType subclassType() { return LayerAndroid::StandardLayer; }
bool hasText() { return m_hasText; }
void checkForPictureOptimizations();
@@ -304,16 +275,18 @@ public:
void copyAnimationStartTimesRecursive(LayerAndroid* oldTree);
// rendering asset management
- void setIsPainting(Layer* drawingTree);
+ SkRegion* getInvalRegion() { return &m_dirtyRegion; }
void mergeInvalsInto(LayerAndroid* replacementTree);
- void assignGroups(Vector<LayerGroup*>* allGroups);
+ bool canJoinGroup(LayerGroup* group);
+ void assignGroups(LayerMergeState* mergeState);
LayerGroup* group() { return m_layerGroup; }
+ void setIntrinsicallyComposited(bool intCom) { m_intrinsicallyComposited = intCom; }
+
protected:
- virtual void onDraw(SkCanvas*, SkScalar opacity, android::DrawExtra* extra);
+ virtual void onDraw(SkCanvas*, SkScalar opacity, android::DrawExtra* extra, PaintStyle style);
IntPoint m_offset;
- IntPoint m_iframeScrollOffset;
TransformationMatrix m_drawTransform;
private:
@@ -330,23 +303,7 @@ private:
// -------------------------------------------------------------------
bool m_haveClip;
- bool m_isFixed;
bool m_backgroundColorSet;
- bool m_isIframe;
-
- SkLength m_fixedLeft;
- SkLength m_fixedTop;
- SkLength m_fixedRight;
- SkLength m_fixedBottom;
- SkLength m_fixedMarginLeft;
- SkLength m_fixedMarginTop;
- SkLength m_fixedMarginRight;
- SkLength m_fixedMarginBottom;
- SkRect m_fixedRect;
-
- // When fixed element is undefined or auto, the render layer's position
- // is needed for offset computation
- IntPoint m_renderLayerPos;
bool m_backfaceVisibility;
bool m_visible;
@@ -357,6 +314,8 @@ private:
float m_anchorPointZ;
float m_drawOpacity;
+ FixedPositioning* m_fixedPosition;
+
// Note that m_recordingPicture and m_imageRef are mutually exclusive;
// m_recordingPicture is used when WebKit is asked to paint the layer's
// content, while m_imageRef contains an image that we directly
@@ -375,8 +334,6 @@ private:
// Fields that are not serialized (generated, cached, or non-serializable)
// -------------------------------------------------------------------
- SkPoint m_iframeOffset;
-
float m_zValue;
FloatRect m_clippingRect;
@@ -403,9 +360,11 @@ private:
RenderLayer* m_owningLayer;
- int m_type;
+ LayerType m_type;
+ SubclassType m_subclassType;
bool m_hasText;
+ bool m_intrinsicallyComposited;
LayerGroup* m_layerGroup;
diff --git a/Source/WebCore/platform/graphics/android/LayerGroup.cpp b/Source/WebCore/platform/graphics/android/LayerGroup.cpp
index cb1cf9b..5ec41f8 100644
--- a/Source/WebCore/platform/graphics/android/LayerGroup.cpp
+++ b/Source/WebCore/platform/graphics/android/LayerGroup.cpp
@@ -53,13 +53,12 @@
// LayerGroups with an area larger than 2048*2048 should never be unclipped
#define MAX_UNCLIPPED_AREA 4194304
-#define TEMP_LAYER m_layers[0]
-
namespace WebCore {
LayerGroup::LayerGroup()
- : m_hasText(false)
- , m_dualTiledTexture(0)
+ : m_dualTiledTexture(0)
+ , m_needsTexture(false)
+ , m_hasText(false)
{
#ifdef DEBUG_COUNT
ClassTracker::instance()->increment("LayerGroup");
@@ -77,61 +76,144 @@ LayerGroup::~LayerGroup()
#endif
}
-void LayerGroup::initializeGroup(LayerAndroid* newLayer, const SkRegion& newLayerInval,
- LayerAndroid* oldLayer)
+bool LayerGroup::tryUpdateLayerGroup(LayerGroup* oldLayerGroup)
{
- if (!newLayer->needsTexture())
- return;
+ if (!needsTexture() || !oldLayerGroup->needsTexture())
+ return false;
+
+ // merge layer group based on first layer ID
+ if (getFirstLayer()->uniqueId() != oldLayerGroup->getFirstLayer()->uniqueId())
+ return false;
+
+ m_dualTiledTexture = oldLayerGroup->m_dualTiledTexture;
+ SkSafeRef(m_dualTiledTexture);
- XLOG("init on LG %p, layer %p, oldlayer %p", this, newLayer, oldLayer);
- if (oldLayer && oldLayer->group() && oldLayer->group()->m_dualTiledTexture) {
- // steal DTT from old group, and apply new inval
- m_dualTiledTexture = oldLayer->group()->m_dualTiledTexture;
- SkSafeRef(m_dualTiledTexture);
- m_dualTiledTexture->markAsDirty(newLayerInval);
- } else
- m_dualTiledTexture = new DualTiledTexture();
- }
-
-void LayerGroup::addLayer(LayerAndroid* layer)
+ XLOG("%p taking old DTT %p from group %p, nt %d",
+ this, m_dualTiledTexture, oldLayerGroup, oldLayerGroup->needsTexture());
+
+ if (!m_dualTiledTexture) {
+ // no DTT to inval, so don't worry about it.
+ return true;
+ }
+
+ if (singleLayer() && oldLayerGroup->singleLayer()) {
+ // both are single matching layers, simply apply inval
+ SkRegion* layerInval = getFirstLayer()->getInvalRegion();
+ m_dualTiledTexture->markAsDirty(*layerInval);
+ } else {
+ SkRegion invalRegion;
+ bool fullInval = false;
+ for (unsigned int i = 0; i < m_layers.size(); i++) {
+ if (m_layers[i]->uniqueId() != oldLayerGroup->m_layers[i]->uniqueId()) {
+ // layer list has changed, fully invalidate
+ // TODO: partially invalidate based on layer size/position
+ fullInval = true;
+ break;
+ } else if (!m_layers[i]->getInvalRegion()->isEmpty()) {
+ // merge layer inval - translate the layer's inval region into group coordinates
+ SkPoint pos = m_layers[i]->getPosition();
+ m_layers[i]->getInvalRegion()->translate(pos.fX, pos.fY);
+ invalRegion.op(*(m_layers[i]->getInvalRegion()), SkRegion::kUnion_Op);
+ break;
+ }
+ }
+
+ if (fullInval)
+ invalRegion.setRect(-1e8, -1e8, 2e8, 2e8);
+
+ m_dualTiledTexture->markAsDirty(invalRegion);
+ }
+ return true;
+}
+
+void LayerGroup::addLayer(LayerAndroid* layer, const TransformationMatrix& transform)
{
m_layers.append(layer);
SkSafeRef(layer);
+
+ m_needsTexture |= layer->needsTexture();
+ m_hasText |= layer->hasText();
+
+ // calculate area size for comparison later
+ IntRect rect = layer->unclippedArea();
+ SkPoint pos = layer->getPosition();
+ rect.setLocation(IntPoint(pos.fX, pos.fY));
+
+ if (layer->needsTexture()) {
+ if (m_unclippedArea.isEmpty()) {
+ m_drawTransform = transform;
+ m_drawTransform.translate3d(-pos.fX, -pos.fY, 0);
+ m_unclippedArea = rect;
+ } else
+ m_unclippedArea.unite(rect);
+ XLOG("LG %p adding LA %p, size %d, %d %dx%d, now LG size %d,%d %dx%d",
+ this, layer, rect.x(), rect.y(), rect.width(), rect.height(),
+ m_unclippedArea.x(), m_unclippedArea.y(),
+ m_unclippedArea.width(), m_unclippedArea.height());
+ }
+}
+
+IntRect LayerGroup::visibleArea()
+{
+ if (singleLayer())
+ return getFirstLayer()->visibleArea();
+
+ IntRect rect = m_unclippedArea;
+
+ // clip with the viewport in documents coordinate
+ IntRect documentViewport(TilesManager::instance()->shader()->documentViewport());
+ rect.intersect(documentViewport);
+
+ // TODO: handle recursive layer clip
+
+ return rect;
}
void LayerGroup::prepareGL(bool layerTilesDisabled)
{
- if (!m_dualTiledTexture)
- return;
+ if (!m_dualTiledTexture) {
+ XLOG("prepareGL on LG %p, no DTT, needsTexture? %d",
+ this, m_dualTiledTexture, needsTexture());
+
+ if (needsTexture())
+ m_dualTiledTexture = new DualTiledTexture();
+ else
+ return;
+ }
if (layerTilesDisabled) {
m_dualTiledTexture->discardTextures();
} else {
- XLOG("prepareGL on LG %p with DTT %p", this, m_dualTiledTexture);
- bool allowZoom = m_hasText; // only allow for scale > 1 if painting vectors
+ bool allowZoom = hasText(); // only allow for scale > 1 if painting vectors
IntRect prepareArea = computePrepareArea();
- m_dualTiledTexture->prepareGL(TEMP_LAYER->state(), TEMP_LAYER->hasText(),
+
+ XLOG("prepareGL on LG %p with DTT %p, %d layers",
+ this, m_dualTiledTexture, m_layers.size());
+ m_dualTiledTexture->prepareGL(getFirstLayer()->state(), allowZoom,
prepareArea, this);
}
}
bool LayerGroup::drawGL(bool layerTilesDisabled)
{
- if (!TEMP_LAYER->visible())
+ if (!getFirstLayer()->visible())
return false;
- FloatRect drawClip = TEMP_LAYER->drawClip();
+ FloatRect drawClip = getFirstLayer()->drawClip();
FloatRect clippingRect = TilesManager::instance()->shader()->rectInScreenCoord(drawClip);
TilesManager::instance()->shader()->clip(clippingRect);
bool askRedraw = false;
if (m_dualTiledTexture && !layerTilesDisabled) {
XLOG("drawGL on LG %p with DTT %p", this, m_dualTiledTexture);
- IntRect visibleArea = TEMP_LAYER->visibleArea();
- const TransformationMatrix* transform = TEMP_LAYER->drawTransform();
- askRedraw |= m_dualTiledTexture->drawGL(visibleArea, opacity(), transform);
+
+ IntRect drawArea = visibleArea();
+ askRedraw |= m_dualTiledTexture->drawGL(drawArea, opacity(), drawTransform());
}
- askRedraw |= TEMP_LAYER->drawGL(layerTilesDisabled);
+
+ // draw member layers (draws image textures, glextras)
+ for (unsigned int i = 0; i < m_layers.size(); i++)
+ askRedraw |= m_layers[i]->drawGL(layerTilesDisabled);
return askRedraw;
}
@@ -155,15 +237,16 @@ bool LayerGroup::isReady()
IntRect LayerGroup::computePrepareArea() {
IntRect area;
- if (!TEMP_LAYER->contentIsScrollable()
- && TEMP_LAYER->state()->layersRenderingMode() == GLWebViewState::kAllTextures) {
- area = TEMP_LAYER->unclippedArea();
+ if (!getFirstLayer()->contentIsScrollable()
+ && getFirstLayer()->state()->layersRenderingMode() == GLWebViewState::kAllTextures) {
+
+ area = singleLayer() ? getFirstLayer()->unclippedArea() : m_unclippedArea;
double total = ((double) area.width()) * ((double) area.height());
if (total > MAX_UNCLIPPED_AREA)
- area = TEMP_LAYER->visibleArea();
+ area = visibleArea();
} else {
- area = TEMP_LAYER->visibleArea();
+ area = visibleArea();
}
return area;
@@ -174,26 +257,48 @@ void LayerGroup::computeTexturesAmount(TexturesResult* result)
if (!m_dualTiledTexture)
return;
- // TODO: don't calculate through layer recursion, use the group list
- m_dualTiledTexture->computeTexturesAmount(result, TEMP_LAYER);
+ m_dualTiledTexture->computeTexturesAmount(result, getFirstLayer());
}
bool LayerGroup::paint(BaseTile* tile, SkCanvas* canvas, unsigned int* pictureUsed)
{
- SkPicture *picture = TEMP_LAYER->picture();
- if (!picture) {
- XLOGC("LG %p couldn't paint, no picture in layer %p", this, TEMP_LAYER);
- return false;
- }
+ if (singleLayer()) {
+ getFirstLayer()->contentDraw(canvas, Layer::UnmergedLayers);
+ } else {
+ SkAutoCanvasRestore acr(canvas, true);
+ SkMatrix matrix;
+ GLUtils::toSkMatrix(matrix, m_drawTransform);
+
+ SkMatrix inverse;
+ inverse.reset();
+ matrix.invert(&inverse);
- canvas->drawPicture(*picture);
+ SkMatrix canvasMatrix = canvas->getTotalMatrix();
+ inverse.postConcat(canvasMatrix);
+ canvas->setMatrix(inverse);
+ for (unsigned int i=0; i<m_layers.size(); i++)
+ m_layers[i]->drawCanvas(canvas, false, Layer::MergedLayers);
+ }
return true;
}
float LayerGroup::opacity()
{
- return TEMP_LAYER->getOpacity();
+ if (singleLayer())
+ return getFirstLayer()->getOpacity();
+ return 1.0;
+}
+
+const TransformationMatrix* LayerGroup::drawTransform()
+{
+ // single layer groups query the layer's draw transform, while multi-layer
+ // groups copy the draw transform once, during initialization
+ // TODO: support fixed multi-layer groups by querying the changing drawTransform
+ if (singleLayer())
+ return getFirstLayer()->drawTransform();
+
+ return &m_drawTransform;
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/LayerGroup.h b/Source/WebCore/platform/graphics/android/LayerGroup.h
index 0546139..e3e0247 100644
--- a/Source/WebCore/platform/graphics/android/LayerGroup.h
+++ b/Source/WebCore/platform/graphics/android/LayerGroup.h
@@ -26,6 +26,7 @@
#ifndef LayerGroup_h
#define LayerGroup_h
+#include "IntRect.h"
#include "TilePainter.h"
#include "Vector.h"
@@ -44,10 +45,11 @@ public:
LayerGroup();
virtual ~LayerGroup();
- void initializeGroup(LayerAndroid* newLayer, const SkRegion& newLayerInval,
- LayerAndroid* oldLayer);
+ bool tryUpdateLayerGroup(LayerGroup* oldLayerGroup);
- void addLayer(LayerAndroid* layer);
+
+ void addLayer(LayerAndroid* layer, const TransformationMatrix& transform);
+ IntRect visibleArea();
void prepareGL(bool layerTilesDisabled);
bool drawGL(bool layerTilesDisabled);
void swapTiles();
@@ -56,15 +58,48 @@ public:
IntRect computePrepareArea();
void computeTexturesAmount(TexturesResult* result);
+ LayerAndroid* getFirstLayer() { return m_layers[0]; }
+ bool singleLayer() { return m_layers.size() == 1; }
+ bool needsTexture() { return m_needsTexture; }
+ bool hasText() { return m_hasText; }
+
// TilePainter methods
virtual bool paint(BaseTile* tile, SkCanvas* canvas, unsigned int* pictureUsed);
virtual float opacity();
private:
- bool m_hasText;
+ const TransformationMatrix* drawTransform();
+ IntRect m_unclippedArea;
+ TransformationMatrix m_drawTransform;
+
DualTiledTexture* m_dualTiledTexture;
+ bool m_needsTexture;
+ bool m_hasText;
Vector<LayerAndroid*> m_layers;
};
+class LayerMergeState {
+public:
+ LayerMergeState(Vector<LayerGroup*>* const allGroups)
+ : groupList(allGroups)
+ , currentLayerGroup(0)
+ , nonMergeNestedLevel(-1) // start at -1 to ignore first LayerAndroid's clipping
+ , depth(0)
+ {}
+
+ // vector storing all generated layer groups
+ Vector<LayerGroup*>* const groupList;
+
+ // currently merging group. if cleared, no more layers may join
+ LayerGroup* currentLayerGroup;
+
+ // records depth within non-mergeable parents (clipping, fixed, scrolling)
+ // and disable merging therein.
+ int nonMergeNestedLevel;
+
+ // counts layer tree depth for debugging
+ int depth;
+};
+
} // namespace WebCore
#endif //#define LayerGroup_h
diff --git a/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.cpp
index 205727c..dffab58 100644
--- a/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.cpp
@@ -21,15 +21,8 @@ bool ScrollableLayerAndroid::scrollTo(int x, int y)
SkScalar newX = SkScalarPin(x, scrollBounds.x(), scrollBounds.width());
SkScalar newY = SkScalarPin(y, scrollBounds.y(), scrollBounds.height());
// Check for no change.
- if (isIFrame()) {
- if (newX == m_iframeScrollOffset.x() && newY == m_iframeScrollOffset.y())
- return false;
- newX = newX - m_iframeScrollOffset.x();
- newY = newY - m_iframeScrollOffset.y();
- } else {
- if (newX == m_offset.x() && newY == m_offset.y())
- return false;
- }
+ if (newX == m_offset.x() && newY == m_offset.y())
+ return false;
setScrollOffset(IntPoint(newX, newY));
return true;
}
@@ -46,16 +39,8 @@ void ScrollableLayerAndroid::getScrollBounds(IntRect* out) const
void ScrollableLayerAndroid::getScrollRect(SkIRect* out) const
{
const SkPoint& pos = getPosition();
- out->fLeft = m_scrollLimits.fLeft - pos.fX;
- out->fTop = m_scrollLimits.fTop - pos.fY;
-
- if (isIFrame()) {
- out->fLeft += m_iframeScrollOffset.x();
- out->fTop += m_iframeScrollOffset.y();
- } else {
- out->fLeft += m_offset.x();
- out->fTop += m_offset.y();
- }
+ out->fLeft = m_scrollLimits.fLeft - pos.fX + m_offset.x();
+ out->fTop = m_scrollLimits.fTop - pos.fY + m_offset.y();
out->fRight = getSize().width() - m_scrollLimits.width();
out->fBottom = getSize().height() - m_scrollLimits.height();
diff --git a/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.h b/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.h
index b8ff299..1f289e6 100644
--- a/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.h
+++ b/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.h
@@ -41,19 +41,20 @@ public:
virtual bool contentIsScrollable() const { return true; }
virtual LayerAndroid* copy() const { return new ScrollableLayerAndroid(*this); }
+ virtual SubclassType subclassType() { return LayerAndroid::ScrollableLayer; }
virtual bool updateWithLayer(LayerAndroid*) { return true; }
// Scrolls to the given position in the layer.
// Returns whether or not any scrolling was required.
- bool scrollTo(int x, int y);
+ virtual bool scrollTo(int x, int y);
// Fills the rect with the current scroll offset and the maximum scroll offset.
// fLeft = scrollX
// fTop = scrollY
// fRight = maxScrollX
// fBottom = maxScrollY
- void getScrollRect(SkIRect*) const;
+ virtual void getScrollRect(SkIRect*) const;
void setScrollLimits(float x, float y, float width, float height)
{
@@ -68,9 +69,9 @@ public:
bool scrollRectIntoView(const SkIRect&);
friend void android::serializeLayer(LayerAndroid* layer, SkWStream* stream);
- friend LayerAndroid* android::deserializeLayer(SkStream* stream);
+ friend LayerAndroid* android::deserializeLayer(int version, SkStream* stream);
-private:
+protected:
void getScrollBounds(IntRect*) const;
diff --git a/Source/WebCore/platform/graphics/android/SurfaceCollection.cpp b/Source/WebCore/platform/graphics/android/SurfaceCollection.cpp
index 48e4f27..55fa51a 100644
--- a/Source/WebCore/platform/graphics/android/SurfaceCollection.cpp
+++ b/Source/WebCore/platform/graphics/android/SurfaceCollection.cpp
@@ -72,7 +72,9 @@ SurfaceCollection::SurfaceCollection(BaseLayerAndroid* baseLayer)
// allocate groups for layers, merging where possible
XLOG("new tree, allocating groups for tree %p", m_baseLayer);
- m_compositedRoot->assignGroups(&m_layerGroups);
+
+ LayerMergeState layerMergeState(&m_layerGroups);
+ m_compositedRoot->assignGroups(&layerMergeState);
}
#ifdef DEBUG_COUNT
ClassTracker::instance()->increment("SurfaceCollection");
@@ -183,7 +185,7 @@ void SurfaceCollection::drawCanvas(SkCanvas* canvas, bool drawLayers)
// draw the layers onto the same canvas (for single surface mode)
if (drawLayers && m_compositedRoot)
- m_compositedRoot->drawCanvas(canvas);
+ m_compositedRoot->drawCanvas(canvas, true, Layer::FlattenedLayers);
}
@@ -198,12 +200,20 @@ void SurfaceCollection::setIsPainting(SurfaceCollection* drawingSurface)
m_baseLayer->setIsPainting();
- LayerAndroid* oldCompositedSurface = 0;
- if (drawingSurface)
- oldCompositedSurface = drawingSurface->m_compositedRoot;
+ if (!drawingSurface)
+ return;
- if (m_compositedRoot)
- m_compositedRoot->setIsPainting(oldCompositedSurface);
+ for (unsigned int i = 0; i < m_layerGroups.size(); i++) {
+ LayerGroup* newLayerGroup = m_layerGroups[i];
+ if (!newLayerGroup->needsTexture())
+ continue;
+
+ for (unsigned int j = 0; j < drawingSurface->m_layerGroups.size(); j++) {
+ LayerGroup* oldLayerGroup = drawingSurface->m_layerGroups[j];
+ if (newLayerGroup->tryUpdateLayerGroup(oldLayerGroup))
+ break;
+ }
+ }
}
void SurfaceCollection::setIsDrawing()
diff --git a/Source/WebCore/rendering/RenderLayer.h b/Source/WebCore/rendering/RenderLayer.h
index 02ab8e9..5e421f0 100644
--- a/Source/WebCore/rendering/RenderLayer.h
+++ b/Source/WebCore/rendering/RenderLayer.h
@@ -498,6 +498,12 @@ public:
bool hasOverflowScroll() const { return m_hasOverflowScroll; }
bool hasOverflowParent() const;
#endif
+#if PLATFORM(ANDROID)
+ bool intrinsicallyComposited() const { return m_intrinsicallyComposited; }
+ void setIntrinsicallyComposited(bool intrinsicallyComposited) {
+ m_intrinsicallyComposited = intrinsicallyComposited;
+ }
+#endif
private:
// The normal operator new is disallowed on all render objects.
@@ -751,6 +757,9 @@ protected:
bool m_shouldComposite : 1;
#endif
#endif
+#if PLATFORM(ANDROID)
+ bool m_intrinsicallyComposited : 1;
+#endif
bool m_containsDirtyOverlayScrollbars : 1;
#if ENABLE(ANDROID_OVERFLOW_SCROLL)
diff --git a/Source/WebCore/rendering/RenderLayerCompositor.cpp b/Source/WebCore/rendering/RenderLayerCompositor.cpp
index 25a08e7..d7f5c6b 100644
--- a/Source/WebCore/rendering/RenderLayerCompositor.cpp
+++ b/Source/WebCore/rendering/RenderLayerCompositor.cpp
@@ -682,7 +682,12 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O
layer->updateLayerPosition();
layer->updateZOrderLists();
layer->updateNormalFlowList();
-
+#if PLATFORM(ANDROID)
+ RenderObject* renderer = layer->renderer();
+ bool intCom = requiresCompositingLayer(layer);
+ layer->setIntrinsicallyComposited(intCom);
+#endif
+
// Clear the flag
layer->setHasCompositingDescendant(false);
diff --git a/Source/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp b/Source/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp
index 1328675..5e16152 100644
--- a/Source/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp
+++ b/Source/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp
@@ -161,8 +161,15 @@ void ChromeClientAndroid::focus()
}
void ChromeClientAndroid::unfocus() { notImplemented(); }
-bool ChromeClientAndroid::canTakeFocus(FocusDirection) { notImplemented(); return false; }
-void ChromeClientAndroid::takeFocus(FocusDirection) { notImplemented(); }
+bool ChromeClientAndroid::canTakeFocus(FocusDirection direction)
+{
+ return android::WebViewCore::getWebViewCore(m_webFrame->page()->mainFrame()->view())->chromeCanTakeFocus(direction);
+}
+
+void ChromeClientAndroid::takeFocus(FocusDirection direction)
+{
+ android::WebViewCore::getWebViewCore(m_webFrame->page()->mainFrame()->view())->chromeTakeFocus(direction);
+}
void ChromeClientAndroid::focusedNodeChanged(Node* node)
{
diff --git a/Source/WebKit/android/jni/AndroidHitTestResult.cpp b/Source/WebKit/android/jni/AndroidHitTestResult.cpp
index 16dd809..9be5613 100644
--- a/Source/WebKit/android/jni/AndroidHitTestResult.cpp
+++ b/Source/WebKit/android/jni/AndroidHitTestResult.cpp
@@ -135,11 +135,15 @@ void AndroidHitTestResult::buildHighlightRects()
node = m_hitTestResult.innerNode();
if (!node || !node->renderer())
return;
+ if (!WebViewCore::nodeIsClickableOrFocusable(node))
+ return;
Frame* frame = node->document()->frame();
IntPoint frameOffset = m_webViewCore->convertGlobalContentToFrameContent(IntPoint(), frame);
RenderObject* renderer = node->renderer();
Vector<FloatQuad> quads;
renderer->absoluteFocusRingQuads(quads);
+ if (!quads.size())
+ renderer->absoluteQuads(quads); // No fancy rings, grab some backups
for (size_t i = 0; i < quads.size(); i++) {
IntRect boundingBox = quads[i].enclosingBoundingBox();
boundingBox.move(-frameOffset.x(), -frameOffset.y());
diff --git a/Source/WebKit/android/jni/ViewStateSerializer.cpp b/Source/WebKit/android/jni/ViewStateSerializer.cpp
index 6b473f5..a96b6b4 100644
--- a/Source/WebKit/android/jni/ViewStateSerializer.cpp
+++ b/Source/WebKit/android/jni/ViewStateSerializer.cpp
@@ -27,7 +27,10 @@
#include "BaseLayerAndroid.h"
#include "CreateJavaOutputStreamAdaptor.h"
+#include "FixedPositioning.h"
#include "ImagesManager.h"
+#include "IFrameContentLayerAndroid.h"
+#include "IFrameLayerAndroid.h"
#include "Layer.h"
#include "LayerAndroid.h"
#include "PictureSet.h"
@@ -49,6 +52,9 @@
#undef XLOG
#define XLOG(...)
+#undef XLOGC
+#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "ViewStateSerializer", __VA_ARGS__)
+
#endif // DEBUG
namespace android {
@@ -57,6 +63,7 @@ enum LayerTypes {
LTNone = 0,
LTLayerAndroid = 1,
LTScrollableLayerAndroid = 2,
+ LTFixedLayerAndroid = 3
};
static bool nativeSerializeViewState(JNIEnv* env, jobject, jint jbaseLayer,
@@ -91,8 +98,8 @@ static bool nativeSerializeViewState(JNIEnv* env, jobject, jint jbaseLayer,
return true;
}
-static BaseLayerAndroid* nativeDeserializeViewState(JNIEnv* env, jobject, jobject jstream,
- jbyteArray jstorage)
+static BaseLayerAndroid* nativeDeserializeViewState(JNIEnv* env, jobject, jint version,
+ jobject jstream, jbyteArray jstorage)
{
SkStream* stream = CreateJavaInputStreamAdaptor(env, jstream, jstorage);
if (!stream)
@@ -107,7 +114,7 @@ static BaseLayerAndroid* nativeDeserializeViewState(JNIEnv* env, jobject, jobjec
SkSafeUnref(picture);
int childCount = stream->readS32();
for (int i = 0; i < childCount; i++) {
- LayerAndroid* childLayer = deserializeLayer(stream);
+ LayerAndroid* childLayer = deserializeLayer(version, stream);
if (childLayer)
layer->addChild(childLayer);
}
@@ -253,9 +260,9 @@ void serializeLayer(LayerAndroid* layer, SkWStream* stream)
stream->write8(LTNone);
return;
}
- LayerTypes type = layer->contentIsScrollable()
- ? LTScrollableLayerAndroid
- : LTLayerAndroid;
+ LayerTypes type = LTLayerAndroid;
+ if (layer->contentIsScrollable())
+ type = LTScrollableLayerAndroid;
stream->write8(type);
// Start with Layer fields
@@ -272,20 +279,43 @@ void serializeLayer(LayerAndroid* layer, SkWStream* stream)
// Next up, LayerAndroid fields
stream->writeBool(layer->m_haveClip);
- stream->writeBool(layer->m_isFixed);
+ stream->writeBool(layer->isFixed());
stream->writeBool(layer->m_backgroundColorSet);
- stream->writeBool(layer->m_isIframe);
- writeSkLength(stream, layer->m_fixedLeft);
- writeSkLength(stream, layer->m_fixedTop);
- writeSkLength(stream, layer->m_fixedRight);
- writeSkLength(stream, layer->m_fixedBottom);
- writeSkLength(stream, layer->m_fixedMarginLeft);
- writeSkLength(stream, layer->m_fixedMarginTop);
- writeSkLength(stream, layer->m_fixedMarginRight);
- writeSkLength(stream, layer->m_fixedMarginBottom);
- writeSkRect(stream, layer->m_fixedRect);
- stream->write32(layer->m_renderLayerPos.x());
- stream->write32(layer->m_renderLayerPos.y());
+ stream->writeBool(layer->isIFrame());
+
+ // With the current LayerAndroid hierarchy, LayerAndroid doesn't have
+ // those fields anymore. Let's keep the current serialization format for
+ // now and output blank fields... not great, but probably better than
+ // dealing with multiple versions.
+ if (layer->fixedPosition()) {
+ FixedPositioning* fixedPosition = layer->fixedPosition();
+ writeSkLength(stream, fixedPosition->m_fixedLeft);
+ writeSkLength(stream, fixedPosition->m_fixedTop);
+ writeSkLength(stream, fixedPosition->m_fixedRight);
+ writeSkLength(stream, fixedPosition->m_fixedBottom);
+ writeSkLength(stream, fixedPosition->m_fixedMarginLeft);
+ writeSkLength(stream, fixedPosition->m_fixedMarginTop);
+ writeSkLength(stream, fixedPosition->m_fixedMarginRight);
+ writeSkLength(stream, fixedPosition->m_fixedMarginBottom);
+ writeSkRect(stream, fixedPosition->m_fixedRect);
+ stream->write32(fixedPosition->m_renderLayerPos.x());
+ stream->write32(fixedPosition->m_renderLayerPos.y());
+ } else {
+ SkLength length;
+ SkRect rect;
+ writeSkLength(stream, length); // fixedLeft
+ writeSkLength(stream, length); // fixedTop
+ writeSkLength(stream, length); // fixedRight
+ writeSkLength(stream, length); // fixedBottom
+ writeSkLength(stream, length); // fixedMarginLeft
+ writeSkLength(stream, length); // fixedMarginTop
+ writeSkLength(stream, length); // fixedMarginRight
+ writeSkLength(stream, length); // fixedMarginBottom
+ writeSkRect(stream, rect); // fixedRect
+ stream->write32(0); // renderLayerPos.x()
+ stream->write32(0); // renderLayerPos.y()
+ }
+
stream->writeBool(layer->m_backfaceVisibility);
stream->writeBool(layer->m_visible);
stream->write32(layer->m_backgroundColor);
@@ -327,7 +357,7 @@ void serializeLayer(LayerAndroid* layer, SkWStream* stream)
serializeLayer(layer->getChild(i), stream);
}
-LayerAndroid* deserializeLayer(SkStream* stream)
+LayerAndroid* deserializeLayer(int version, SkStream* stream)
{
int type = stream->readU8();
if (type == LTNone)
@@ -354,20 +384,55 @@ LayerAndroid* deserializeLayer(SkStream* stream)
// LayerAndroid fields
layer->m_haveClip = stream->readBool();
- layer->m_isFixed = stream->readBool();
+
+ // Keep the legacy serialization/deserialization format...
+ bool isFixed = stream->readBool();
+
layer->m_backgroundColorSet = stream->readBool();
- layer->m_isIframe = stream->readBool();
- layer->m_fixedLeft = readSkLength(stream);
- layer->m_fixedTop = readSkLength(stream);
- layer->m_fixedRight = readSkLength(stream);
- layer->m_fixedBottom = readSkLength(stream);
- layer->m_fixedMarginLeft = readSkLength(stream);
- layer->m_fixedMarginTop = readSkLength(stream);
- layer->m_fixedMarginRight = readSkLength(stream);
- layer->m_fixedMarginBottom = readSkLength(stream);
- layer->m_fixedRect = readSkRect(stream);
- layer->m_renderLayerPos.setX(stream->readS32());
- layer->m_renderLayerPos.setY(stream->readS32());
+
+ bool isIframe = stream->readBool();
+ // If we are a scrollable layer android, we are an iframe content
+ if (isIframe && type == LTScrollableLayerAndroid) {
+ IFrameContentLayerAndroid* iframeContent = new IFrameContentLayerAndroid(*layer);
+ layer->unref();
+ layer = iframeContent;
+ } else if (isIframe) { // otherwise we are just the iframe (we use it to compute offset)
+ IFrameLayerAndroid* iframe = new IFrameLayerAndroid(*layer);
+ layer->unref();
+ layer = iframe;
+ }
+
+ if (isFixed) {
+ FixedPositioning* fixedPosition = new FixedPositioning(layer);
+
+ fixedPosition->m_fixedLeft = readSkLength(stream);
+ fixedPosition->m_fixedTop = readSkLength(stream);
+ fixedPosition->m_fixedRight = readSkLength(stream);
+ fixedPosition->m_fixedBottom = readSkLength(stream);
+ fixedPosition->m_fixedMarginLeft = readSkLength(stream);
+ fixedPosition->m_fixedMarginTop = readSkLength(stream);
+ fixedPosition->m_fixedMarginRight = readSkLength(stream);
+ fixedPosition->m_fixedMarginBottom = readSkLength(stream);
+ fixedPosition->m_fixedRect = readSkRect(stream);
+ fixedPosition->m_renderLayerPos.setX(stream->readS32());
+ fixedPosition->m_renderLayerPos.setY(stream->readS32());
+
+ layer->setFixedPosition(fixedPosition);
+ } else {
+ // Not a fixed element, bypass the values in the stream
+ readSkLength(stream); // fixedLeft
+ readSkLength(stream); // fixedTop
+ readSkLength(stream); // fixedRight
+ readSkLength(stream); // fixedBottom
+ readSkLength(stream); // fixedMarginLeft
+ readSkLength(stream); // fixedMarginTop
+ readSkLength(stream); // fixedMarginRight
+ readSkLength(stream); // fixedMarginBottom
+ readSkRect(stream); // fixedRect
+ stream->readS32(); // renderLayerPos.x()
+ stream->readS32(); // renderLayerPos.y()
+ }
+
layer->m_backfaceVisibility = stream->readBool();
layer->m_visible = stream->readBool();
layer->m_backgroundColor = stream->readU32();
@@ -404,7 +469,7 @@ LayerAndroid* deserializeLayer(SkStream* stream)
}
int childCount = stream->readU32();
for (int i = 0; i < childCount; i++) {
- LayerAndroid *childLayer = deserializeLayer(stream);
+ LayerAndroid *childLayer = deserializeLayer(version, stream);
if (childLayer)
layer->addChild(childLayer);
}
@@ -419,7 +484,7 @@ LayerAndroid* deserializeLayer(SkStream* stream)
static JNINativeMethod gSerializerMethods[] = {
{ "nativeSerializeViewState", "(ILjava/io/OutputStream;[B)Z",
(void*) nativeSerializeViewState },
- { "nativeDeserializeViewState", "(Ljava/io/InputStream;[B)I",
+ { "nativeDeserializeViewState", "(ILjava/io/InputStream;[B)I",
(void*) nativeDeserializeViewState },
};
diff --git a/Source/WebKit/android/jni/WebViewCore.cpp b/Source/WebKit/android/jni/WebViewCore.cpp
index 41a8339..af25b3b 100644
--- a/Source/WebKit/android/jni/WebViewCore.cpp
+++ b/Source/WebKit/android/jni/WebViewCore.cpp
@@ -366,6 +366,8 @@ struct WebViewCore::JavaGlue {
jmethodID m_selectAt;
jmethodID m_initEditField;
jmethodID m_updateMatchCount;
+ jmethodID m_chromeCanTakeFocus;
+ jmethodID m_chromeTakeFocus;
AutoJObject object(JNIEnv* env) {
// We hold a weak reference to the Java WebViewCore to avoid memeory
// leaks due to circular references when WebView.destroy() is not
@@ -482,6 +484,8 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m
m_javaGlue->m_selectAt = GetJMethod(env, clazz, "selectAt", "(II)V");
m_javaGlue->m_initEditField = GetJMethod(env, clazz, "initEditField", "(ILjava/lang/String;IZZLjava/lang/String;IIII)V");
m_javaGlue->m_updateMatchCount = GetJMethod(env, clazz, "updateMatchCount", "(IILjava/lang/String;)V");
+ m_javaGlue->m_chromeCanTakeFocus = GetJMethod(env, clazz, "chromeCanTakeFocus", "(I)Z");
+ m_javaGlue->m_chromeTakeFocus = GetJMethod(env, clazz, "chromeTakeFocus", "(I)V");
env->DeleteLocalRef(clazz);
env->SetIntField(javaWebViewCore, gWebViewCoreFields.m_nativeClass, (jint)this);
@@ -1670,6 +1674,23 @@ void WebViewCore::selectText(int startX, int startY, int endX, int endY)
sc->setSelection(selection);
}
+bool WebViewCore::nodeIsClickableOrFocusable(Node* node)
+{
+ if (!node)
+ return false;
+ if (node->disabled())
+ return false;
+ if (!node->inDocument())
+ return false;
+ if (!node->renderer() || node->renderer()->style()->visibility() != VISIBLE)
+ return false;
+ return node->supportsFocus()
+ || node->hasEventListeners(eventNames().clickEvent)
+ || node->hasEventListeners(eventNames().mousedownEvent)
+ || node->hasEventListeners(eventNames().mouseupEvent)
+ || node->hasEventListeners(eventNames().mouseoverEvent);
+}
+
// get the highlight rectangles for the touch point (x, y) with the slop
AndroidHitTestResult WebViewCore::hitTestAtPoint(int x, int y, int slop, bool doMoveMouse)
{
@@ -1711,11 +1732,7 @@ AndroidHitTestResult WebViewCore::hitTestAtPoint(int x, int y, int slop, bool do
RenderObject* render = eventNode->renderer();
if (render && (render->isBody() || render->isRenderView()))
break;
- if (eventNode->supportsFocus()
- || eventNode->hasEventListeners(eventNames().clickEvent)
- || eventNode->hasEventListeners(eventNames().mousedownEvent)
- || eventNode->hasEventListeners(eventNames().mouseupEvent)
- || eventNode->hasEventListeners(eventNames().mouseoverEvent)) {
+ if (nodeIsClickableOrFocusable(eventNode)) {
found = true;
break;
}
@@ -1816,15 +1833,15 @@ AndroidHitTestResult WebViewCore::hitTestAtPoint(int x, int y, int slop, bool do
}
// now get the node's highlight rectangles in the page coordinate system
if (final.mUrlNode) {
+ // Update innerNode and innerNonSharedNode
+ androidHitResult.hitTestResult().setInnerNode(final.mInnerNode);
+ androidHitResult.hitTestResult().setInnerNonSharedNode(final.mInnerNode);
if (final.mUrlNode->isElementNode()) {
// We found a URL element. Update the hitTestResult
androidHitResult.setURLElement(static_cast<Element*>(final.mUrlNode));
} else {
androidHitResult.setURLElement(0);
}
- // Update innerNode and innerNonSharedNode
- androidHitResult.hitTestResult().setInnerNode(final.mInnerNode);
- androidHitResult.hitTestResult().setInnerNonSharedNode(final.mInnerNode);
IntPoint frameAdjust;
if (frame != m_mainFrame) {
frameAdjust = frame->view()->contentsToWindow(IntPoint());
@@ -2990,6 +3007,24 @@ bool WebViewCore::key(const PlatformKeyboardEvent& event)
return eventHandler->keyEvent(event);
}
+bool WebViewCore::chromeCanTakeFocus(FocusDirection direction)
+{
+ JNIEnv* env = JSC::Bindings::getJNIEnv();
+ AutoJObject javaObject = m_javaGlue->object(env);
+ if (!javaObject.get())
+ return false;
+ return env->CallBooleanMethod(javaObject.get(), m_javaGlue->m_chromeCanTakeFocus, direction);
+}
+
+void WebViewCore::chromeTakeFocus(FocusDirection direction)
+{
+ JNIEnv* env = JSC::Bindings::getJNIEnv();
+ AutoJObject javaObject = m_javaGlue->object(env);
+ if (!javaObject.get())
+ return;
+ env->CallVoidMethod(javaObject.get(), m_javaGlue->m_chromeTakeFocus, direction);
+}
+
// For when the user clicks the trackball, presses dpad center, or types into an
// unfocused textfield. In the latter case, 'fake' will be true
void WebViewCore::click(WebCore::Frame* frame, WebCore::Node* node, bool fake) {
diff --git a/Source/WebKit/android/jni/WebViewCore.h b/Source/WebKit/android/jni/WebViewCore.h
index 4cbc566..c5704e0 100644
--- a/Source/WebKit/android/jni/WebViewCore.h
+++ b/Source/WebKit/android/jni/WebViewCore.h
@@ -29,6 +29,7 @@
#include "DeviceMotionAndOrientationManager.h"
#include "DOMSelection.h"
#include "FileChooser.h"
+#include "FocusDirection.h"
#include "HitTestResult.h"
#include "PictureSet.h"
#include "PlatformGraphicsContext.h"
@@ -318,6 +319,8 @@ namespace android {
* @return Whether keyCode was handled by this class.
*/
bool key(const WebCore::PlatformKeyboardEvent& event);
+ bool chromeCanTakeFocus(FocusDirection direction);
+ void chromeTakeFocus(FocusDirection direction);
/**
* Handle (trackball) click event / dpad center press from Java.
@@ -509,6 +512,7 @@ namespace android {
Node** node, HitTestResult* hitTestResult);
// This does a sloppy hit test
AndroidHitTestResult hitTestAtPoint(int x, int y, int slop, bool doMoveMouse = false);
+ static bool nodeIsClickableOrFocusable(Node* node);
// Open a file chooser for selecting a file to upload
void openFileChooser(PassRefPtr<WebCore::FileChooser> );
diff --git a/Source/WebKit/android/nav/WebView.cpp b/Source/WebKit/android/nav/WebView.cpp
index 830ef4e..8b7acc5 100644
--- a/Source/WebKit/android/nav/WebView.cpp
+++ b/Source/WebKit/android/nav/WebView.cpp
@@ -313,7 +313,7 @@ PictureSet* draw(SkCanvas* canvas, SkColor bgColor, DrawExtras extras, bool spli
if (compositeLayer) {
// call this to be sure we've adjusted for any scrolling or animations
// before we actually draw
- compositeLayer->updateFixedLayersPositions(m_visibleRect);
+ compositeLayer->updateLayerPositions(m_visibleRect);
compositeLayer->updatePositions();
// We have to set the canvas' matrix on the base layer
// (to have fixed layers work as intended)