summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Source/WebCore/bindings/v8/V8AbstractEventListener.cpp8
-rw-r--r--Source/WebCore/platform/android/RenderThemeAndroid.cpp9
-rw-r--r--Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp58
-rw-r--r--Source/WebCore/platform/graphics/android/BaseLayerAndroid.h2
-rw-r--r--Source/WebCore/platform/graphics/android/GLWebViewState.cpp155
-rw-r--r--Source/WebCore/platform/graphics/android/GLWebViewState.h4
-rw-r--r--Source/WebCore/platform/graphics/android/Layer.cpp68
-rw-r--r--Source/WebCore/platform/graphics/android/Layer.h38
-rw-r--r--Source/WebCore/platform/graphics/android/LayerAndroid.cpp34
-rw-r--r--Source/WebCore/platform/graphics/android/LayerAndroid.h19
-rw-r--r--Source/WebCore/platform/graphics/android/PaintTileOperation.cpp4
-rw-r--r--Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.cpp5
-rw-r--r--Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.h16
-rw-r--r--Source/WebCore/platform/graphics/android/ShaderProgram.cpp13
-rw-r--r--Source/WebCore/platform/graphics/android/ShaderProgram.h6
-rw-r--r--Source/WebCore/platform/graphics/android/TiledPage.cpp9
-rw-r--r--Source/WebCore/platform/graphics/android/TiledPage.h3
-rw-r--r--Source/WebCore/platform/graphics/android/TransferQueue.cpp24
-rw-r--r--Source/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.cpp13
-rw-r--r--Source/WebKit/android/jni/JavaSharedClient.cpp4
-rw-r--r--Source/WebKit/android/jni/ViewStateSerializer.cpp4
-rw-r--r--Source/WebKit/android/jni/WebCoreFrameBridge.cpp5
-rw-r--r--Source/WebKit/android/jni/WebViewCore.cpp17
-rw-r--r--Source/WebKit/android/nav/FindCanvas.cpp9
-rw-r--r--Source/WebKit/android/nav/FindCanvas.h7
-rw-r--r--Source/WebKit/android/nav/WebView.cpp64
26 files changed, 389 insertions, 209 deletions
diff --git a/Source/WebCore/bindings/v8/V8AbstractEventListener.cpp b/Source/WebCore/bindings/v8/V8AbstractEventListener.cpp
index 90dc097..0de99f8 100644
--- a/Source/WebCore/bindings/v8/V8AbstractEventListener.cpp
+++ b/Source/WebCore/bindings/v8/V8AbstractEventListener.cpp
@@ -72,6 +72,14 @@ V8AbstractEventListener::~V8AbstractEventListener()
void V8AbstractEventListener::handleEvent(ScriptExecutionContext* context, Event* event)
{
+#ifdef ANDROID
+ // Monkey data shows that we can crash here, due to script executing while the
+ // page's frame has been detached (in the middle of a navigation).
+ // See b/5201341
+ if (!context)
+ return;
+#endif
+
// Don't reenter V8 if execution was terminated in this instance of V8.
if (context->isJSExecutionForbidden())
return;
diff --git a/Source/WebCore/platform/android/RenderThemeAndroid.cpp b/Source/WebCore/platform/android/RenderThemeAndroid.cpp
index c6e3bc5..7ef814e 100644
--- a/Source/WebCore/platform/android/RenderThemeAndroid.cpp
+++ b/Source/WebCore/platform/android/RenderThemeAndroid.cpp
@@ -212,9 +212,12 @@ void RenderThemeAndroid::adjustButtonStyle(CSSStyleSelector*, RenderStyle* style
{
// Code is taken from RenderThemeSafari.cpp
// It makes sure we have enough space for the button text.
- const int padding = 8;
- style->setPaddingLeft(Length(padding, Fixed));
- style->setPaddingRight(Length(padding, Fixed));
+ const int paddingHoriz = 12;
+ const int paddingVert = 8;
+ style->setPaddingLeft(Length(paddingHoriz, Fixed));
+ style->setPaddingRight(Length(paddingHoriz, Fixed));
+ style->setPaddingTop(Length(paddingVert, Fixed));
+ style->setPaddingBottom(Length(paddingVert, Fixed));
// Set a min-height so that we can't get smaller than the mini button.
style->setMinHeight(Length(15, Fixed));
diff --git a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp
index 1fa69f8..547ac39 100644
--- a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp
@@ -54,6 +54,12 @@
#endif // DEBUG
+// TODO: dynamically determine based on DPI
+#define PREFETCH_SCALE_MODIFIER 0.3
+#define PREFETCH_OPACITY 1
+#define PREFETCH_X_DIST 1
+#define PREFETCH_Y_DIST 2
+
namespace WebCore {
using namespace android;
@@ -116,6 +122,49 @@ void BaseLayerAndroid::drawCanvas(SkCanvas* canvas)
}
#if USE(ACCELERATED_COMPOSITING)
+
+void BaseLayerAndroid::prefetchBasePicture(SkRect& viewport, float currentScale,
+ TiledPage* prefetchTiledPage)
+{
+ SkIRect bounds;
+ float prefetchScale = currentScale * PREFETCH_SCALE_MODIFIER;
+
+ float invTileWidth = (prefetchScale)
+ / TilesManager::instance()->tileWidth();
+ float invTileHeight = (prefetchScale)
+ / TilesManager::instance()->tileHeight();
+ bool goingDown = m_glWebViewState->goingDown();
+ bool goingLeft = m_glWebViewState->goingLeft();
+
+
+ XLOG("fetch rect %f %f %f %f, scale %f",
+ viewport.fLeft,
+ viewport.fTop,
+ viewport.fRight,
+ viewport.fBottom,
+ scale);
+
+ bounds.fLeft = static_cast<int>(floorf(viewport.fLeft * invTileWidth)) - PREFETCH_X_DIST;
+ bounds.fTop = static_cast<int>(floorf(viewport.fTop * invTileHeight)) - PREFETCH_Y_DIST;
+ bounds.fRight = static_cast<int>(ceilf(viewport.fRight * invTileWidth)) + PREFETCH_X_DIST;
+ bounds.fBottom = static_cast<int>(ceilf(viewport.fBottom * invTileHeight)) + PREFETCH_Y_DIST;
+
+ XLOG("prefetch rect %d %d %d %d, scale %f, preparing page %p",
+ bounds.fLeft, bounds.fTop,
+ bounds.fRight, bounds.fBottom,
+ scale * PREFETCH_SCALE,
+ prefetchTiledPage);
+
+ prefetchTiledPage->setScale(prefetchScale);
+ prefetchTiledPage->updateTileDirtiness(bounds);
+ prefetchTiledPage->prepare(goingDown, goingLeft, bounds,
+ TiledPage::ExpandedBounds);
+ prefetchTiledPage->swapBuffersIfReady(bounds,
+ prefetchScale,
+ TiledPage::SwapWhateverIsReady);
+ prefetchTiledPage->draw(PREFETCH_OPACITY, bounds);
+}
+
bool BaseLayerAndroid::drawBasePictureInGL(SkRect& viewport, float scale,
double currentTime, bool* buffersSwappedPtr)
{
@@ -183,6 +232,13 @@ bool BaseLayerAndroid::drawBasePictureInGL(SkRect& viewport, float scale,
bool scrolling = m_scrollState != NotScrolling;
bool zooming = ZoomManager::kNoScaleRequest != zoomManager->scaleRequestState();
+ // prefetch in the nextTiledPage if unused by zooming (even if not scrolling
+ // since we want the tiles to be ready before they're needed)
+ bool usePrefetchPage = !zooming;
+ nextTiledPage->setIsPrefetchPage(usePrefetchPage);
+ if (usePrefetchPage)
+ prefetchBasePicture(viewport, scale, nextTiledPage);
+
// When we aren't zooming, we should TRY and swap tile buffers if they're
// ready. When scrolling, we swap whatever's ready. Otherwise, buffer until
// the entire page is ready and then swap.
@@ -239,7 +295,6 @@ bool BaseLayerAndroid::drawBasePictureInGL(SkRect& viewport, float scale,
tiledPage->draw(transparency, preZoomBounds);
- m_glWebViewState->paintExtras();
return needsRedraw;
}
#endif // USE(ACCELERATED_COMPOSITING)
@@ -281,6 +336,7 @@ bool BaseLayerAndroid::drawGL(double currentTime, LayerAndroid* compositedRoot,
// Clean up GL textures for video layer.
TilesManager::instance()->videoLayerManager()->deleteUnusedTextures();
+ compositedRoot->prepare(m_glWebViewState);
if (compositedRoot->drawGL(m_glWebViewState, matrix))
needsRedraw = true;
else if (!animsRunning)
diff --git a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.h b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.h
index a42a372..26fd158 100644
--- a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.h
+++ b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.h
@@ -66,6 +66,8 @@ public:
void swapExtra(BaseLayerAndroid* base) { m_extra.swap(base->m_extra); }
private:
#if USE(ACCELERATED_COMPOSITING)
+ void prefetchBasePicture(SkRect& viewport, float currentScale,
+ TiledPage* prefetchTiledPage);
bool drawBasePictureInGL(SkRect& viewport, float scale, double currentTime,
bool* buffersSwappedPtr);
diff --git a/Source/WebCore/platform/graphics/android/GLWebViewState.cpp b/Source/WebCore/platform/graphics/android/GLWebViewState.cpp
index 5764a6b..55419f4 100644
--- a/Source/WebCore/platform/graphics/android/GLWebViewState.cpp
+++ b/Source/WebCore/platform/graphics/android/GLWebViewState.cpp
@@ -32,6 +32,7 @@
#include "ClassTracker.h"
#include "GLUtils.h"
#include "LayerAndroid.h"
+#include "SkPath.h"
#include "TilesManager.h"
#include "TilesTracker.h"
#include <wtf/CurrentTime.h>
@@ -59,6 +60,14 @@
#define FRAMERATE_CAP 0.01666 // We cap at 60 fps
+// Touch ring border width. This is doubled if the ring is not pressed
+#define RING_BORDER_WIDTH 1
+// Color of the ring is 0x6633b5e5 (copied from framework)
+#define RING_COLOR_ALPHA 0.4
+#define RING_COLOR_R 0x33
+#define RING_COLOR_G 0xb5
+#define RING_COLOR_B 0xe5
+
namespace WebCore {
using namespace android;
@@ -170,7 +179,13 @@ void GLWebViewState::setRings(Vector<IntRect>& rings, bool isPressed)
{
android::Mutex::Autolock lock(m_baseLayerLock);
m_displayRings = true;
- m_rings = rings;
+ m_rings.setEmpty();
+ for (size_t i = 0; i < rings.size(); i++) {
+ if (i == 0)
+ m_rings.setRect(rings.at(i));
+ else
+ m_rings.op(rings.at(i), SkRegion::kUnion_Op);
+ }
m_ringsIsPressed = isPressed;
}
@@ -247,78 +262,80 @@ void GLWebViewState::resetRings()
m_displayRings = false;
}
-void GLWebViewState::drawFocusRing(IntRect& srcRect)
+void GLWebViewState::drawFocusRing(SkRect& srcRect)
{
- // TODO: use a 9-patch texture to draw the focus ring
- // instead of plain colors
- const float alpha = 0.3;
- float borderAlpha = 0.4;
-
- const int r = 51;
- const int g = 181;
- const int b = 229;
-
- int padding = 4;
- int border = 1;
- int fuzzyBorder = border * 2;
- if (!m_ringsIsPressed) {
- padding = 0;
- border = 2;
- fuzzyBorder = 3;
- borderAlpha = 0.2;
- }
if (m_focusRingTexture == -1)
- m_focusRingTexture = GLUtils::createSampleColorTexture(r, g, b);
-
- SkRect rLeft, rTop, rRight, rBottom, rOverlay;
-
- IntRect rect(srcRect.x() - padding, srcRect.y() - padding,
- srcRect.width() + (padding * 2), srcRect.height() + (padding * 2));
- rLeft.set(rect.x() - border, rect.y(),
- rect.x(), rect.y() + rect.height());
- rTop.set(rect.x() - border, rect.y() - border,
- rect.x() + rect.width() + border, rect.y());
- rRight.set(rect.x() + rect.width(), rect.y(),
- rect.x() + rect.width() + border,
- rect.y() + rect.height());
- rBottom.set(rect.x() - border, rect.y() + rect.height(),
- rect.x() + rect.width() + border,
- rect.y() + rect.height() + border);
- rOverlay.set(rect.x() - fuzzyBorder, rect.y() - fuzzyBorder,
- rect.x() + rect.width() + fuzzyBorder,
- rect.y() + rect.height() + fuzzyBorder);
-
- TilesManager::instance()->shader()->drawQuad(rLeft, m_focusRingTexture, borderAlpha);
- TilesManager::instance()->shader()->drawQuad(rTop, m_focusRingTexture, borderAlpha);
- TilesManager::instance()->shader()->drawQuad(rRight, m_focusRingTexture, borderAlpha);
- TilesManager::instance()->shader()->drawQuad(rBottom, m_focusRingTexture, borderAlpha);
- if (m_ringsIsPressed) {
- TilesManager::instance()->shader()->drawQuad(rOverlay, m_focusRingTexture, alpha);
- } else {
- rLeft.set(rect.x() - fuzzyBorder, rect.y(),
- rect.x(), rect.y() + rect.height());
- rTop.set(rect.x() - fuzzyBorder, rect.y() - fuzzyBorder,
- rect.x() + rect.width() + fuzzyBorder, rect.y());
- rRight.set(rect.x() + rect.width(), rect.y(),
- rect.x() + rect.width() + fuzzyBorder,
- rect.y() + rect.height());
- rBottom.set(rect.x() - fuzzyBorder, rect.y() + rect.height(),
- rect.x() + rect.width() + fuzzyBorder,
- rect.y() + rect.height() + fuzzyBorder);
- TilesManager::instance()->shader()->drawQuad(rLeft, m_focusRingTexture, alpha);
- TilesManager::instance()->shader()->drawQuad(rTop, m_focusRingTexture, alpha);
- TilesManager::instance()->shader()->drawQuad(rRight, m_focusRingTexture, alpha);
- TilesManager::instance()->shader()->drawQuad(rBottom, m_focusRingTexture, alpha);
- }
+ m_focusRingTexture = GLUtils::createSampleColorTexture(RING_COLOR_R,
+ RING_COLOR_G,
+ RING_COLOR_B);
+
+ TilesManager::instance()->shader()->drawQuad(srcRect, m_focusRingTexture,
+ RING_COLOR_ALPHA);
}
void GLWebViewState::paintExtras()
{
- if (m_displayRings) {
- // TODO: handles correctly the multi-rings case
- for (size_t i = 0; i < m_rings.size(); i++) {
- IntRect rect = m_rings.at(i);
- drawFocusRing(rect);
+ if (m_displayRings && !m_rings.isEmpty()) {
+ if (m_ringsIsPressed) {
+ SkRegion::Iterator rgnIter(m_rings);
+ while (!rgnIter.done()) {
+ SkIRect ir = rgnIter.rect();
+ SkRect r;
+ r.set(ir.fLeft, ir.fTop, ir.fRight, ir.fBottom);
+ drawFocusRing(r);
+ rgnIter.next();
+ }
+ }
+ SkPath path;
+ if (!m_rings.getBoundaryPath(&path))
+ return;
+ SkPath::Iter iter(path, true);
+ SkPath::Verb verb;
+ SkPoint pts[4];
+ SkRegion clip;
+ SkIRect startRect;
+ while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
+ if (verb == SkPath::kLine_Verb) {
+ SkRect r;
+ r.set(pts, 2);
+ SkIRect line;
+ int borderWidth = RING_BORDER_WIDTH;
+ if (!m_ringsIsPressed)
+ borderWidth *= 2;
+ line.fLeft = r.fLeft - borderWidth;
+ line.fRight = r.fRight + borderWidth;
+ line.fTop = r.fTop - borderWidth;
+ line.fBottom = r.fBottom + borderWidth;
+ if (clip.intersects(line)) {
+ clip.op(line, SkRegion::kReverseDifference_Op);
+ if (clip.isEmpty())
+ continue; // Nothing to draw, continue
+ line = clip.getBounds();
+ if (SkIRect::Intersects(startRect, line)) {
+ clip.op(startRect, SkRegion::kDifference_Op);
+ if (clip.isEmpty())
+ continue; // Nothing to draw, continue
+ line = clip.getBounds();
+ }
+ } else {
+ clip.setRect(line);
+ }
+ r.set(line.fLeft, line.fTop, line.fRight, line.fBottom);
+ drawFocusRing(r);
+ if (!m_ringsIsPressed) {
+ r.fLeft += RING_BORDER_WIDTH;
+ r.fRight -= RING_BORDER_WIDTH;
+ r.fTop += RING_BORDER_WIDTH;
+ r.fBottom -= RING_BORDER_WIDTH;
+ drawFocusRing(r);
+ }
+ if (startRect.isEmpty()) {
+ startRect.set(line.fLeft, line.fTop, line.fRight, line.fBottom);
+ }
+ }
+ if (verb == SkPath::kMove_Verb) {
+ startRect.setEmpty();
+ }
}
}
}
@@ -558,6 +575,10 @@ bool GLWebViewState::drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect,
double currentTime = setupDrawing(rect, viewport, webViewRect, titleBarHeight, clip, scale);
bool ret = baseLayer->drawGL(currentTime, compositedRoot, rect,
viewport, scale, buffersSwappedPtr);
+ // Reset the clip to make sure we can draw the rings. If this isn't done, the
+ // current clip will be the clip of whatever layer was last drawn
+ TilesManager::instance()->shader()->clip(clip);
+ paintExtras();
glBindBuffer(GL_ARRAY_BUFFER, 0);
diff --git a/Source/WebCore/platform/graphics/android/GLWebViewState.h b/Source/WebCore/platform/graphics/android/GLWebViewState.h
index a7803de..6c7d31e 100644
--- a/Source/WebCore/platform/graphics/android/GLWebViewState.h
+++ b/Source/WebCore/platform/graphics/android/GLWebViewState.h
@@ -179,7 +179,7 @@ public:
void setRings(Vector<IntRect>& rings, bool isPressed);
void resetRings();
- void drawFocusRing(IntRect& rect);
+ void drawFocusRing(SkRect& rect);
TiledPage* sibling(TiledPage* page);
TiledPage* frontPage();
@@ -269,7 +269,7 @@ private:
bool m_measurePerfs;
#endif
bool m_displayRings;
- Vector<IntRect> m_rings;
+ SkRegion m_rings;
bool m_ringsIsPressed;
int m_focusRingTexture;
diff --git a/Source/WebCore/platform/graphics/android/Layer.cpp b/Source/WebCore/platform/graphics/android/Layer.cpp
index 22c40f1..361cb4e 100644
--- a/Source/WebCore/platform/graphics/android/Layer.cpp
+++ b/Source/WebCore/platform/graphics/android/Layer.cpp
@@ -18,9 +18,9 @@ Layer::Layer() {
m_position.set(0, 0);
m_anchorPoint.set(SK_ScalarHalf, SK_ScalarHalf);
- fMatrix.reset();
- fChildrenMatrix.reset();
- fFlags = 0;
+ m_matrix.reset();
+ m_childrenMatrix.reset();
+ m_shouldInheritFromRootTransform = false;
m_hasOverflowChildren = false;
@@ -37,9 +37,9 @@ Layer::Layer(const Layer& src) : INHERITED() {
m_position = src.m_position;
m_anchorPoint = src.m_anchorPoint;
- fMatrix = src.fMatrix;
- fChildrenMatrix = src.fChildrenMatrix;
- fFlags = src.fFlags;
+ m_matrix = src.m_matrix;
+ m_childrenMatrix = src.m_childrenMatrix;
+ m_shouldInheritFromRootTransform = src.m_shouldInheritFromRootTransform;
m_hasOverflowChildren = src.m_hasOverflowChildren;
@@ -50,7 +50,7 @@ Layer::Layer(const Layer& src) : INHERITED() {
}
Layer::~Layer() {
- this->removeChildren();
+ removeChildren();
#ifdef DEBUG_TRACK_NEW_DELETE
gLayerAllocCount -= 1;
@@ -60,28 +60,6 @@ Layer::~Layer() {
///////////////////////////////////////////////////////////////////////////////
-bool Layer::isInheritFromRootTransform() const {
- return (fFlags & kInheritFromRootTransform_Flag) != 0;
-}
-
-void Layer::setInheritFromRootTransform(bool doInherit) {
- if (doInherit) {
- fFlags |= kInheritFromRootTransform_Flag;
- } else {
- fFlags &= ~kInheritFromRootTransform_Flag;
- }
-}
-
-void Layer::setMatrix(const SkMatrix& matrix) {
- fMatrix = matrix;
-}
-
-void Layer::setChildrenMatrix(const SkMatrix& matrix) {
- fChildrenMatrix = matrix;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
int Layer::countChildren() const {
return m_children.count();
}
@@ -111,7 +89,7 @@ void Layer::detachFromParent() {
SkASSERT(index >= 0);
fParent->m_children.remove(index);
fParent = NULL;
- this->unref(); // this call might delete us
+ unref(); // this call might delete us
}
}
@@ -142,15 +120,15 @@ void Layer::getLocalTransform(SkMatrix* matrix) const {
SkScalar tx = SkScalarMul(m_anchorPoint.fX, m_size.width());
SkScalar ty = SkScalarMul(m_anchorPoint.fY, m_size.height());
matrix->preTranslate(tx, ty);
- matrix->preConcat(this->getMatrix());
+ matrix->preConcat(getMatrix());
matrix->preTranslate(-tx, -ty);
}
void Layer::localToGlobal(SkMatrix* matrix) const {
- this->getLocalTransform(matrix);
+ getLocalTransform(matrix);
- if (this->isInheritFromRootTransform()) {
- matrix->postConcat(this->getRootLayer()->getMatrix());
+ if (shouldInheritFromRootTransform()) {
+ matrix->postConcat(getRootLayer()->getMatrix());
return;
}
@@ -176,14 +154,14 @@ void Layer::onDraw(SkCanvas*, SkScalar opacity) {
void Layer::draw(SkCanvas* canvas, SkScalar opacity) {
#if 0
SkString str1, str2;
- // this->getMatrix().toDumpString(&str1);
- // this->getChildrenMatrix().toDumpString(&str2);
+ // getMatrix().toDumpString(&str1);
+ // getChildrenMatrix().toDumpString(&str2);
SkDebugf("--- drawlayer %p opacity %g size [%g %g] pos [%g %g] matrix %s children %s\n",
- this, opacity * this->getOpacity(), m_size.width(), m_size.height(),
+ this, opacity * getOpacity(), m_size.width(), m_size.height(),
m_position.fX, m_position.fY, str1.c_str(), str2.c_str());
#endif
- opacity = SkScalarMul(opacity, this->getOpacity());
+ opacity = SkScalarMul(opacity, getOpacity());
if (opacity <= 0) {
// SkDebugf("---- abort drawing %p opacity %g\n", this, opacity);
return;
@@ -194,19 +172,19 @@ void Layer::draw(SkCanvas* canvas, SkScalar opacity) {
// apply our local transform
{
SkMatrix tmp;
- this->getLocalTransform(&tmp);
- if (this->isInheritFromRootTransform()) {
+ getLocalTransform(&tmp);
+ if (shouldInheritFromRootTransform()) {
// should we also apply the root's childrenMatrix?
canvas->setMatrix(getRootLayer()->getMatrix());
}
canvas->concat(tmp);
}
- this->onDraw(canvas, opacity);
+ onDraw(canvas, opacity);
#ifdef DEBUG_DRAW_LAYER_BOUNDS
{
- SkRect r = SkRect::MakeSize(this->getSize());
+ SkRect r = SkRect::MakeSize(getSize());
SkPaint p;
p.setAntiAlias(true);
p.setStyle(SkPaint::kStroke_Style);
@@ -218,11 +196,11 @@ void Layer::draw(SkCanvas* canvas, SkScalar opacity) {
}
#endif
- int count = this->countChildren();
+ int count = countChildren();
if (count > 0) {
- canvas->concat(this->getChildrenMatrix());
+ canvas->concat(getChildrenMatrix());
for (int i = 0; i < count; i++) {
- this->getChild(i)->draw(canvas, opacity);
+ getChild(i)->draw(canvas, opacity);
}
}
}
diff --git a/Source/WebCore/platform/graphics/android/Layer.h b/Source/WebCore/platform/graphics/android/Layer.h
index 6450fde..7b27349 100644
--- a/Source/WebCore/platform/graphics/android/Layer.h
+++ b/Source/WebCore/platform/graphics/android/Layer.h
@@ -34,24 +34,27 @@ public:
Layer(const Layer&);
virtual ~Layer();
- bool isInheritFromRootTransform() const;
+ // Whether the layer should apply its tranform directly onto the root
+ // layer, rather than using the transforms of all ancestor layers. This is
+ // used for fixed position layers.
+ bool shouldInheritFromRootTransform() const { return m_shouldInheritFromRootTransform; }
SkScalar getOpacity() const { return m_opacity; }
const SkSize& getSize() const { return m_size; }
const SkPoint& getPosition() const { return m_position; }
const SkPoint& getAnchorPoint() const { return m_anchorPoint; }
- const SkMatrix& getMatrix() const { return fMatrix; }
- const SkMatrix& getChildrenMatrix() const { return fChildrenMatrix; }
+ const SkMatrix& getMatrix() const { return m_matrix; }
+ const SkMatrix& getChildrenMatrix() const { return m_childrenMatrix; }
SkScalar getWidth() const { return m_size.width(); }
SkScalar getHeight() const { return m_size.height(); }
- void setInheritFromRootTransform(bool);
+ void setShouldInheritFromRootTransform(bool inherit) { m_shouldInheritFromRootTransform = inherit; }
void setOpacity(SkScalar opacity) { m_opacity = opacity; }
void setSize(SkScalar w, SkScalar h) { m_size.set(w, h); }
void setPosition(SkScalar x, SkScalar y) { m_position.set(x, y); }
void setAnchorPoint(SkScalar x, SkScalar y) { m_anchorPoint.set(x, y); }
- void setMatrix(const SkMatrix&);
- void setChildrenMatrix(const SkMatrix&);
+ void setMatrix(const SkMatrix& matrix) { m_matrix = matrix; }
+ void setChildrenMatrix(const SkMatrix& matrix) { m_childrenMatrix = matrix; }
// children
@@ -118,18 +121,17 @@ protected:
bool m_hasOverflowChildren;
private:
- enum Flags {
- kInheritFromRootTransform_Flag = 0x01
- };
-
- Layer* fParent;
- SkScalar m_opacity;
- SkSize m_size;
- SkPoint m_position;
- SkPoint m_anchorPoint;
- SkMatrix fMatrix;
- SkMatrix fChildrenMatrix;
- uint32_t fFlags;
+ Layer* fParent;
+ SkScalar m_opacity;
+ SkSize m_size;
+ // The position of the origin of the layer, relative to the parent layer.
+ SkPoint m_position;
+ // The point in the layer used as the origin for local transformations,
+ // expressed as a fraction of the layer size.
+ SkPoint m_anchorPoint;
+ SkMatrix m_matrix;
+ SkMatrix m_childrenMatrix;
+ bool m_shouldInheritFromRootTransform;
SkTDArray<Layer*> m_children;
diff --git a/Source/WebCore/platform/graphics/android/LayerAndroid.cpp b/Source/WebCore/platform/graphics/android/LayerAndroid.cpp
index 48dcaaa..a39614f 100644
--- a/Source/WebCore/platform/graphics/android/LayerAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/LayerAndroid.cpp
@@ -267,7 +267,7 @@ void LayerAndroid::removeAnimationsForKeyframes(const String& name)
}
// We only use the bounding rect of the layer as mask...
-// TODO: use a real mask?
+// FIXME: use a real mask?
void LayerAndroid::setMaskLayer(LayerAndroid* layer)
{
if (layer)
@@ -546,7 +546,7 @@ void LayerAndroid::updatePositions()
if (!m_isFixed) {
// turn our fields into a matrix.
//
- // TODO: this should happen in the caller, and we should remove these
+ // FIXME: this should happen in the caller, and we should remove these
// fields from our subclass
SkMatrix matrix;
GLUtils::toSkMatrix(matrix, m_transform);
@@ -793,6 +793,26 @@ void LayerAndroid::clearDirtyRegion()
m_dirtyRegion.setEmpty();
}
+void LayerAndroid::prepare(GLWebViewState* glWebViewState)
+{
+ int count = this->countChildren();
+ if (count > 0) {
+ Vector <LayerAndroid*> sublayers;
+ for (int i = 0; i < count; i++)
+ sublayers.append(this->getChild(i));
+
+ // now we sort for the transparency
+ std::stable_sort(sublayers.begin(), sublayers.end(), compareLayerZ);
+
+ // iterate in reverse so top layers get textures first
+ for (int i = count-1; i >= 0; i--)
+ sublayers[i]->prepare(glWebViewState);
+ }
+
+ if (m_texture)
+ m_texture->prepare(glWebViewState);
+}
+
bool LayerAndroid::drawGL(GLWebViewState* glWebViewState, SkMatrix& matrix)
{
TilesManager::instance()->shader()->clip(m_clippingRect);
@@ -801,10 +821,8 @@ bool LayerAndroid::drawGL(GLWebViewState* glWebViewState, SkMatrix& matrix)
bool askPaint = false;
- if (m_texture) {
- m_texture->prepare(glWebViewState);
+ if (m_texture)
askPaint |= m_texture->draw();
- }
// When the layer is dirty, the UI thread should be notified to redraw.
askPaint |= drawChildrenGL(glWebViewState, matrix);
@@ -817,7 +835,6 @@ bool LayerAndroid::drawGL(GLWebViewState* glWebViewState, SkMatrix& matrix)
return askPaint;
}
-
bool LayerAndroid::drawChildrenGL(GLWebViewState* glWebViewState, SkMatrix& matrix)
{
bool askPaint = false;
@@ -926,6 +943,11 @@ SkRect LayerAndroid::subtractLayers(const SkRect& visibleRect) const
{
SkRect result;
if (m_recordingPicture) {
+ // FIXME: This seems wrong. localToGlobal() applies the full local transform,
+ // se surely we should operate globalMatrix on size(), not bounds() with
+ // the position removed? Perhaps we never noticed the bug because most
+ // layers don't use a local transform?
+ // See http://b/5338388
SkRect globalRect = bounds();
globalRect.offset(-getPosition()); // localToGlobal adds in position
SkMatrix globalMatrix;
diff --git a/Source/WebCore/platform/graphics/android/LayerAndroid.h b/Source/WebCore/platform/graphics/android/LayerAndroid.h
index 7192aaf..31bb185 100644
--- a/Source/WebCore/platform/graphics/android/LayerAndroid.h
+++ b/Source/WebCore/platform/graphics/android/LayerAndroid.h
@@ -109,6 +109,10 @@ public:
void setBackfaceVisibility(bool value) { m_backfaceVisibility = value; }
void setTransform(const TransformationMatrix& matrix) { m_transform = matrix; }
FloatPoint translation() const;
+ // Returns a rect describing the bounds of the layer with the local
+ // transformation applied, expressed relative to the parent layer.
+ // FIXME: Currently we use only the translation component of the local
+ // transformation.
SkRect bounds() const;
IntRect clippedRect() const;
bool outsideViewport();
@@ -121,8 +125,14 @@ public:
void showLayer(int indent);
float getScale() { return m_scale; }
+
+ // draw layer and its children via Z, pre-order traversal
virtual bool drawGL(GLWebViewState*, SkMatrix&);
bool drawChildrenGL(GLWebViewState*, SkMatrix&);
+
+ // prepare layer and its children via reverse-Z, post-order traversal
+ void prepare(GLWebViewState*);
+
void updateGLPositionsAndScale(const TransformationMatrix& parentMatrix,
const FloatRect& clip, float opacity, float scale);
void setDrawOpacity(float opacity) { m_drawOpacity = opacity; }
@@ -160,7 +170,7 @@ public:
m_fixedRect = viewRect;
m_isFixed = true;
m_renderLayerPos = renderLayerPos;
- setInheritFromRootTransform(true);
+ setShouldInheritFromRootTransform(true);
}
void setBackgroundColor(SkColor color);
@@ -183,9 +193,10 @@ public:
SkPicture* picture() const { return m_recordingPicture; }
- // remove layers bounds from visible rectangle to show what can be
- // scrolled into view; returns original minus layer bounds in global space.
- SkRect subtractLayers(const SkRect& visibleRect) const;
+ // Given a rect in global space, subtracts from it the bounds of this layer
+ // and of all of its children. Returns the bounding rectangle of the result,
+ // in global space.
+ SkRect subtractLayers(const SkRect&) const;
void dumpLayers(FILE*, int indentLevel) const;
void dumpToLog() const;
diff --git a/Source/WebCore/platform/graphics/android/PaintTileOperation.cpp b/Source/WebCore/platform/graphics/android/PaintTileOperation.cpp
index aa3f320..19b49f1 100644
--- a/Source/WebCore/platform/graphics/android/PaintTileOperation.cpp
+++ b/Source/WebCore/platform/graphics/android/PaintTileOperation.cpp
@@ -81,6 +81,10 @@ int PaintTileOperation::priority()
unsigned long long drawDelta = currentDraw - m_tile->drawCount();
int priority = 100000 * (int)std::min(drawDelta, (unsigned long long)1000);
+ // prioritize the prefetch page, if it exists
+ if (!m_tile->page() || !m_tile->page()->isPrefetchPage())
+ priority += 200000;
+
// prioritize unpainted tiles, within the same drawCount
if (m_tile->frontTexture())
priority += 50000;
diff --git a/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.cpp
index ca8f03c..2bb8b5c 100644
--- a/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.cpp
@@ -18,10 +18,7 @@ bool ScrollableLayerAndroid::scrollTo(int x, int y)
if (newX == scrollBounds.fLeft && newY == scrollBounds.fTop)
return false;
- SkScalar diffX = newX - scrollBounds.fLeft;
- SkScalar diffY = newY - scrollBounds.fTop;
- const SkPoint& pos = getPosition();
- setPosition(pos.fX - diffX, pos.fY - diffY);
+ setPosition(m_scrollLimits.fLeft - newX, m_scrollLimits.fTop - newY);
return true;
}
diff --git a/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.h b/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.h
index c3fdecd..b59b4e1 100644
--- a/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.h
+++ b/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.h
@@ -42,15 +42,16 @@ public:
virtual LayerAndroid* copy() const { return new ScrollableLayerAndroid(*this); }
- // Returns true if the content position has changed.
- bool scrollTo(int dx, int dy);
+ // Scrolls to the given position in the layer.
+ // Returns whether or not any scrolling was required.
+ bool scrollTo(int x, int y);
- // Fills the rect with the current scroll offset and the maximum scroll.
+ // Fills the rect with the current scroll offset and the maximum scroll offset.
// fLeft = scrollX
// fTop = scrollY
- // fRight = maxX
- // fBottom = maxY
- void getScrollRect(SkIRect* out) const;
+ // fRight = maxScrollX
+ // fBottom = maxScrollY
+ void getScrollRect(SkIRect*) const;
void setScrollLimits(float x, float y, float width, float height)
{
@@ -61,6 +62,9 @@ public:
friend LayerAndroid* android::deserializeLayer(SkStream* stream);
private:
+ // The position of the visible area of the layer, relative to the parent
+ // layer. This is fixed during scrolling. We acheive scrolling by modifying
+ // the position of the layer.
SkRect m_scrollLimits;
};
diff --git a/Source/WebCore/platform/graphics/android/ShaderProgram.cpp b/Source/WebCore/platform/graphics/android/ShaderProgram.cpp
index bf5f760..857623a 100644
--- a/Source/WebCore/platform/graphics/android/ShaderProgram.cpp
+++ b/Source/WebCore/platform/graphics/android/ShaderProgram.cpp
@@ -294,6 +294,7 @@ void ShaderProgram::drawQuadInternal(SkRect& geometry,
GLenum textureTarget,
GLint position,
GLint alpha,
+ GLint texFilter,
GLint contrast)
{
glUseProgram(program);
@@ -313,8 +314,8 @@ void ShaderProgram::drawQuadInternal(SkRect& geometry,
glActiveTexture(GL_TEXTURE0);
glUniform1i(texSampler, 0);
glBindTexture(textureTarget, textureId);
- glTexParameteri(textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(textureTarget, GL_TEXTURE_MIN_FILTER, texFilter);
+ glTexParameteri(textureTarget, GL_TEXTURE_MAG_FILTER, texFilter);
glTexParameteri(textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
@@ -330,26 +331,26 @@ void ShaderProgram::drawQuadInternal(SkRect& geometry,
}
void ShaderProgram::drawQuad(SkRect& geometry, int textureId, float opacity,
- GLenum textureTarget)
+ GLenum textureTarget, GLint texFilter)
{
if (textureTarget == GL_TEXTURE_2D) {
drawQuadInternal(geometry, textureId, opacity, m_program,
m_hProjectionMatrix,
m_hTexSampler, GL_TEXTURE_2D,
- m_hPosition, alpha());
+ m_hPosition, alpha(), texFilter);
} else if (textureTarget == GL_TEXTURE_EXTERNAL_OES
&& !TilesManager::instance()->invertedScreen()) {
drawQuadInternal(geometry, textureId, opacity, m_surfTexOESProgram,
m_hSTOESProjectionMatrix,
m_hSTOESTexSampler, GL_TEXTURE_EXTERNAL_OES,
- m_hSTOESPosition, m_hSTOESAlpha);
+ m_hSTOESPosition, m_hSTOESAlpha, texFilter);
} else if (textureTarget == GL_TEXTURE_EXTERNAL_OES
&& TilesManager::instance()->invertedScreen()) {
drawQuadInternal(geometry, textureId, opacity, m_surfTexOESProgramInverted,
m_hSTOESProjectionMatrixInverted,
m_hSTOESTexSamplerInverted, GL_TEXTURE_EXTERNAL_OES,
m_hSTOESPositionInverted, m_hSTOESAlphaInverted,
- m_hSTOESContrastInverted);
+ texFilter, m_hSTOESContrastInverted);
}
GLUtils::checkGlError("drawQuad");
}
diff --git a/Source/WebCore/platform/graphics/android/ShaderProgram.h b/Source/WebCore/platform/graphics/android/ShaderProgram.h
index d8447bf..5f5ce9f 100644
--- a/Source/WebCore/platform/graphics/android/ShaderProgram.h
+++ b/Source/WebCore/platform/graphics/android/ShaderProgram.h
@@ -54,7 +54,8 @@ public:
// support Surface texture in GL_TEXTURE_EXTERNAL_OES target on all
// platforms.
void drawQuad(SkRect& geometry, int textureId, float opacity,
- GLenum textureTarget = GL_TEXTURE_2D);
+ GLenum textureTarget = GL_TEXTURE_2D,
+ GLint texFilter = GL_LINEAR);
void drawLayerQuad(const TransformationMatrix& drawMatrix,
SkRect& geometry, int textureId, float opacity,
bool forceBlending = false,
@@ -99,7 +100,8 @@ private:
void drawQuadInternal(SkRect& geometry, GLint textureId, float opacity,
GLint program, GLint projectionMatrixHandle,
GLint texSampler, GLenum textureTarget,
- GLint position, GLint alpha, GLint contrast = -1);
+ GLint position, GLint alpha,
+ GLint texFilter, GLint contrast = -1);
void drawLayerQuadInternal(const GLfloat* projectionMatrix, int textureId,
float opacity, GLenum textureTarget, GLint program,
diff --git a/Source/WebCore/platform/graphics/android/TiledPage.cpp b/Source/WebCore/platform/graphics/android/TiledPage.cpp
index ede7d1b..2b8ebcc 100644
--- a/Source/WebCore/platform/graphics/android/TiledPage.cpp
+++ b/Source/WebCore/platform/graphics/android/TiledPage.cpp
@@ -31,6 +31,8 @@
#include "GLUtils.h"
#include "IntRect.h"
#include "PaintTileOperation.h"
+#include "SkPaint.h"
+#include "SkPaintFlagsDrawFilter.h"
#include "TilesManager.h"
#include <cutils/log.h>
@@ -65,6 +67,7 @@ TiledPage::TiledPage(int id, GLWebViewState* state)
, m_glWebViewState(state)
, m_latestPictureInval(0)
, m_prepare(false)
+ , m_isPrefetchPage(false)
{
m_baseTiles = new BaseTile[TilesManager::getMaxTextureAllocation() + 1];
#ifdef DEBUG_COUNT
@@ -366,9 +369,15 @@ void TiledPage::draw(float transparency, const SkIRect& tileBounds)
bool TiledPage::paint(BaseTile* tile, SkCanvas* canvas, unsigned int* pictureUsed)
{
+ // TODO: consider other flags so the pre-rendered tiles aren't so ugly
+ static SkPaintFlagsDrawFilter prefetchFilter(SkPaint::kAllFlags, 0);
+
if (!m_glWebViewState)
return false;
+ if (isPrefetchPage())
+ canvas->setDrawFilter(&prefetchFilter);
+
*pictureUsed = m_glWebViewState->paintBaseLayerContent(canvas);
return true;
}
diff --git a/Source/WebCore/platform/graphics/android/TiledPage.h b/Source/WebCore/platform/graphics/android/TiledPage.h
index 946421c..c903abc 100644
--- a/Source/WebCore/platform/graphics/android/TiledPage.h
+++ b/Source/WebCore/platform/graphics/android/TiledPage.h
@@ -98,6 +98,8 @@ public:
void updateBaseTileSize();
bool scrollingDown() { return m_scrollingDown; }
SkIRect* expandedTileBounds() { return &m_expandedTileBounds; }
+ bool isPrefetchPage() { return m_isPrefetchPage; }
+ void setIsPrefetchPage(bool isPrefetch) { m_isPrefetchPage = isPrefetch; }
private:
void prepareRow(bool goingLeft, int tilesInRow, int firstTileX, int y, const SkIRect& tileBounds);
@@ -127,6 +129,7 @@ private:
bool m_prepare;
bool m_scrollingDown;
SkIRect m_expandedTileBounds;
+ bool m_isPrefetchPage;
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/TransferQueue.cpp b/Source/WebCore/platform/graphics/android/TransferQueue.cpp
index 918d484..a8451a6 100644
--- a/Source/WebCore/platform/graphics/android/TransferQueue.cpp
+++ b/Source/WebCore/platform/graphics/android/TransferQueue.cpp
@@ -135,9 +135,6 @@ void TransferQueue::blitTileFromQueue(GLuint fboID, BaseTileTexture* destTex,
GLuint srcTexId, GLenum srcTexTarget,
int index)
{
- // guarantee that we have a texture to blit into
- destTex->requireTexture();
-
// Then set up the FBO and copy the SurfTex content in.
glBindFramebuffer(GL_FRAMEBUFFER, fboID);
glFramebufferTexture2D(GL_FRAMEBUFFER,
@@ -157,7 +154,7 @@ void TransferQueue::blitTileFromQueue(GLuint fboID, BaseTileTexture* destTex,
// Use empty rect to set up the special matrix to draw.
SkRect rect = SkRect::MakeEmpty();
TilesManager::instance()->shader()->drawQuad(rect, srcTexId, 1.0,
- srcTexTarget);
+ srcTexTarget, GL_NEAREST);
// To workaround a sync issue on some platforms, we should insert the sync
// here while in the current FBO.
@@ -260,7 +257,9 @@ void TransferQueue::discardQueue()
// Call on UI thread to copy from the shared Surface Texture to the BaseTile's texture.
void TransferQueue::updateDirtyBaseTiles()
{
+#if !DEBUG_TRANSFER_USING_CPU_UPLOAD
saveGLState();
+#endif
android::Mutex::Autolock lock(m_transferQueueItemLocks);
cleanupTransportQueue();
@@ -279,9 +278,9 @@ void TransferQueue::updateDirtyBaseTiles()
BaseTileTexture* destTexture = 0;
if (!obsoleteBaseTile)
destTexture = m_transferQueue[index].savedBaseTilePtr->backTexture();
-
+#if !DEBUG_TRANSFER_USING_CPU_UPLOAD
m_sharedSurfaceTexture->updateTexImage();
-
+#endif
m_transferQueue[index].savedBaseTilePtr = 0;
m_transferQueue[index].status = emptyItem;
if (obsoleteBaseTile) {
@@ -290,6 +289,9 @@ void TransferQueue::updateDirtyBaseTiles()
continue;
}
+ // guarantee that we have a texture to blit into
+ destTexture->requireTexture();
+
#if DEBUG_TRANSFER_USING_CPU_UPLOAD
// Here we just need to upload the bitmap content to the GL Texture
GLUtils::updateTextureWithBitmap(destTexture->m_ownTextureId, 0, 0,
@@ -317,7 +319,9 @@ void TransferQueue::updateDirtyBaseTiles()
index = (index + 1) % ST_BUFFER_NUMBER;
}
+#if !DEBUG_TRANSFER_USING_CPU_UPLOAD
restoreGLState();
+#endif
m_emptyItemCount = ST_BUFFER_NUMBER;
m_transferQueueItemCond.signal();
@@ -334,7 +338,7 @@ void TransferQueue::updateQueueWithBitmap(const TileRenderInfo* renderInfo,
renderInfo->x, renderInfo->y);
return;
}
-
+#if !DEBUG_TRANSFER_USING_CPU_UPLOAD
// a) Dequeue the Surface Texture and write into the buffer
if (!m_ANW.get()) {
XLOG("ERROR: ANW is null");
@@ -370,6 +374,7 @@ void TransferQueue::updateQueueWithBitmap(const TileRenderInfo* renderInfo,
}
ANativeWindow_unlockAndPost(m_ANW.get());
+#endif
m_transferQueueItemLocks.lock();
// b) After update the Surface Texture, now udpate the transfer queue info.
addItemInTransferQueue(renderInfo);
@@ -417,8 +422,9 @@ void TransferQueue::cleanupTransportQueue()
for (int i = 0 ; i < ST_BUFFER_NUMBER; i++) {
if (m_transferQueue[index].status == pendingDiscard) {
+#if !DEBUG_TRANSFER_USING_CPU_UPLOAD
m_sharedSurfaceTexture->updateTexImage();
-
+#endif
m_transferQueue[index].savedBaseTilePtr = 0;
m_transferQueue[index].status = emptyItem;
}
@@ -455,7 +461,7 @@ void TransferQueue::restoreGLState()
if (m_GLStateBeforeBlit.scissor[0])
glEnable(GL_SCISSOR_TEST);
- if (m_GLStateBeforeBlit.depth)
+ if (m_GLStateBeforeBlit.depth[0])
glEnable(GL_DEPTH_TEST);
glClearColor(m_GLStateBeforeBlit.clearColor[0],
diff --git a/Source/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.cpp b/Source/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.cpp
index 9de6c09..3134a44 100644
--- a/Source/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.cpp
+++ b/Source/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.cpp
@@ -373,10 +373,16 @@ void FrameLoaderClientAndroid::dispatchDidFailProvisionalLoad(const ResourceErro
url.append(buf, res);
}
}
+ // Vector sets up its data buffer lazilly, so if failingUrl is the empty
+ // string, the data buffer will be null. This will result in sanitizedUrl
+ // being null, and the string substitution below will be a no-op.
+ // FIXME: Ideally we'd always have a non-empty URL, or at least improve the
+ // wording of the error page in this case. See http://b/5293782.
+ String sanitizedUrl = url.data() ? String(url.data(), url.size()) : "";
// Replace all occurances of %s with the failing url.
String s = UTF8Encoding().decode((const char*)a->getBuffer(false), a->getLength());
- s = s.replace("%s", String(url.data(), url.size()));
+ s = s.replace("%s", sanitizedUrl);
// Replace all occurances of %e with the error text
s = s.replace("%e", error.localizedDescription());
@@ -913,6 +919,10 @@ void FrameLoaderClientAndroid::transitionToCommittedFromCachedFrame(WebCore::Cac
#ifdef ANDROID_META_SUPPORT
platformData->restoreMetadata(m_frame->settings());
#endif
+ WebViewCore* webViewCore = WebViewCore::getWebViewCore(m_frame->view());
+
+ webViewCore->clearContent();
+
m_webFrame->transitionToCommitted(m_frame);
}
@@ -946,6 +956,7 @@ void FrameLoaderClientAndroid::transitionToCommittedForNewPage() {
// Create a new WebFrameView for the new FrameView
WebFrameView* newFrameView = new WebFrameView(m_frame->view(), webViewCore);
+ webViewCore->clearContent();
newFrameView->setLocation(bounds.x(), bounds.y());
newFrameView->setSize(bounds.width(), bounds.height());
newFrameView->setVisibleSize(visBounds.width(), visBounds.height());
diff --git a/Source/WebKit/android/jni/JavaSharedClient.cpp b/Source/WebKit/android/jni/JavaSharedClient.cpp
index e884c99..4f40355 100644
--- a/Source/WebKit/android/jni/JavaSharedClient.cpp
+++ b/Source/WebKit/android/jni/JavaSharedClient.cpp
@@ -117,7 +117,7 @@ namespace android {
void (*proc)(void*) = 0;
void* payload = 0;
const FuncPtrRec* rec;
-
+
// we have to copy the proc/payload (if present). we do this so we
// don't call the proc inside the mutex (possible deadlock!)
gFuncPtrQMutex.acquire();
@@ -128,7 +128,7 @@ namespace android {
gFuncPtrQ.pop_front();
}
gFuncPtrQMutex.release();
-
+
if (!rec)
break;
proc(payload);
diff --git a/Source/WebKit/android/jni/ViewStateSerializer.cpp b/Source/WebKit/android/jni/ViewStateSerializer.cpp
index 794c118..b3556c3 100644
--- a/Source/WebKit/android/jni/ViewStateSerializer.cpp
+++ b/Source/WebKit/android/jni/ViewStateSerializer.cpp
@@ -257,7 +257,7 @@ void serializeLayer(LayerAndroid* layer, SkWStream* stream)
stream->write8(type);
// Start with Layer fields
- stream->writeBool(layer->isInheritFromRootTransform());
+ stream->writeBool(layer->shouldInheritFromRootTransform());
stream->writeScalar(layer->getOpacity());
stream->writeScalar(layer->getSize().width());
stream->writeScalar(layer->getSize().height());
@@ -338,7 +338,7 @@ LayerAndroid* deserializeLayer(SkStream* stream)
}
// Layer fields
- layer->setInheritFromRootTransform(stream->readBool());
+ layer->setShouldInheritFromRootTransform(stream->readBool());
layer->setOpacity(stream->readScalar());
layer->setSize(stream->readScalar(), stream->readScalar());
layer->setPosition(stream->readScalar(), stream->readScalar());
diff --git a/Source/WebKit/android/jni/WebCoreFrameBridge.cpp b/Source/WebKit/android/jni/WebCoreFrameBridge.cpp
index f243b09..46499b1 100644
--- a/Source/WebKit/android/jni/WebCoreFrameBridge.cpp
+++ b/Source/WebKit/android/jni/WebCoreFrameBridge.cpp
@@ -1479,11 +1479,6 @@ static void LoadUrl(JNIEnv *env, jobject obj, jstring url, jobject headers)
}
LOGV("LoadUrl %s", kurl.string().latin1().data());
pFrame->loader()->load(request, false);
-
- // Loading a new URL, clear the picture set.
- WebCore::FrameView* view = pFrame->view();
- if (view)
- WebViewCore::getWebViewCore(view)->clearContent();
}
static void PostUrl(JNIEnv *env, jobject obj, jstring url, jbyteArray postData)
diff --git a/Source/WebKit/android/jni/WebViewCore.cpp b/Source/WebKit/android/jni/WebViewCore.cpp
index 9b5a6fa..24266f6 100644
--- a/Source/WebKit/android/jni/WebViewCore.cpp
+++ b/Source/WebKit/android/jni/WebViewCore.cpp
@@ -1729,7 +1729,7 @@ Vector<IntRect> WebViewCore::getTouchHighlightRects(int x, int y, int slop)
Node* eventNode = it->get();
while (eventNode) {
RenderObject* render = eventNode->renderer();
- if (render->isBody() || render->isRenderView())
+ if (render && (render->isBody() || render->isRenderView()))
break;
if (eventNode->supportsFocus()
|| eventNode->hasEventListeners(eventNames().clickEvent)
@@ -1755,7 +1755,7 @@ Vector<IntRect> WebViewCore::getTouchHighlightRects(int x, int y, int slop)
// If the fat point touches everyone, the order in the list should be "b", "d", "c"
// and "a". When we search for the event node for "b", we really don't want "a" as
// in the z-order it is behind everything else.
- if (!render->style()->hasAutoZIndex())
+ if (render && !render->style()->hasAutoZIndex())
break;
eventNode = eventNode->parentNode();
}
@@ -2189,6 +2189,11 @@ void WebViewCore::setSelection(int start, int end)
String WebViewCore::modifySelection(const int direction, const int axis)
{
DOMSelection* selection = m_mainFrame->domWindow()->getSelection();
+ ASSERT(selection);
+ // We've seen crashes where selection is null, but we don't know why
+ // See http://b/5244036
+ if (!selection)
+ return String();
if (selection->rangeCount() > 1)
selection->removeAllRanges();
switch (axis) {
@@ -2219,12 +2224,16 @@ void WebViewCore::scrollNodeIntoView(Frame* frame, Node* node)
if (!node->isElementNode()) {
HTMLElement* body = frame->document()->body();
do {
- if (!node || node == body)
+ if (node == body)
return;
node = node->parentNode();
- } while (!node->isElementNode() && !isVisible(node));
+ } while (node && !node->isElementNode() && !isVisible(node));
}
+ // Couldn't find a visible predecessor.
+ if (!node)
+ return;
+
elementNode = static_cast<Element*>(node);
elementNode->scrollIntoViewIfNeeded(true);
}
diff --git a/Source/WebKit/android/nav/FindCanvas.cpp b/Source/WebKit/android/nav/FindCanvas.cpp
index 2d310b3..ca3cfba 100644
--- a/Source/WebKit/android/nav/FindCanvas.cpp
+++ b/Source/WebKit/android/nav/FindCanvas.cpp
@@ -532,9 +532,6 @@ IntRect FindOnPage::currentMatchBounds() const {
if (!m_matches || !m_matches->size())
return noBounds;
MatchInfo& info = (*m_matches)[m_findIndex];
- // FIXME: this should test if the match in the layer is visible
- if (info.isInLayer())
- return noBounds;
return info.getLocation().getBounds();
}
@@ -545,6 +542,10 @@ bool FindOnPage::currentMatchIsInLayer() const {
return info.isInLayer();
}
+int FindOnPage::currentMatchLayerId() const {
+ return (*m_matches)[m_findIndex].layerId();
+}
+
// This function is only used by findNext and setMatches. In it, we store
// upper left corner of the match specified by m_findIndex in
// m_currentMatchLocation.
@@ -597,7 +598,7 @@ void FindOnPage::draw(SkCanvas* canvas, LayerAndroid* layer, IntRect* inval) {
unsigned numberOfMatches = m_matches->size();
if (numberOfMatches > 1
&& numberOfMatches < MAX_NUMBER_OF_MATCHES_TO_DRAW) {
- for(unsigned i = 0; i < numberOfMatches; i++) {
+ for (unsigned i = 0; i < numberOfMatches; i++) {
// The current match has already been drawn
if (i == m_findIndex)
continue;
diff --git a/Source/WebKit/android/nav/FindCanvas.h b/Source/WebKit/android/nav/FindCanvas.h
index 76ee1e2..994ff17 100644
--- a/Source/WebKit/android/nav/FindCanvas.h
+++ b/Source/WebKit/android/nav/FindCanvas.h
@@ -54,9 +54,9 @@ public:
SkPicture* getPicture() const { return m_picture; }
// This will make a copy of the region, and increase the ref count on the
// SkPicture. If this MatchInfo already had one, unref it.
+ void set(const SkRegion& region, SkPicture* pic, int layerId);
bool isInLayer() const { return m_layerId >= 0; }
int layerId() const { return m_layerId; }
- void set(const SkRegion& region, SkPicture* pic, int layerId);
private:
MatchInfo& operator=(MatchInfo& src);
SkRegion m_location;
@@ -141,7 +141,7 @@ public:
const SkPaint& paint) {
}
- void drawLayers(LayerAndroid* );
+ void drawLayers(LayerAndroid*);
int found() const { return mNumFound; }
void setLayerId(int layerId) { mLayerId = layerId; }
@@ -227,6 +227,9 @@ public:
IntRect currentMatchBounds() const;
int currentMatchIndex() const { return m_findIndex; }
bool currentMatchIsInLayer() const;
+ // This requires the current match to be in a layer. See
+ // currentMatchIsInLayer().
+ int currentMatchLayerId() const;
virtual void draw(SkCanvas* , LayerAndroid* , IntRect* );
void findNext(bool forward);
bool isCurrentLocationValid() { return m_hasCurrentLocation; }
diff --git a/Source/WebKit/android/nav/WebView.cpp b/Source/WebKit/android/nav/WebView.cpp
index a528e9a..101e206 100644
--- a/Source/WebKit/android/nav/WebView.cpp
+++ b/Source/WebKit/android/nav/WebView.cpp
@@ -105,8 +105,7 @@ class WebView
public:
enum FrameCachePermission {
DontAllowNewer,
- AllowNewer,
- AllowNewest
+ AllowNewer
};
enum DrawExtras { // keep this in sync with WebView.java
@@ -332,8 +331,32 @@ void nativeRecordButtons(bool hasFocus, bool pressed, bool invalidate)
}
}
-// The caller has already determined that the desired document rect corresponds
-// to the main picture, and not a layer
+void scrollToCurrentMatch()
+{
+ if (!m_findOnPage.currentMatchIsInLayer()) {
+ scrollRectOnScreen(m_findOnPage.currentMatchBounds());
+ return;
+ }
+
+ SkRect matchBounds = m_findOnPage.currentMatchBounds();
+ const LayerAndroid* rootLayer = getFrameCache(DontAllowNewer)->rootLayer();
+ const Layer* layerContainingMatch = rootLayer->findById(m_findOnPage.currentMatchLayerId());
+ ASSERT(layerContainingMatch);
+
+ // FIXME: If the match is in a scrollable layer or a child of such a layer,
+ // we may need to scroll these layers to make sure the match is visible.
+ // See http://b/5262656.
+
+ // Convert matchBounds to the global space so we can scroll the main page.
+ SkMatrix transform;
+ layerContainingMatch->localToGlobal(&transform);
+ SkRect transformedMatchBounds;
+ transform.mapRect(&transformedMatchBounds, matchBounds);
+ SkIRect roundedTransformedMatchBounds;
+ transformedMatchBounds.roundOut(&roundedTransformedMatchBounds);
+ scrollRectOnScreen(roundedTransformedMatchBounds);
+}
+
void scrollRectOnScreen(const IntRect& rect)
{
if (rect.isEmpty())
@@ -489,8 +512,23 @@ bool drawGL(WebCore::IntRect& viewRect, WebCore::IntRect* invalRect, WebCore::In
m_glWebViewState->resetRings();
if (extra) {
if (extra == &m_ring) {
+ WTF::Vector<IntRect> rings;
if (root == m_ring.m_frame)
- m_glWebViewState->setRings(m_ring.rings(), m_ring.m_isPressed);
+ rings = m_ring.rings();
+ else {
+ // TODO: Fix the navcache to work with layers correctly
+ // In the meantime, this works around the bug. However, the rings
+ // it produces are not as nice for some reason, thus we use
+ // m_ring.rings() above for the base layer instead of the below
+ for (size_t i = 0; i < m_ring.m_node->rings().size(); i++) {
+ IntRect rect = m_ring.m_node->rings().at(i);
+ rect = m_ring.m_frame->adjustBounds(m_ring.m_node, rect);
+ rect.inflate(4);
+ rings.append(rect);
+ }
+ }
+ m_glWebViewState->setRings(rings, m_ring.m_isPressed);
+ extra = 0;
} else {
LayerAndroid mainPicture(m_navPictureUI);
PictureSet* content = m_baseLayer->content();
@@ -1290,8 +1328,7 @@ void sendMotionUp(WebCore::Frame* framePtr, WebCore::Node* nodePtr, int x, int y
void findNext(bool forward)
{
m_findOnPage.findNext(forward);
- if (!m_findOnPage.currentMatchIsInLayer())
- scrollRectOnScreen(m_findOnPage.currentMatchBounds());
+ scrollToCurrentMatch();
viewInvalidate();
}
@@ -1303,21 +1340,16 @@ void setMatches(WTF::Vector<MatchInfo>* matches, jboolean sameAsLastSearch)
// location to determine whether to scroll. If the same word is found
// in the same place, then do not scroll.
IntRect oldLocation;
- bool checkAgainstOldLocation;
+ bool checkAgainstOldLocation = false;
if (sameAsLastSearch && m_findOnPage.isCurrentLocationValid()) {
oldLocation = m_findOnPage.currentMatchBounds();
checkAgainstOldLocation = true;
- } else
- checkAgainstOldLocation = false;
+ }
m_findOnPage.setMatches(matches);
- if (!checkAgainstOldLocation
- || oldLocation != m_findOnPage.currentMatchBounds()) {
- // FIXME: Need to scroll if the match is in a layer.
- if (!m_findOnPage.currentMatchIsInLayer())
- scrollRectOnScreen(m_findOnPage.currentMatchBounds());
- }
+ if (!checkAgainstOldLocation || oldLocation != m_findOnPage.currentMatchBounds())
+ scrollToCurrentMatch();
viewInvalidate();
}