summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicolas Roard <nicolasroard@google.com>2012-04-24 15:57:34 -0700
committerAndroid (Google) Code Review <android-gerrit@google.com>2012-04-24 15:57:34 -0700
commit2ad54828a335c8e7337ab1f1077253689630a6d2 (patch)
treed1d235ab26f0e0f4cdd104169fe01a047c2113c9
parent6808f6c0e2a6365404cd431b0233a2ec80dcd8a6 (diff)
parenta15d30f54c6edc68da7e82c198b5916dd023ac4d (diff)
downloadexternal_webkit-2ad54828a335c8e7337ab1f1077253689630a6d2.zip
external_webkit-2ad54828a335c8e7337ab1f1077253689630a6d2.tar.gz
external_webkit-2ad54828a335c8e7337ab1f1077253689630a6d2.tar.bz2
Merge "CSS Background image implementation"
-rw-r--r--Source/WebCore/platform/graphics/GraphicsLayerClient.h3
-rw-r--r--Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp152
-rw-r--r--Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.h7
-rw-r--r--Source/WebCore/platform/graphics/android/context/GraphicsOperationCollection.cpp4
-rw-r--r--Source/WebCore/platform/graphics/android/layers/BaseLayerAndroid.cpp44
-rw-r--r--Source/WebCore/platform/graphics/android/layers/BaseLayerAndroid.h29
-rw-r--r--Source/WebCore/platform/graphics/android/layers/FixedBackgroundLayerAndroid.h49
-rw-r--r--Source/WebCore/platform/graphics/android/layers/FixedPositioning.h9
-rw-r--r--Source/WebCore/platform/graphics/android/layers/LayerAndroid.cpp6
-rw-r--r--Source/WebCore/platform/graphics/android/layers/LayerAndroid.h10
-rw-r--r--Source/WebCore/platform/graphics/android/rendering/Surface.cpp20
-rw-r--r--Source/WebCore/platform/graphics/android/utils/ClassTracker.cpp2
-rw-r--r--Source/WebCore/rendering/PaintPhase.h4
-rw-r--r--Source/WebCore/rendering/RenderBlock.cpp6
-rw-r--r--Source/WebCore/rendering/RenderBox.cpp5
-rw-r--r--Source/WebCore/rendering/RenderBoxModelObject.h4
-rw-r--r--Source/WebCore/rendering/RenderLayerBacking.cpp12
-rw-r--r--Source/WebCore/rendering/RenderLayerCompositor.cpp3
-rw-r--r--Source/WebKit/android/jni/WebViewCore.cpp68
-rw-r--r--Source/WebKit/android/nav/WebView.cpp2
20 files changed, 383 insertions, 56 deletions
diff --git a/Source/WebCore/platform/graphics/GraphicsLayerClient.h b/Source/WebCore/platform/graphics/GraphicsLayerClient.h
index aab176b..3f09f32 100644
--- a/Source/WebCore/platform/graphics/GraphicsLayerClient.h
+++ b/Source/WebCore/platform/graphics/GraphicsLayerClient.h
@@ -43,6 +43,9 @@ enum GraphicsLayerPaintingPhase {
GraphicsLayerPaintBackground = (1 << 0),
GraphicsLayerPaintForeground = (1 << 1),
GraphicsLayerPaintMask = (1 << 2),
+#if PLATFORM(ANDROID)
+ GraphicsLayerPaintBackgroundDecorations = (1 << 3),
+#endif
GraphicsLayerPaintAll = (GraphicsLayerPaintBackground | GraphicsLayerPaintForeground | GraphicsLayerPaintMask)
};
diff --git a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp
index 00e6918..381f0b1 100644
--- a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp
@@ -25,9 +25,11 @@
#include "AndroidAnimation.h"
#include "AndroidLog.h"
#include "Animation.h"
+#include "CachedImage.h"
#include "CanvasLayer.h"
-#include "FloatRect.h"
+#include "FixedBackgroundLayerAndroid.h"
#include "FixedPositioning.h"
+#include "FloatRect.h"
#include "GraphicsContext.h"
#include "IFrameContentLayerAndroid.h"
#include "IFrameLayerAndroid.h"
@@ -47,6 +49,7 @@
#include "ScrollableLayerAndroid.h"
#include "SkCanvas.h"
#include "SkRegion.h"
+#include "StyleCachedImage.h"
#include "TransformationMatrix.h"
#include "TranslateTransformOperation.h"
@@ -117,6 +120,8 @@ GraphicsLayerAndroid::GraphicsLayerAndroid(GraphicsLayerClient* client) :
m_haveContents(false),
m_newImage(false),
m_image(0),
+ m_backgroundDecorationsLayer(0),
+ m_fixedBackgroundLayer(0),
m_foregroundLayer(0),
m_foregroundClipLayer(0)
{
@@ -136,6 +141,8 @@ GraphicsLayerAndroid::~GraphicsLayerAndroid()
m_image->deref();
m_contentLayer->unref();
+ SkSafeUnref(m_backgroundDecorationsLayer);
+ SkSafeUnref(m_fixedBackgroundLayer);
SkSafeUnref(m_foregroundLayer);
SkSafeUnref(m_foregroundClipLayer);
gDebugGraphicsLayerAndroidInstances--;
@@ -167,7 +174,7 @@ void GraphicsLayerAndroid::addChild(GraphicsLayer* childLayer)
{
#ifndef NDEBUG
const String& name = childLayer->name();
- ALOGV("(%x) addChild: %x (%s)", this, childLayer, name.latin1().data());
+ ALOGV("(%x) addChild: %x (%s)", this, childLayer, name.ascii().data());
#endif
GraphicsLayer::addChild(childLayer);
m_needsSyncChildren = true;
@@ -328,7 +335,8 @@ void GraphicsLayerAndroid::setSize(const FloatSize& size)
{
if (size == m_size)
return;
- ALOGV("(%x) setSize (%.2f,%.2f)", this, size.width(), size.height());
+ ALOGV("(%x) layer %d setSize (%.2f,%.2f)", this,
+ m_contentLayer->uniqueId(), size.width(), size.height());
GraphicsLayer::setSize(size);
// If it is a media layer the size may have changed as a result of the media
@@ -547,7 +555,7 @@ void GraphicsLayerAndroid::updateScrollingLayers()
}
// Need to rebuild our children based on the new structure.
m_needsSyncChildren = true;
- } else {
+ } else if (!m_contentLayer->isFixedBackground()) {
ASSERT(hasOverflowScroll && !layerNeedsOverflow && !iframeNeedsOverflow);
ASSERT(m_contentLayer);
// Remove the foreground layers.
@@ -573,6 +581,96 @@ void GraphicsLayerAndroid::updateScrollingLayers()
#endif
}
+void GraphicsLayerAndroid::updateFixedBackgroundLayers() {
+ RenderLayer* renderLayer = renderLayerFromClient(m_client);
+ if (!renderLayer)
+ return;
+ RenderView* view = static_cast<RenderView*>(renderLayer->renderer());
+ if (!view)
+ return;
+ if (view->isBody()) // body element is already handled
+ return;
+ if (!view->style()->hasFixedBackgroundImage())
+ return;
+ if (m_contentLayer->isFixedBackground())
+ return;
+ if (m_fixedBackgroundLayer) // already created
+ return;
+
+ // we will have:
+ // m_contentLayer
+ // \- m_foregroundClipLayer
+ // \- m_fixedBackgroundLayer
+ // \- m_backgroundDecorationsLayer
+ // \- m_foregroundLayer
+
+ // Grab the background image and create a layer for it
+ // the layer will be fixed positioned.
+ // TODO: if there's a background color, we don't honor it.
+ FillLayer* layers = view->style()->accessBackgroundLayers();
+ StyleImage* styleImage = layers->image();
+ if (styleImage->isCachedImage()) {
+ CachedImage* cachedImage = static_cast<StyleCachedImage*>(styleImage)->cachedImage();
+ Image* image = cachedImage->image();
+ if (image) {
+ m_fixedBackgroundLayer = new LayerAndroid(renderLayer);
+ m_fixedBackgroundLayer->setContentsImage(image->nativeImageForCurrentFrame());
+ m_fixedBackgroundLayer->setSize(image->width(), image->height());
+
+ // TODO: add support for the correct CSS position attributes
+ // for now, just pin to left(0) top(0)
+
+ FixedPositioning* fixedPosition = new FixedPositioning(m_fixedBackgroundLayer);
+ SkRect viewRect;
+ SkLength left, top, right, bottom;
+ left.setFixedValue(0);
+ top.setFixedValue(0);
+ right.setAuto();
+ bottom.setAuto();
+ SkLength marginLeft, marginTop, marginRight, marginBottom;
+ marginLeft.setAuto();
+ marginTop.setAuto();
+ marginRight.setAuto();
+ marginBottom.setAuto();
+
+ viewRect.set(0, 0, view->width(), view->height());
+ fixedPosition->setFixedPosition(left, top, right, bottom,
+ marginLeft, marginTop,
+ marginRight, marginBottom,
+ IntPoint(0, 0), viewRect);
+
+ m_fixedBackgroundLayer->setFixedPosition(fixedPosition);
+ }
+ }
+
+ // We need to clip the background image to the bounds of the original element
+ m_foregroundClipLayer = new LayerAndroid(renderLayer);
+ m_foregroundClipLayer->setMasksToBounds(true);
+ m_foregroundClipLayer->addChild(m_fixedBackgroundLayer);
+
+ // We then want to display the content above the image background; webkit
+ // allow to paint background and foreground separately. For now, we'll create
+ // two layers; the one containing the background will be painted *without* the
+ // background image (but with the decorations, e.g. border)
+ // TODO: use a single layer with a new type of content (joining background/foreground?)
+ m_backgroundDecorationsLayer = new LayerAndroid(renderLayer);
+ m_backgroundDecorationsLayer->setIntrinsicallyComposited(true);
+ m_foregroundLayer = new LayerAndroid(renderLayer);
+ m_foregroundLayer->setIntrinsicallyComposited(false);
+
+ // Finally, let's assemble all the layers under a FixedBackgroundLayerAndroid layer
+ LayerAndroid* layer = new FixedBackgroundLayerAndroid(*m_contentLayer);
+ m_contentLayer->unref();
+ m_contentLayer = layer;
+
+ m_contentLayer->addChild(m_foregroundClipLayer);
+ m_contentLayer->addChild(m_backgroundDecorationsLayer);
+ m_contentLayer->addChild(m_foregroundLayer);
+
+ m_needsRepaint = true;
+ m_needsSyncChildren = true;
+}
+
void GraphicsLayerAndroid::updateScrollOffset() {
RenderLayer* layer = renderLayerFromClient(m_client);
if (!layer || !(m_foregroundLayer || m_contentLayer->contentIsScrollable()))
@@ -600,7 +698,7 @@ bool GraphicsLayerAndroid::repaint()
RenderLayer* layer = renderLayerFromClient(m_client);
if (!layer)
return false;
- if (m_foregroundLayer) {
+ if (m_foregroundLayer && !m_contentLayer->isFixedBackground()) {
PaintingPhase phase(this);
// Paint the background into a separate context.
phase.set(GraphicsLayerPaintBackground);
@@ -648,7 +746,7 @@ bool GraphicsLayerAndroid::repaint()
// for the contents to be in the correct position.
m_foregroundLayer->setPosition(-x, -y);
// Set the scrollable bounds of the layer.
- m_foregroundLayer->setScrollLimits(-x, -y, m_size.width(), m_size.height());
+ static_cast<ScrollableLayerAndroid*>(m_foregroundLayer)->setScrollLimits(-x, -y, m_size.width(), m_size.height());
// Invalidate the entire layer for now, as webkit will only send the
// setNeedsDisplayInRect() for the visible (clipped) scrollable area,
@@ -657,6 +755,25 @@ bool GraphicsLayerAndroid::repaint()
SkRegion region;
region.setRect(0, 0, contentsRect.width(), contentsRect.height());
m_foregroundLayer->markAsDirty(region);
+ } else if (m_contentLayer->isFixedBackground()) {
+ PaintingPhase phase(this);
+ // Paint the background into a separate context.
+ ALOGV("paint background of layer %d (%d x %d)", m_contentLayer->uniqueId(),
+ layerBounds.width(), layerBounds.height());
+
+ m_backgroundDecorationsLayer->setSize(layerBounds.width(), layerBounds.height());
+ phase.set(GraphicsLayerPaintBackgroundDecorations);
+ paintContext(m_backgroundDecorationsLayer, layerBounds);
+ phase.clear(GraphicsLayerPaintBackgroundDecorations);
+
+ // Paint the foreground into a separate context.
+ ALOGV("paint foreground of layer %d", m_contentLayer->uniqueId());
+ m_foregroundLayer->setSize(layerBounds.width(), layerBounds.height());
+ phase.set(GraphicsLayerPaintForeground);
+ paintContext(m_foregroundLayer, layerBounds);
+
+ m_foregroundClipLayer->setPosition(layerBounds.x(), layerBounds.y());
+ m_foregroundClipLayer->setSize(layerBounds.width(), layerBounds.height());
} else {
// If there is no contents clip, we can draw everything into one
// picture.
@@ -788,7 +905,7 @@ bool GraphicsLayerAndroid::createAnimationFromKeyframes(const KeyframeValueList&
{
bool isKeyframe = valueList.size() > 2;
ALOGV("createAnimationFromKeyframes(%d), name(%s) beginTime(%.2f)",
- isKeyframe, keyframesName.latin1().data(), beginTime);
+ isKeyframe, keyframesName.ascii().data(), beginTime);
switch (valueList.property()) {
case AnimatedPropertyInvalid: break;
@@ -837,7 +954,7 @@ bool GraphicsLayerAndroid::createTransformAnimationsFromKeyframes(const Keyframe
{
ASSERT(valueList.property() == AnimatedPropertyWebkitTransform);
ALOGV("createTransformAnimationFromKeyframes, name(%s) beginTime(%.2f)",
- keyframesName.latin1().data(), beginTime);
+ keyframesName.ascii().data(), beginTime);
KeyframeValueList* operationsList = new KeyframeValueList(AnimatedPropertyWebkitTransform);
for (unsigned int i = 0; i < valueList.size(); i++) {
@@ -874,14 +991,14 @@ void GraphicsLayerAndroid::removeAnimationsForProperty(AnimatedPropertyID anID)
void GraphicsLayerAndroid::removeAnimationsForKeyframes(const String& keyframesName)
{
- ALOGV("NRO removeAnimationsForKeyframes(%s)", keyframesName.latin1().data());
+ ALOGV("NRO removeAnimationsForKeyframes(%s)", keyframesName.ascii().data());
m_contentLayer->removeAnimationsForKeyframes(keyframesName);
askForSync();
}
void GraphicsLayerAndroid::pauseAnimation(const String& keyframesName)
{
- ALOGV("NRO pauseAnimation(%s)", keyframesName.latin1().data());
+ ALOGV("NRO pauseAnimation(%s)", keyframesName.ascii().data());
}
void GraphicsLayerAndroid::suspendAnimations(double time)
@@ -984,20 +1101,28 @@ void GraphicsLayerAndroid::askForSync()
void GraphicsLayerAndroid::syncChildren()
{
- if (m_needsSyncChildren) {
+ if (m_needsSyncChildren && !m_contentLayer->isFixedBackground()) {
m_contentLayer->removeChildren();
LayerAndroid* layer = m_contentLayer;
- if (m_foregroundClipLayer) {
+
+ if (m_contentLayer->isFixedBackground()) {
+ m_contentLayer->addChild(m_foregroundClipLayer);
+ m_contentLayer->addChild(m_backgroundDecorationsLayer);
+ m_contentLayer->addChild(m_foregroundLayer);
+ layer = m_foregroundLayer;
+ layer->removeChildren();
+ } else if (m_foregroundClipLayer) {
m_contentLayer->addChild(m_foregroundClipLayer);
// Use the scrollable content layer as the parent of the children so
// that they move with the content.
layer = m_foregroundLayer;
layer->removeChildren();
}
+
for (unsigned int i = 0; i < m_children.size(); i++)
layer->addChild(m_children[i]->platformLayer());
- m_needsSyncChildren = false;
}
+ m_needsSyncChildren = false;
}
void GraphicsLayerAndroid::syncMask()
@@ -1046,6 +1171,7 @@ void GraphicsLayerAndroid::syncCompositingStateForThisLayerOnly()
}
updateScrollingLayers();
+ updateFixedBackgroundLayers();
updatePositionedLayers();
syncChildren();
syncMask();
diff --git a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.h b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.h
index 97f974e..24ba2d8 100644
--- a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.h
+++ b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.h
@@ -124,7 +124,7 @@ public:
void notifyClientAnimationStarted();
LayerAndroid* contentLayer() { return m_contentLayer; }
- ScrollableLayerAndroid* foregroundLayer() { return m_foregroundLayer; }
+ LayerAndroid* foregroundLayer() { return m_foregroundLayer; }
static int instancesCount();
@@ -139,6 +139,7 @@ private:
void updatePositionedLayers();
void updateScrollingLayers();
+ void updateFixedBackgroundLayers();
// with SkPicture, we always repaint the entire layer's content.
bool repaint();
@@ -158,7 +159,9 @@ private:
SkRegion m_dirtyRegion;
LayerAndroid* m_contentLayer;
- ScrollableLayerAndroid* m_foregroundLayer;
+ LayerAndroid* m_backgroundDecorationsLayer;
+ LayerAndroid* m_fixedBackgroundLayer;
+ LayerAndroid* m_foregroundLayer;
LayerAndroid* m_foregroundClipLayer;
};
diff --git a/Source/WebCore/platform/graphics/android/context/GraphicsOperationCollection.cpp b/Source/WebCore/platform/graphics/android/context/GraphicsOperationCollection.cpp
index 6118160..9e6208d 100644
--- a/Source/WebCore/platform/graphics/android/context/GraphicsOperationCollection.cpp
+++ b/Source/WebCore/platform/graphics/android/context/GraphicsOperationCollection.cpp
@@ -28,8 +28,8 @@ void GraphicsOperationCollection::apply(PlatformGraphicsContext* context)
{
ALOGD("\nApply GraphicsOperationCollection %x, %d operations", this, m_operations.size());
for (unsigned int i = 0; i < m_operations.size(); i++) {
- ALOGD("[%d] (%x) %s %s", i, this, m_operations[i]->name().latin1().data(),
- m_operations[i]->parameters().latin1().data());
+ ALOGD("[%d] (%x) %s %s", i, this, m_operations[i]->name().ascii().data(),
+ m_operations[i]->parameters().ascii().data());
m_operations[i]->apply(context);
}
}
diff --git a/Source/WebCore/platform/graphics/android/layers/BaseLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/layers/BaseLayerAndroid.cpp
index ce520b4..bc3b04b 100644
--- a/Source/WebCore/platform/graphics/android/layers/BaseLayerAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/layers/BaseLayerAndroid.cpp
@@ -30,6 +30,7 @@
#include "BaseLayerAndroid.h"
#include "AndroidLog.h"
+#include "FixedPositioning.h"
#include "GLWebViewState.h"
#include "LayerContent.h"
@@ -42,8 +43,10 @@ BaseLayerAndroid::BaseLayerAndroid(LayerContent* content)
: LayerAndroid((RenderLayer*)0)
, m_color(Color::white)
{
- setContent(content);
- setSize(content->width(), content->height());
+ if (content) {
+ setContent(content);
+ setSize(content->width(), content->height());
+ }
m_uniqueId = BASE_UNIQUE_ID;
}
@@ -66,4 +69,41 @@ IFrameLayerAndroid* BaseLayerAndroid::updatePosition(SkRect viewport,
return LayerAndroid::updatePosition(viewport, parentIframeLayer);
}
+ForegroundBaseLayerAndroid::ForegroundBaseLayerAndroid(LayerContent* content)
+ : LayerAndroid((RenderLayer*)0)
+{
+ setIntrinsicallyComposited(true);
+}
+
+FixedBackgroundBaseLayerAndroid::FixedBackgroundBaseLayerAndroid(LayerContent* content)
+ : LayerAndroid((RenderLayer*)0)
+{
+ if (content) {
+ setContent(content);
+ setSize(content->width(), content->height());
+ }
+ setIntrinsicallyComposited(true);
+
+ // TODO: add support for fixed positioning attributes
+ SkRect viewRect;
+ SkLength left, top, right, bottom;
+ left.setFixedValue(0);
+ top.setFixedValue(0);
+ right.setAuto();
+ bottom.setAuto();
+ SkLength marginLeft, marginTop, marginRight, marginBottom;
+ marginLeft.setAuto();
+ marginTop.setAuto();
+ marginRight.setAuto();
+ marginBottom.setAuto();
+
+ viewRect.set(0, 0, content->width(), content->height());
+ FixedPositioning* fixedPosition = new FixedPositioning(this);
+ setFixedPosition(fixedPosition);
+ fixedPosition->setFixedPosition(left, top, right, bottom,
+ marginLeft, marginTop,
+ marginRight, marginBottom,
+ IntPoint(0, 0), viewRect);
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/layers/BaseLayerAndroid.h b/Source/WebCore/platform/graphics/android/layers/BaseLayerAndroid.h
index f4cf9f3..dc4c25f 100644
--- a/Source/WebCore/platform/graphics/android/layers/BaseLayerAndroid.h
+++ b/Source/WebCore/platform/graphics/android/layers/BaseLayerAndroid.h
@@ -34,28 +34,37 @@ namespace WebCore {
class RenderLayerCompositor;
class BaseLayerAndroid : public LayerAndroid {
-
public:
BaseLayerAndroid(LayerContent* content);
-
- virtual ~BaseLayerAndroid() {};
-
virtual SubclassType subclassType() { return LayerAndroid::BaseLayer; }
- virtual bool needsTexture() { return true; }
-
- void setBackgroundColor(Color& color) { m_color = color; }
- Color getBackgroundColor() { return m_color; }
-
virtual void getLocalTransform(SkMatrix* matrix) const;
virtual const TransformationMatrix* drawTransform() const { return 0; }
-
+ virtual bool needsTexture() { return content(); }
virtual IFrameLayerAndroid* updatePosition(SkRect viewport,
IFrameLayerAndroid* parentIframeLayer);
+ void setBackgroundColor(Color& color) { m_color = color; }
+ Color getBackgroundColor() { return m_color; }
+
private:
// TODO: move to SurfaceCollection.
Color m_color;
};
+class ForegroundBaseLayerAndroid : public LayerAndroid {
+public:
+ ForegroundBaseLayerAndroid(LayerContent* content);
+ virtual SubclassType subclassType() { return LayerAndroid::ForegroundBaseLayer; }
+
+ virtual bool needsTexture() { return false; }
+};
+
+class FixedBackgroundBaseLayerAndroid : public LayerAndroid {
+public:
+ FixedBackgroundBaseLayerAndroid(LayerContent* content);
+ virtual bool needsTexture() { return true; }
+ virtual SubclassType subclassType() { return LayerAndroid::FixedBackgroundBaseLayer; }
+};
+
} // namespace WebCore
#endif //BaseLayerAndroid_h
diff --git a/Source/WebCore/platform/graphics/android/layers/FixedBackgroundLayerAndroid.h b/Source/WebCore/platform/graphics/android/layers/FixedBackgroundLayerAndroid.h
new file mode 100644
index 0000000..6c8f42c
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/layers/FixedBackgroundLayerAndroid.h
@@ -0,0 +1,49 @@
+/*
+ * 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 FixedBackgroundLayerAndroid_h
+#define FixedBackgroundLayerAndroid_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "LayerAndroid.h"
+
+namespace WebCore {
+
+// TODO: the hierarchy manipulation in GraphicsLayerAndroid should
+// (at least partly) be handled in this class
+class FixedBackgroundLayerAndroid : public LayerAndroid {
+public:
+ FixedBackgroundLayerAndroid(RenderLayer* owner)
+ : LayerAndroid(owner) {}
+ FixedBackgroundLayerAndroid(const FixedBackgroundLayerAndroid& layer)
+ : LayerAndroid(layer) {}
+ FixedBackgroundLayerAndroid(const LayerAndroid& layer)
+ : LayerAndroid(layer) {}
+ virtual ~FixedBackgroundLayerAndroid() {};
+
+ virtual LayerAndroid* copy() const { return new FixedBackgroundLayerAndroid(*this); }
+
+ virtual bool isFixedBackground() const { return true; }
+
+ virtual SubclassType subclassType() { return LayerAndroid::FixedBackgroundLayer; }
+};
+
+}
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif // FixedBackgroundLayerAndroid_h
diff --git a/Source/WebCore/platform/graphics/android/layers/FixedPositioning.h b/Source/WebCore/platform/graphics/android/layers/FixedPositioning.h
index 973113b..2fa7ae9 100644
--- a/Source/WebCore/platform/graphics/android/layers/FixedPositioning.h
+++ b/Source/WebCore/platform/graphics/android/layers/FixedPositioning.h
@@ -50,6 +50,15 @@ struct SkLength {
return false;
return true;
}
+ void setFixedValue(float v)
+ {
+ type = Fixed;
+ value = v;
+ }
+ void setAuto()
+ {
+ type = Auto;
+ }
float calcFloatValue(float max) const
{
switch (type) {
diff --git a/Source/WebCore/platform/graphics/android/layers/LayerAndroid.cpp b/Source/WebCore/platform/graphics/android/layers/LayerAndroid.cpp
index a02759d..69c597f 100644
--- a/Source/WebCore/platform/graphics/android/layers/LayerAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/layers/LayerAndroid.cpp
@@ -578,9 +578,9 @@ void LayerAndroid::showLayer(int indent)
IntRect visible = visibleArea();
IntRect clip(m_clippingRect.x(), m_clippingRect.y(),
m_clippingRect.width(), m_clippingRect.height());
- ALOGD("%s %s (%d) [%d:0x%x] - %s %s - area (%d, %d, %d, %d) - visible (%d, %d, %d, %d) "
+ ALOGD("%s %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 m_content(%x), pic w: %d h: %d",
- spaces, subclassName().latin1().data(), subclassType(), uniqueId(), m_owningLayer,
+ spaces, m_haveClip ? "CLIP LAYER" : "", subclassName().ascii().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(),
@@ -748,6 +748,8 @@ IntRect LayerAndroid::unclippedArea()
IntRect LayerAndroid::visibleArea()
{
IntRect area = unclippedArea();
+ if (subclassType() == LayerAndroid::FixedBackgroundBaseLayer)
+ return area;
// First, we get the transformed area of the layer,
// in document coordinates
IntRect rect = m_drawTransform.mapRect(area);
diff --git a/Source/WebCore/platform/graphics/android/layers/LayerAndroid.h b/Source/WebCore/platform/graphics/android/layers/LayerAndroid.h
index 9a803a9..4f94698 100644
--- a/Source/WebCore/platform/graphics/android/layers/LayerAndroid.h
+++ b/Source/WebCore/platform/graphics/android/layers/LayerAndroid.h
@@ -94,6 +94,9 @@ public:
typedef enum { UndefinedLayer, WebCoreLayer, UILayer } LayerType;
typedef enum { StandardLayer, ScrollableLayer,
IFrameLayer, IFrameContentLayer,
+ FixedBackgroundLayer,
+ FixedBackgroundBaseLayer,
+ ForegroundBaseLayer,
CanvasLayer, BaseLayer } SubclassType;
typedef enum { InvalidateNone = 0, InvalidateLayers } InvalidateFlags;
@@ -108,6 +111,12 @@ public:
return "IFrameLayer";
case LayerAndroid::IFrameContentLayer:
return "IFrameContentLayer";
+ case LayerAndroid::FixedBackgroundLayer:
+ return "FixedBackgroundLayer";
+ case LayerAndroid::FixedBackgroundBaseLayer:
+ return "FixedBackgroundBaseLayer";
+ case LayerAndroid::ForegroundBaseLayer:
+ return "ForegroundBaseLayer";
case LayerAndroid::CanvasLayer:
return "CanvasLayer";
case LayerAndroid::BaseLayer:
@@ -241,6 +250,7 @@ public:
virtual bool isVideo() const { return false; }
virtual bool isIFrame() const { return false; }
virtual bool isIFrameContent() const { return false; }
+ virtual bool isFixedBackground() const { return false; }
bool isPositionFixed() const { return m_fixedPosition; }
void setAbsolutePosition(bool isAbsolute) { m_isPositionAbsolute = isAbsolute; }
diff --git a/Source/WebCore/platform/graphics/android/rendering/Surface.cpp b/Source/WebCore/platform/graphics/android/rendering/Surface.cpp
index 210f434..13c7d27 100644
--- a/Source/WebCore/platform/graphics/android/rendering/Surface.cpp
+++ b/Source/WebCore/platform/graphics/android/rendering/Surface.cpp
@@ -38,6 +38,8 @@
#include "SurfaceBacking.h"
#include "TilesManager.h"
+#include <wtf/text/CString.h>
+
// Surfaces with an area larger than 2048*2048 should never be unclipped
#define MAX_UNCLIPPED_AREA 4194304
@@ -199,8 +201,13 @@ void Surface::prepareGL(bool layerTilesDisabled)
IntRect prepareArea = computePrepareArea();
IntRect fullArea = unclippedArea();
- ALOGV("prepareGL on Surf %p with SurfBack %p, %d layers",
- this, m_surfaceBacking, m_layers.size());
+ ALOGV("prepareGL on Surf %p with SurfBack %p, %d layers, first layer %s (%d) "
+ "prepareArea(%d, %d - %d x %d) fullArea(%d, %d - %d x %d)",
+ this, m_surfaceBacking, m_layers.size(),
+ getFirstLayer()->subclassName().ascii().data(),
+ getFirstLayer()->uniqueId(),
+ prepareArea.x(), prepareArea.y(), prepareArea.width(), prepareArea.height(),
+ fullArea.x(), fullArea.y(), fullArea.width(), fullArea.height());
m_surfaceBacking->prepareGL(getFirstLayer()->state(), allowZoom,
prepareArea, fullArea,
@@ -214,7 +221,11 @@ bool Surface::drawGL(bool layerTilesDisabled)
if (!getFirstLayer()->visible())
return false;
- if (!isBase()) {
+ bool isBaseLayer = isBase()
+ || getFirstLayer()->subclassType() == LayerAndroid::FixedBackgroundBaseLayer
+ || getFirstLayer()->subclassType() == LayerAndroid::ForegroundBaseLayer;
+
+ if (!isBaseLayer) {
// TODO: why are clipping regions wrong for base layer?
FloatRect drawClip = getFirstLayer()->drawClip();
FloatRect clippingRect = TilesManager::instance()->shader()->rectInScreenCoord(drawClip);
@@ -223,7 +234,8 @@ bool Surface::drawGL(bool layerTilesDisabled)
bool askRedraw = false;
if (m_surfaceBacking && !tilesDisabled) {
- ALOGV("drawGL on Surf %p with SurfBack %p", this, m_surfaceBacking);
+ ALOGV("drawGL on Surf %p with SurfBack %p, first layer %s (%d)", this, m_surfaceBacking,
+ getFirstLayer()->subclassName().ascii().data(), getFirstLayer()->uniqueId());
IntRect drawArea = visibleArea();
m_surfaceBacking->drawGL(drawArea, opacity(), drawTransform(),
diff --git a/Source/WebCore/platform/graphics/android/utils/ClassTracker.cpp b/Source/WebCore/platform/graphics/android/utils/ClassTracker.cpp
index 98e33d9..a73ece8 100644
--- a/Source/WebCore/platform/graphics/android/utils/ClassTracker.cpp
+++ b/Source/WebCore/platform/graphics/android/utils/ClassTracker.cpp
@@ -87,7 +87,7 @@ void ClassTracker::show()
ALOGD("*** Tracking %d classes ***", m_classes.size());
for (HashMap<String, int>::iterator iter = m_classes.begin(); iter != m_classes.end(); ++iter) {
ALOGD("class %s has %d instances",
- iter->first.latin1().data(), iter->second);
+ iter->first.ascii().data(), iter->second);
}
ALOGD("*** %d Layers ***", m_layers.size());
int nbTextures = 0;
diff --git a/Source/WebCore/rendering/PaintPhase.h b/Source/WebCore/rendering/PaintPhase.h
index 396131f..7dc205d 100644
--- a/Source/WebCore/rendering/PaintPhase.h
+++ b/Source/WebCore/rendering/PaintPhase.h
@@ -39,6 +39,10 @@ namespace WebCore {
enum PaintPhase {
PaintPhaseBlockBackground,
+#if PLATFORM(ANDROID)
+ // Used for fixed background support in layers
+ PaintPhaseBlockBackgroundDecorations,
+#endif
PaintPhaseChildBlockBackground,
PaintPhaseChildBlockBackgrounds,
PaintPhaseFloat,
diff --git a/Source/WebCore/rendering/RenderBlock.cpp b/Source/WebCore/rendering/RenderBlock.cpp
index a3bd41a..49dd169 100644
--- a/Source/WebCore/rendering/RenderBlock.cpp
+++ b/Source/WebCore/rendering/RenderBlock.cpp
@@ -2499,7 +2499,11 @@ void RenderBlock::paintObject(PaintInfo& paintInfo, int tx, int ty)
PaintPhase paintPhase = paintInfo.phase;
// 1. paint background, borders etc
- if ((paintPhase == PaintPhaseBlockBackground || paintPhase == PaintPhaseChildBlockBackground) && style()->visibility() == VISIBLE) {
+ if ((paintPhase == PaintPhaseBlockBackground || paintPhase == PaintPhaseChildBlockBackground
+#if PLATFORM(ANDROID)
+ || paintPhase == PaintPhaseBlockBackgroundDecorations
+#endif
+ ) && style()->visibility() == VISIBLE) {
if (hasBoxDecorations())
paintBoxDecorations(paintInfo, tx, ty);
if (hasColumns())
diff --git a/Source/WebCore/rendering/RenderBox.cpp b/Source/WebCore/rendering/RenderBox.cpp
index 9c40d5b..bc7d03a 100644
--- a/Source/WebCore/rendering/RenderBox.cpp
+++ b/Source/WebCore/rendering/RenderBox.cpp
@@ -843,6 +843,11 @@ void RenderBox::paintBoxDecorationsWithSize(PaintInfo& paintInfo, int tx, int ty
else if (!isBody() || document()->documentElement()->renderer()->hasBackground()) {
// The <body> only paints its background if the root element has defined a background
// independent of the body.
+#if PLATFORM(ANDROID)
+ // If we only want to draw the decorations, don't draw
+ // the background
+ if (paintInfo.phase != PaintPhaseBlockBackgroundDecorations)
+#endif
paintFillLayers(paintInfo, style()->visitedDependentColor(CSSPropertyBackgroundColor), style()->backgroundLayers(), tx, ty, width, height);
}
if (style()->hasAppearance())
diff --git a/Source/WebCore/rendering/RenderBoxModelObject.h b/Source/WebCore/rendering/RenderBoxModelObject.h
index d2f5972..ac4152f 100644
--- a/Source/WebCore/rendering/RenderBoxModelObject.h
+++ b/Source/WebCore/rendering/RenderBoxModelObject.h
@@ -62,7 +62,11 @@ public:
bool hasSelfPaintingLayer() const;
RenderLayer* layer() const { return m_layer; }
+#if PLATFORM(ANDROID)
+ virtual bool requiresLayer() const { return isRoot() || isPositioned() || isRelPositioned() || isTransparent() || hasOverflowClip() || hasTransform() || hasMask() || hasReflection() || style()->specifiesColumns() || style()->hasFixedBackgroundImage(); }
+#else
virtual bool requiresLayer() const { return isRoot() || isPositioned() || isRelPositioned() || isTransparent() || hasOverflowClip() || hasTransform() || hasMask() || hasReflection() || style()->specifiesColumns(); }
+#endif
// This will work on inlines to return the bounding box of all of the lines' border boxes.
virtual IntRect borderBoundingBox() const = 0;
diff --git a/Source/WebCore/rendering/RenderLayerBacking.cpp b/Source/WebCore/rendering/RenderLayerBacking.cpp
index 6f56eca..c0c562a 100644
--- a/Source/WebCore/rendering/RenderLayerBacking.cpp
+++ b/Source/WebCore/rendering/RenderLayerBacking.cpp
@@ -1114,12 +1114,24 @@ void RenderLayerBacking::paintIntoLayer(RenderLayer* rootLayer, GraphicsContext*
bool shouldPaint = (m_owningLayer->hasVisibleContent() || m_owningLayer->hasVisibleDescendant()) && m_owningLayer->isSelfPaintingLayer();
+#if PLATFORM(ANDROID)
+ if (shouldPaint && ((paintingPhase & GraphicsLayerPaintBackground)
+ || (paintingPhase & GraphicsLayerPaintBackgroundDecorations))) {
+#else
if (shouldPaint && (paintingPhase & GraphicsLayerPaintBackground)) {
+#endif
// Paint our background first, before painting any child layers.
// Establish the clip used to paint our background.
setClip(context, paintDirtyRect, damageRect);
+#if PLATFORM(ANDROID)
+ PaintPhase phase = PaintPhaseBlockBackground;
+ if (paintingPhase & GraphicsLayerPaintBackgroundDecorations)
+ phase = PaintPhaseBlockBackgroundDecorations;
+ PaintInfo info(context, damageRect, phase, false, paintingRootForRenderer, 0);
+#else
PaintInfo info(context, damageRect, PaintPhaseBlockBackground, false, paintingRootForRenderer, 0);
+#endif
renderer()->paint(info, tx, ty);
// Our scrollbar widgets paint exactly when we tell them to, so that they work properly with
diff --git a/Source/WebCore/rendering/RenderLayerCompositor.cpp b/Source/WebCore/rendering/RenderLayerCompositor.cpp
index 1871b57..6b669e8 100644
--- a/Source/WebCore/rendering/RenderLayerCompositor.cpp
+++ b/Source/WebCore/rendering/RenderLayerCompositor.cpp
@@ -1432,6 +1432,9 @@ bool RenderLayerCompositor::requiresCompositingForAndroidLayers(const RenderLaye
if (layer->renderer()->isCanvas())
return true;
+ if (layer->renderer()->style()->hasFixedBackgroundImage())
+ return true;
+
return false;
}
#endif
diff --git a/Source/WebKit/android/jni/WebViewCore.cpp b/Source/WebKit/android/jni/WebViewCore.cpp
index 7cc427f..726a225 100644
--- a/Source/WebKit/android/jni/WebViewCore.cpp
+++ b/Source/WebKit/android/jni/WebViewCore.cpp
@@ -88,6 +88,7 @@
#include "NodeList.h"
#include "Page.h"
#include "PageGroup.h"
+#include "PictureLayerContent.h"
#include "PictureSetLayerContent.h"
#include "PlatformKeyboardEvent.h"
#include "PlatformString.h"
@@ -872,37 +873,69 @@ void WebViewCore::notifyAnimationStarted()
BaseLayerAndroid* WebViewCore::createBaseLayer(SkRegion* region)
{
- PictureSetLayerContent* content = new PictureSetLayerContent(m_content);
- BaseLayerAndroid* base = new BaseLayerAndroid(content);
- SkSafeUnref(content);
-
- m_skipContentDraw = true;
- bool layoutSucceeded = layoutIfNeededRecursive(m_mainFrame);
- m_skipContentDraw = false;
- // Layout only fails if called during a layout.
- ALOG_ASSERT(layoutSucceeded, "Can never be called recursively");
-
-#if USE(ACCELERATED_COMPOSITING)
// We set the background color
Color background = Color::white;
+
+ bool bodyHasFixedBackgroundImage = false;
+ bool bodyHasCSSBackground = false;
+
if (m_mainFrame && m_mainFrame->document()
&& m_mainFrame->document()->body()) {
- bool hasCSSBackground = false;
Document* document = m_mainFrame->document();
RefPtr<RenderStyle> style = document->styleForElementIgnoringPendingStylesheets(document->body());
if (style->hasBackground()) {
background = style->visitedDependentColor(CSSPropertyBackgroundColor);
- hasCSSBackground = true;
+ bodyHasCSSBackground = true;
}
-
WebCore::FrameView* view = m_mainFrame->view();
if (view) {
Color viewBackground = view->baseBackgroundColor();
- background = hasCSSBackground ? viewBackground.blend(background) : viewBackground;
+ background = bodyHasCSSBackground ? viewBackground.blend(background) : viewBackground;
}
+ bodyHasFixedBackgroundImage = style->hasFixedBackgroundImage();
+ }
+
+ PictureSetLayerContent* content = new PictureSetLayerContent(m_content);
+
+ BaseLayerAndroid* realBase = 0;
+ LayerAndroid* base = 0;
+
+ //If we have a fixed background image on the body element, the fixed image
+ // will be contained in the PictureSet (the content object), and the foreground
+ //of the body element will be moved to a layer.
+ //In that case, let's change the hierarchy to obtain:
+ //
+ //BaseLayerAndroid
+ // \- FixedBackgroundBaseLayerAndroid (fixed positioning)
+ // \- ForegroundBaseLayerAndroid
+ // \- root layer (webkit composited tree)
+
+ if (bodyHasFixedBackgroundImage) {
+ base = new ForegroundBaseLayerAndroid(0);
+ base->setSize(content->width(), content->height());
+ FixedBackgroundBaseLayerAndroid* baseBackground =
+ new FixedBackgroundBaseLayerAndroid(content);
+
+ // TODO -- check we don't have the assumption that baselayer has only one child
+ realBase = new BaseLayerAndroid(0);
+ realBase->setSize(content->width(), content->height());
+ realBase->addChild(baseBackground);
+ realBase->addChild(base);
+ } else {
+ realBase = new BaseLayerAndroid(content);
+ base = realBase;
}
- base->setBackgroundColor(background);
+
+ realBase->setBackgroundColor(background);
+
+ SkSafeUnref(content);
+
+ m_skipContentDraw = true;
+ bool layoutSucceeded = layoutIfNeededRecursive(m_mainFrame);
+ m_skipContentDraw = false;
+ // Layout only fails if called during a layout.
+ ALOG_ASSERT(layoutSucceeded, "Can never be called recursively");
// We update the layers
ChromeClientAndroid* chromeC = static_cast<ChromeClientAndroid*>(m_mainFrame->page()->chrome()->client());
@@ -913,9 +946,8 @@ BaseLayerAndroid* WebViewCore::createBaseLayer(SkRegion* region)
copyLayer->unref();
root->contentLayer()->clearDirtyRegion();
}
-#endif
- return base;
+ return realBase;
}
BaseLayerAndroid* WebViewCore::recordContent(SkRegion* region, SkIPoint* point)
diff --git a/Source/WebKit/android/nav/WebView.cpp b/Source/WebKit/android/nav/WebView.cpp
index c6d5679..804a479 100644
--- a/Source/WebKit/android/nav/WebView.cpp
+++ b/Source/WebKit/android/nav/WebView.cpp
@@ -305,7 +305,7 @@ PictureSet* draw(SkCanvas* canvas, SkColor bgColor, DrawExtras extras, bool spli
LayerContent* content = m_baseLayer->content();
int sc = canvas->save(SkCanvas::kClip_SaveFlag);
canvas->clipRect(SkRect::MakeLTRB(0, 0, content->width(),
- content->height()), SkRegion::kDifference_Op);
+ content->height()), SkRegion::kDifference_Op);
Color c = m_baseLayer->getBackgroundColor();
canvas->drawColor(SkColorSetARGBInline(c.alpha(), c.red(), c.green(), c.blue()));
canvas->restoreToCount(sc);