summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--JavaScriptCore/ChangeLog16
-rw-r--r--JavaScriptCore/jit/JITStubs.cpp29
-rw-r--r--JavaScriptCore/runtime/JSString.h35
-rw-r--r--JavaScriptCore/runtime/Operations.cpp11
-rw-r--r--JavaScriptCore/runtime/Operations.h69
-rw-r--r--JavaScriptCore/wtf/Platform.h4
-rw-r--r--WebCore/Android.derived.v8bindings.mk3
-rw-r--r--WebCore/Android.mk3
-rw-r--r--WebCore/config.h1
-rw-r--r--WebCore/platform/android/PlatformBridge.h9
-rw-r--r--WebCore/platform/graphics/android/AndroidAnimation.cpp313
-rw-r--r--WebCore/platform/graphics/android/AndroidAnimation.h205
-rw-r--r--WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp852
-rw-r--r--WebCore/platform/graphics/android/GraphicsLayerAndroid.h156
-rw-r--r--WebCore/platform/graphics/android/LayerAndroid.cpp353
-rw-r--r--WebCore/platform/graphics/android/LayerAndroid.h129
-rw-r--r--WebCore/rendering/RenderLayerBacking.cpp2
-rw-r--r--WebCore/rendering/RenderLayerCompositor.cpp5
-rw-r--r--WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp63
-rw-r--r--WebKit/android/WebCoreSupport/ChromeClientAndroid.h26
-rw-r--r--WebKit/android/WebCoreSupport/PlatformBridge.cpp19
-rw-r--r--WebKit/android/jni/WebViewCore.cpp94
-rw-r--r--WebKit/android/jni/WebViewCore.h7
-rw-r--r--WebKit/android/nav/CacheBuilder.cpp2
-rw-r--r--WebKit/android/nav/CachedFrame.cpp50
-rw-r--r--WebKit/android/nav/CachedFrame.h2
-rw-r--r--WebKit/android/nav/CachedInput.cpp15
-rw-r--r--WebKit/android/nav/CachedRoot.cpp23
-rw-r--r--WebKit/android/nav/CachedRoot.h7
-rw-r--r--WebKit/android/nav/WebView.cpp142
30 files changed, 2466 insertions, 179 deletions
diff --git a/JavaScriptCore/ChangeLog b/JavaScriptCore/ChangeLog
index 3e9187b..829cc98 100644
--- a/JavaScriptCore/ChangeLog
+++ b/JavaScriptCore/ChangeLog
@@ -1,3 +1,19 @@
+2009-12-10 Adam Barth <abarth@webkit.org>
+
+ No review, rolling out r51975.
+ http://trac.webkit.org/changeset/51975
+
+ * jit/JITStubs.cpp:
+ (JSC::DEFINE_STUB_FUNCTION):
+ * runtime/JSString.h:
+ (JSC::JSString::JSString):
+ (JSC::JSString::appendStringInConstruct):
+ * runtime/Operations.cpp:
+ (JSC::jsAddSlowCase):
+ * runtime/Operations.h:
+ (JSC::jsString):
+ (JSC::jsAdd):
+
2009-12-10 Oliver Hunt <oliver@apple.com>
Reviewed by Gavin Barraclough.
diff --git a/JavaScriptCore/jit/JITStubs.cpp b/JavaScriptCore/jit/JITStubs.cpp
index 8dd7a97..cace8b2 100644
--- a/JavaScriptCore/jit/JITStubs.cpp
+++ b/JavaScriptCore/jit/JITStubs.cpp
@@ -1033,19 +1033,34 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_add)
JSValue v1 = stackFrame.args[0].jsValue();
JSValue v2 = stackFrame.args[1].jsValue();
+
+ double left;
+ double right = 0.0;
+
+ bool rightIsNumber = v2.getNumber(right);
+ if (rightIsNumber && v1.getNumber(left))
+ return JSValue::encode(jsNumber(stackFrame.globalData, left + right));
+
CallFrame* callFrame = stackFrame.callFrame;
- if (v1.isString()) {
- JSValue result = v2.isString()
- ? jsString(callFrame, asString(v1), asString(v2))
- : jsString(callFrame, asString(v1), v2.toString(callFrame));
+ bool leftIsString = v1.isString();
+ if (leftIsString && v2.isString()) {
+ JSValue result = jsString(callFrame, asString(v1), asString(v2));
CHECK_FOR_EXCEPTION_AT_END();
return JSValue::encode(result);
}
- double left = 0.0, right;
- if (v1.getNumber(left) && v2.getNumber(right))
- return JSValue::encode(jsNumber(stackFrame.globalData, left + right));
+ if (rightIsNumber & leftIsString) {
+ RefPtr<UString::Rep> value = v2.isInt32() ?
+ concatenate(asString(v1)->value(callFrame).rep(), v2.asInt32()) :
+ concatenate(asString(v1)->value(callFrame).rep(), right);
+
+ if (UNLIKELY(!value)) {
+ throwOutOfMemoryError(callFrame);
+ VM_THROW_EXCEPTION();
+ }
+ return JSValue::encode(jsString(stackFrame.globalData, value.release()));
+ }
// All other cases are pretty uncommon
JSValue result = jsAddSlowCase(callFrame, v1, v2);
diff --git a/JavaScriptCore/runtime/JSString.h b/JavaScriptCore/runtime/JSString.h
index 1867b17..93b11f1 100644
--- a/JavaScriptCore/runtime/JSString.h
+++ b/JavaScriptCore/runtime/JSString.h
@@ -203,32 +203,6 @@ namespace JSC {
appendStringInConstruct(index, s2);
ASSERT(ropeLength == index);
}
- // This constructor constructs a new string by concatenating s1 & s2.
- // This should only be called with ropeLength <= 3.
- JSString(JSGlobalData* globalData, unsigned ropeLength, JSString* s1, const UString& u2)
- : JSCell(globalData->stringStructure.get())
- , m_stringLength(s1->length() + u2.size())
- , m_ropeLength(ropeLength)
- {
- ASSERT(ropeLength <= s_maxInternalRopeLength);
- unsigned index = 0;
- appendStringInConstruct(index, s1);
- appendStringInConstruct(index, u2);
- ASSERT(ropeLength == index);
- }
- // This constructor constructs a new string by concatenating s1 & s2.
- // This should only be called with ropeLength <= 3.
- JSString(JSGlobalData* globalData, unsigned ropeLength, const UString& u1, JSString* s2)
- : JSCell(globalData->stringStructure.get())
- , m_stringLength(u1.size() + s2->length())
- , m_ropeLength(ropeLength)
- {
- ASSERT(ropeLength <= s_maxInternalRopeLength);
- unsigned index = 0;
- appendStringInConstruct(index, u1);
- appendStringInConstruct(index, s2);
- ASSERT(ropeLength == index);
- }
// This constructor constructs a new string by concatenating v1, v2 & v3.
// This should only be called with ropeLength <= 3 ... which since every
// value must require a ropeLength of at least one implies that the length
@@ -284,18 +258,13 @@ namespace JSC {
void resolveRope(ExecState*) const;
- void appendStringInConstruct(unsigned& index, const UString& string)
- {
- m_fibers[index++] = Rope::Fiber(string.rep()->ref());
- }
-
void appendStringInConstruct(unsigned& index, JSString* jsString)
{
if (jsString->isRope()) {
for (unsigned i = 0; i < jsString->m_ropeLength; ++i)
m_fibers[index++] = jsString->m_fibers[i].ref();
} else
- appendStringInConstruct(index, jsString->string());
+ m_fibers[index++] = Rope::Fiber(jsString->string().rep()->ref());
}
void appendValueInConstructAndIncrementLength(ExecState* exec, unsigned& index, JSValue v)
@@ -342,8 +311,6 @@ namespace JSC {
unsigned ropeLength() { return m_ropeLength ? m_ropeLength : 1; }
friend JSValue jsString(ExecState* exec, JSString* s1, JSString* s2);
- friend JSValue jsString(ExecState* exec, const UString& u1, JSString* s2);
- friend JSValue jsString(ExecState* exec, JSString* s1, const UString& u2);
friend JSValue jsString(ExecState* exec, Register* strings, unsigned count);
};
diff --git a/JavaScriptCore/runtime/Operations.cpp b/JavaScriptCore/runtime/Operations.cpp
index 0e1887c..139c7b8 100644
--- a/JavaScriptCore/runtime/Operations.cpp
+++ b/JavaScriptCore/runtime/Operations.cpp
@@ -54,13 +54,12 @@ NEVER_INLINE JSValue jsAddSlowCase(CallFrame* callFrame, JSValue v1, JSValue v2)
JSValue p1 = v1.toPrimitive(callFrame);
JSValue p2 = v2.toPrimitive(callFrame);
- if (p1.isString()) {
- return p2.isString()
- ? jsString(callFrame, asString(p1), asString(p2))
- : jsString(callFrame, asString(p1), p2.toString(callFrame));
+ if (p1.isString() || p2.isString()) {
+ RefPtr<UString::Rep> value = concatenate(p1.toString(callFrame).rep(), p2.toString(callFrame).rep());
+ if (!value)
+ return throwOutOfMemoryError(callFrame);
+ return jsString(callFrame, value.release());
}
- if (p2.isString())
- return jsString(callFrame, p1.toString(callFrame), asString(p2));
return jsNumber(callFrame, p1.toNumber(callFrame) + p2.toNumber(callFrame));
}
diff --git a/JavaScriptCore/runtime/Operations.h b/JavaScriptCore/runtime/Operations.h
index 0289ac2..1cab06d 100644
--- a/JavaScriptCore/runtime/Operations.h
+++ b/JavaScriptCore/runtime/Operations.h
@@ -37,11 +37,6 @@ namespace JSC {
ALWAYS_INLINE JSValue jsString(ExecState* exec, JSString* s1, JSString* s2)
{
- if (!s1->length())
- return s2;
- if (!s2->length())
- return s1;
-
unsigned ropeLength = s1->ropeLength() + s2->ropeLength();
JSGlobalData* globalData = &exec->globalData();
@@ -58,42 +53,6 @@ namespace JSC {
return new (globalData) JSString(globalData, rope.release());
}
- ALWAYS_INLINE JSValue jsString(ExecState* exec, const UString& u1, JSString* s2)
- {
- unsigned ropeLength = 1 + s2->ropeLength();
- JSGlobalData* globalData = &exec->globalData();
-
- if (ropeLength <= JSString::s_maxInternalRopeLength)
- return new (globalData) JSString(globalData, ropeLength, u1, s2);
-
- unsigned index = 0;
- RefPtr<JSString::Rope> rope = JSString::Rope::createOrNull(ropeLength);
- if (UNLIKELY(!rope))
- return throwOutOfMemoryError(exec);
- rope->append(index, u1);
- rope->append(index, s2);
- ASSERT(index == ropeLength);
- return new (globalData) JSString(globalData, rope.release());
- }
-
- ALWAYS_INLINE JSValue jsString(ExecState* exec, JSString* s1, const UString& u2)
- {
- unsigned ropeLength = s1->ropeLength() + 1;
- JSGlobalData* globalData = &exec->globalData();
-
- if (ropeLength <= JSString::s_maxInternalRopeLength)
- return new (globalData) JSString(globalData, ropeLength, s1, u2);
-
- unsigned index = 0;
- RefPtr<JSString::Rope> rope = JSString::Rope::createOrNull(ropeLength);
- if (UNLIKELY(!rope))
- return throwOutOfMemoryError(exec);
- rope->append(index, s1);
- rope->append(index, u2);
- ASSERT(index == ropeLength);
- return new (globalData) JSString(globalData, rope.release());
- }
-
ALWAYS_INLINE JSValue jsString(ExecState* exec, Register* strings, unsigned count)
{
ASSERT(count >= 3);
@@ -288,14 +247,30 @@ namespace JSC {
ALWAYS_INLINE JSValue jsAdd(CallFrame* callFrame, JSValue v1, JSValue v2)
{
- double left = 0.0, right;
- if (v1.getNumber(left), v2.getNumber(right))
+ double left;
+ double right = 0.0;
+
+ bool rightIsNumber = v2.getNumber(right);
+ if (rightIsNumber && v1.getNumber(left))
return jsNumber(callFrame, left + right);
- if (v1.isString()) {
- return v2.isString()
- ? jsString(callFrame, asString(v1), asString(v2))
- : jsString(callFrame, asString(v1), v2.toString(callFrame));
+ bool leftIsString = v1.isString();
+ if (leftIsString && v2.isString()) {
+ if (!asString(v1)->length())
+ return asString(v2);
+ if (!asString(v2)->length())
+ return asString(v1);
+ return jsString(callFrame, asString(v1), asString(v2));
+ }
+
+ if (rightIsNumber & leftIsString) {
+ RefPtr<UString::Rep> value = v2.isInt32() ?
+ concatenate(asString(v1)->value(callFrame).rep(), v2.asInt32()) :
+ concatenate(asString(v1)->value(callFrame).rep(), right);
+
+ if (!value)
+ return throwOutOfMemoryError(callFrame);
+ return jsString(callFrame, value.release());
}
// All other cases are pretty uncommon
diff --git a/JavaScriptCore/wtf/Platform.h b/JavaScriptCore/wtf/Platform.h
index dbe2f8e..18e2b5c 100644
--- a/JavaScriptCore/wtf/Platform.h
+++ b/JavaScriptCore/wtf/Platform.h
@@ -919,6 +919,10 @@ on MinGW. See https://bugs.webkit.org/show_bug.cgi?id=29268 */
#endif
#endif
+#if PLATFORM(ANDROID)
+#define WTF_USE_ACCELERATED_COMPOSITING 0
+#endif
+
#if PLATFORM(IPHONE)
#define WTF_USE_ACCELERATED_COMPOSITING 1
#endif
diff --git a/WebCore/Android.derived.v8bindings.mk b/WebCore/Android.derived.v8bindings.mk
index 33b7050..a9f403a 100644
--- a/WebCore/Android.derived.v8bindings.mk
+++ b/WebCore/Android.derived.v8bindings.mk
@@ -30,7 +30,8 @@ js_binding_scripts := \
$(LOCAL_PATH)/bindings/scripts/IDLStructure.pm \
$(LOCAL_PATH)/bindings/scripts/generate-bindings.pl
-FEATURE_DEFINES := ENABLE_ORIENTATION_EVENTS=1 ENABLE_TOUCH_EVENTS=1 V8_BINDING ENABLE_DATABASE=1 ENABLE_OFFLINE_WEB_APPLICATIONS=1 ENABLE_DOM_STORAGE=1 ENABLE_VIDEO=1 ENABLE_WORKERS=1 ENABLE_GEOLOCATION=1
+# Add ACCELERATED_COMPOSITING=1 and ENABLE_3D_RENDERING=1 for layers support
+FEATURE_DEFINES := ENABLE_ORIENTATION_EVENTS=1 ENABLE_TOUCH_EVENTS=1 V8_BINDING ENABLE_DATABASE=1 ENABLE_OFFLINE_WEB_APPLICATIONS=1 ENABLE_DOM_STORAGE=1 ENABLE_WORKERS=1 ENABLE_VIDEO=1 ENABLE_GEOLOCATION=1
# CSS
GEN := \
diff --git a/WebCore/Android.mk b/WebCore/Android.mk
index 46d9caa..0ab375b 100644
--- a/WebCore/Android.mk
+++ b/WebCore/Android.mk
@@ -449,6 +449,7 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \
platform/graphics/StringTruncator.cpp \
platform/graphics/WidthIterator.cpp \
\
+ platform/graphics/android/AndroidAnimation.cpp \
platform/graphics/android/BitmapAllocatorAndroid.cpp \
platform/graphics/android/FontAndroid.cpp \
platform/graphics/android/FontCacheAndroid.cpp \
@@ -458,9 +459,11 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \
platform/graphics/android/GlyphMapAndroid.cpp \
platform/graphics/android/GradientAndroid.cpp \
platform/graphics/android/GraphicsContextAndroid.cpp \
+ platform/graphics/android/GraphicsLayerAndroid.cpp \
platform/graphics/android/ImageAndroid.cpp \
platform/graphics/android/ImageBufferAndroid.cpp \
platform/graphics/android/ImageSourceAndroid.cpp \
+ platform/graphics/android/LayerAndroid.cpp \
platform/graphics/android/PathAndroid.cpp \
platform/graphics/android/PatternAndroid.cpp \
platform/graphics/android/PlatformGraphicsContext.cpp \
diff --git a/WebCore/config.h b/WebCore/config.h
index 907b0d5..8fbed4f 100644
--- a/WebCore/config.h
+++ b/WebCore/config.h
@@ -91,6 +91,7 @@
#ifndef ENABLE_SVG
#define ENABLE_SVG 0
#endif
+#define ENABLE_3D_RENDERING 0
#define ENABLE_VIDEO 1
#define ENABLE_WORKERS 1
diff --git a/WebCore/platform/android/PlatformBridge.h b/WebCore/platform/android/PlatformBridge.h
index e3f3b98..9adb314 100644
--- a/WebCore/platform/android/PlatformBridge.h
+++ b/WebCore/platform/android/PlatformBridge.h
@@ -33,6 +33,8 @@
namespace WebCore {
+class FrameView;
+
// An interface to the embedding layer, which has the ability to answer
// questions about the system and so on...
// This is very similar to ChromiumBridge and the two are likely to converge
@@ -58,6 +60,13 @@ public:
SubmitLabel
};
static String* globalLocalizedName(rawResId resId);
+
+#if USE(ACCELERATED_COMPOSITING)
+ // Those methods are used by the layers system
+ static void setRootLayer(const FrameView* view, int layer);
+ static void immediateRepaint(const FrameView* view);
+#endif // USE(ACCELERATED_COMPOSITING)
+
};
}
#endif // PlatformBridge_h
diff --git a/WebCore/platform/graphics/android/AndroidAnimation.cpp b/WebCore/platform/graphics/android/AndroidAnimation.cpp
new file mode 100644
index 0000000..9cdb0c7
--- /dev/null
+++ b/WebCore/platform/graphics/android/AndroidAnimation.cpp
@@ -0,0 +1,313 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+#include "config.h"
+#include "AndroidAnimation.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "Animation.h"
+#include "GraphicsLayerAndroid.h"
+
+#include "Timer.h"
+#include "TimingFunction.h"
+#include "UnitBezier.h"
+
+#include <wtf/CurrentTime.h>
+
+namespace WebCore {
+
+void AndroidTransformAnimationValue::apply()
+{
+ if (m_doTranslation)
+ m_layer->setTranslation(m_translation);
+
+ if (m_doScaling)
+ m_layer->setScale(m_scale);
+
+ if (m_doRotation)
+ m_layer->setRotation(m_rotation);
+}
+
+void AndroidAnimationTimer::fired()
+{
+ if (!m_notificationSent) {
+ m_notificationSent = true;
+ if (m_layer && m_layer->client())
+ m_layer->client()->notifyAnimationStarted(m_layer, WTF::currentTime());
+ }
+}
+
+static long gDebugAndroidAnimationInstances;
+
+long AndroidAnimation::instancesCount()
+{
+ return gDebugAndroidAnimationInstances;
+}
+
+AndroidAnimation::AndroidAnimation(LayerAndroid* contentLayer,
+ const Animation* animation,
+ double beginTime) :
+ m_contentLayer(contentLayer),
+ m_beginTime(beginTime),
+ m_duration(animation->duration()),
+ m_iterationCount(animation->iterationCount()),
+ m_currentIteration(0),
+ m_direction(animation->direction()),
+ m_timingFunction(animation->timingFunction())
+{
+ if (!static_cast<int>(beginTime)) // time not set
+ m_beginTime = WTF::currentTime();
+
+ gDebugAndroidAnimationInstances++;
+}
+
+AndroidAnimation::AndroidAnimation(AndroidAnimation* anim) :
+ m_contentLayer(anim->m_contentLayer),
+ m_beginTime(anim->m_beginTime),
+ m_duration(anim->m_duration),
+ m_iterationCount(anim->m_iterationCount),
+ m_currentIteration(0),
+ m_direction(anim->m_direction),
+ m_timingFunction(anim->m_timingFunction)
+{
+ gDebugAndroidAnimationInstances++;
+}
+
+AndroidAnimation::~AndroidAnimation()
+{
+ gDebugAndroidAnimationInstances--;
+}
+
+float AndroidAnimation::currentProgress(double time)
+{
+ if (m_beginTime <= 0.000001) // overflow or not correctly set
+ m_beginTime = time;
+
+ m_elapsedTime = time - m_beginTime;
+
+ if (m_duration <= 0)
+ m_duration = 0.000001;
+
+ if (m_elapsedTime < 0) // animation not yet started.
+ return 0;
+
+ return m_elapsedTime / m_duration;
+}
+
+bool AndroidAnimation::checkIterationsAndProgress(double time, float* finalProgress)
+{
+ float progress = currentProgress(time);
+
+ int currentIteration = static_cast<int>(progress);
+ if (currentIteration != m_currentIteration)
+ if (m_direction == Animation::AnimationDirectionAlternate)
+ swapDirection();
+
+ m_currentIteration = currentIteration;
+ progress -= m_currentIteration;
+
+ if ((m_currentIteration >= m_iterationCount)
+ && (m_iterationCount != Animation::IterationCountInfinite))
+ return false;
+
+ if (m_timingFunction.type() != LinearTimingFunction) {
+ UnitBezier bezier(m_timingFunction.x1(),
+ m_timingFunction.y1(),
+ m_timingFunction.x2(),
+ m_timingFunction.y2());
+ if (m_duration > 0)
+ progress = bezier.solve(progress, 1.0f / (200.0f * m_duration));
+ }
+
+ *finalProgress = progress;
+ return true;
+}
+
+PassRefPtr<AndroidOpacityAnimation> AndroidOpacityAnimation::create(LayerAndroid* contentLayer,
+ float fromValue, float toValue,
+ const Animation* animation, double beginTime)
+{
+ return adoptRef(new AndroidOpacityAnimation(contentLayer,
+ fromValue, toValue, animation, beginTime));
+}
+
+AndroidOpacityAnimation::AndroidOpacityAnimation(LayerAndroid* contentLayer,
+ float fromValue, float toValue,
+ const Animation* animation,
+ double beginTime)
+ : AndroidAnimation(contentLayer, animation, beginTime),
+ m_fromValue(fromValue), m_toValue(toValue)
+{
+}
+
+AndroidOpacityAnimation::AndroidOpacityAnimation(AndroidOpacityAnimation* anim)
+ : AndroidAnimation(anim),
+ m_fromValue(anim->m_fromValue),
+ m_toValue(anim->m_toValue)
+{
+}
+
+AndroidAnimation* AndroidOpacityAnimation::copy()
+{
+ return new AndroidOpacityAnimation(this);
+}
+
+void AndroidOpacityAnimation::swapDirection()
+{
+ float v = m_toValue;
+ m_toValue = m_fromValue;
+ m_fromValue = m_toValue;
+}
+
+bool AndroidOpacityAnimation::evaluate(double time)
+{
+ float progress;
+ if (!checkIterationsAndProgress(time, &progress))
+ return false;
+
+ if (progress < 0) // we still want to be evaluated until we get progress > 0
+ return true;
+
+ float value = m_fromValue + ((m_toValue - m_fromValue) * progress);
+ m_result = AndroidOpacityAnimationValue::create(m_contentLayer.get(), value);
+ return true;
+}
+
+PassRefPtr<AndroidTransformAnimation> AndroidTransformAnimation::create(LayerAndroid* contentLayer,
+ const Animation* animation, double beginTime)
+{
+ return adoptRef(new AndroidTransformAnimation(contentLayer, animation, beginTime));
+}
+
+AndroidTransformAnimation::AndroidTransformAnimation(LayerAndroid* contentLayer,
+ const Animation* animation,
+ double beginTime)
+ : AndroidAnimation(contentLayer, animation, beginTime),
+ m_doTranslation(false),
+ m_doScaling(false),
+ m_doRotation(false)
+{
+}
+
+AndroidTransformAnimation::AndroidTransformAnimation(AndroidTransformAnimation* anim)
+ : AndroidAnimation(anim),
+ m_doTranslation(anim->m_doTranslation),
+ m_doScaling(anim->m_doScaling),
+ m_doRotation(anim->m_doRotation),
+ m_position(anim->m_position),
+ m_fromX(anim->m_fromX), m_fromY(anim->m_fromY), m_fromZ(anim->m_fromZ),
+ m_toX(anim->m_toX), m_toY(anim->m_toY), m_toZ(anim->m_toZ),
+ m_fromAngle(anim->m_fromAngle), m_toAngle(anim->m_toAngle),
+ m_fromScaleX(anim->m_fromScaleX), m_fromScaleY(anim->m_fromScaleY), m_fromScaleZ(anim->m_fromScaleZ),
+ m_toScaleX(anim->m_toScaleX), m_toScaleY(anim->m_toScaleY), m_toScaleZ(anim->m_toScaleZ)
+{
+}
+
+AndroidAnimation* AndroidTransformAnimation::copy()
+{
+ return new AndroidTransformAnimation(this);
+}
+
+void AndroidTransformAnimation::setRotation(float fA, float tA)
+{
+ m_fromAngle = fA;
+ m_toAngle = tA;
+ m_doRotation = true;
+}
+
+void AndroidTransformAnimation::setTranslation(float fX, float fY, float fZ,
+ float tX, float tY, float tZ)
+{
+ m_fromX = fX;
+ m_fromY = fY;
+ m_fromZ = fZ;
+ m_toX = tX;
+ m_toY = tY;
+ m_toZ = tZ;
+ m_doTranslation = true;
+}
+
+void AndroidTransformAnimation::setScale(float fX, float fY, float fZ,
+ float tX, float tY, float tZ)
+{
+ m_fromScaleX = fX;
+ m_fromScaleY = fY;
+ m_fromScaleZ = fZ;
+ m_toScaleX = tX;
+ m_toScaleY = tY;
+ m_toScaleZ = tZ;
+ m_doScaling = true;
+}
+
+void AndroidTransformAnimation::swapDirection()
+{
+ if (m_doTranslation) {
+ float tx = m_toX;
+ m_toX = m_fromX;
+ m_fromX = tx;
+ float ty = m_toY;
+ m_toY = m_fromY;
+ m_fromY = ty;
+ float tz = m_toZ;
+ m_toZ = m_fromZ;
+ m_fromZ = tz;
+ }
+ if (m_doScaling) {
+ float sx = m_toScaleX;
+ m_toScaleX = m_fromScaleX;
+ m_fromScaleX = sx;
+ float sy = m_toScaleY;
+ m_toScaleY = m_fromScaleY;
+ m_fromScaleY = sy;
+ }
+ if (m_doRotation) {
+ float a = m_toAngle;
+ m_toAngle = m_fromAngle;
+ m_fromAngle = a;
+ }
+}
+
+bool AndroidTransformAnimation::evaluate(double time)
+{
+ float progress;
+ if (!checkIterationsAndProgress(time, &progress))
+ return false;
+
+ if (progress < 0) // we still want to be evaluated until we get progress > 0
+ return true;
+
+ float x = m_fromX + (m_toX - m_fromX) * progress;
+ float y = m_fromY + (m_toY - m_fromY) * progress;
+ float z = m_fromZ + (m_toZ - m_fromZ) * progress;
+ float sx = m_fromScaleX + (m_toScaleX - m_fromScaleX) * progress;
+ float sy = m_fromScaleY + (m_toScaleY - m_fromScaleY) * progress;
+ float sz = m_fromScaleZ + (m_toScaleZ - m_fromScaleZ) * progress;
+ float a = m_fromAngle + (m_toAngle - m_fromAngle) * progress;
+
+ FloatPoint translation(x, y);
+ FloatPoint3D scale(sx, sy, sz);
+ m_result = AndroidTransformAnimationValue::create(m_contentLayer.get(),
+ translation, scale, a);
+ m_result->setDoTranslation(m_doTranslation);
+ m_result->setDoScaling(m_doScaling);
+ m_result->setDoRotation(m_doRotation);
+ return true;
+}
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/WebCore/platform/graphics/android/AndroidAnimation.h b/WebCore/platform/graphics/android/AndroidAnimation.h
new file mode 100644
index 0000000..05d6a76
--- /dev/null
+++ b/WebCore/platform/graphics/android/AndroidAnimation.h
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2009 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 AndroidAnimation_h
+#define AndroidAnimation_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "FloatPoint.h"
+#include "FloatPoint3D.h"
+#include "HashMap.h"
+#include "LayerAndroid.h"
+#include "RefPtr.h"
+#include "Timer.h"
+#include "Vector.h"
+
+namespace WebCore {
+
+class AndroidAnimation;
+class GraphicsLayerAndroid;
+class TimingFunction;
+
+typedef Vector<RefPtr<AndroidAnimation> > AnimsVector;
+typedef HashMap<RefPtr<LayerAndroid>, AnimsVector* > LayersAnimsMap;
+
+class AndroidAnimationValue : public RefCounted<AndroidAnimationValue> {
+ public:
+ AndroidAnimationValue(LayerAndroid* layer) : m_layer(layer) { }
+ virtual ~AndroidAnimationValue() { }
+ virtual void apply() = 0;
+ protected:
+ RefPtr<LayerAndroid> m_layer;
+};
+
+class AndroidOpacityAnimationValue : public AndroidAnimationValue {
+ public:
+ static PassRefPtr<AndroidOpacityAnimationValue> create(
+ LayerAndroid* layer, float value) {
+ return adoptRef(new AndroidOpacityAnimationValue(layer, value));
+ }
+ AndroidOpacityAnimationValue(LayerAndroid* layer, float value) :
+ AndroidAnimationValue(layer), m_value(value) { }
+ virtual void apply() { m_layer->setOpacity(m_value); }
+ private:
+ float m_value;
+};
+
+class AndroidTransformAnimationValue : public AndroidAnimationValue {
+ public:
+ static PassRefPtr<AndroidTransformAnimationValue> create(
+ LayerAndroid* layer,
+ FloatPoint translation,
+ FloatPoint3D scale,
+ float rotation) {
+ return adoptRef(new AndroidTransformAnimationValue(layer, translation, scale, rotation));
+ }
+
+ AndroidTransformAnimationValue(LayerAndroid* layer,
+ FloatPoint translation,
+ FloatPoint3D scale,
+ float rotation) :
+ AndroidAnimationValue(layer),
+ m_doTranslation(false), m_doScaling(false), m_doRotation(false),
+ m_translation(translation), m_scale(scale), m_rotation(rotation) { }
+ void setDoTranslation(bool doTranslation) { m_doTranslation = doTranslation; }
+ void setDoScaling(bool doScaling) { m_doScaling = doScaling; }
+ void setDoRotation(bool doRotation) { m_doRotation = doRotation; }
+
+ virtual void apply();
+
+ private:
+ bool m_doTranslation;
+ bool m_doScaling;
+ bool m_doRotation;
+ FloatPoint m_translation;
+ FloatPoint3D m_scale;
+ float m_rotation;
+};
+
+class AndroidAnimation : public RefCounted<AndroidAnimation> {
+ public:
+ AndroidAnimation(LayerAndroid* contentLayer,
+ const Animation* animation,
+ double beginTime);
+ AndroidAnimation(AndroidAnimation* anim);
+
+ virtual ~AndroidAnimation();
+ virtual AndroidAnimation* copy() = 0;
+ float currentProgress(double time);
+ bool checkIterationsAndProgress(double time, float* finalProgress);
+ virtual void swapDirection() = 0;
+ virtual bool evaluate(double time) = 0;
+ LayerAndroid* contentLayer() { return m_contentLayer.get(); }
+ static long instancesCount();
+ void setLayer(LayerAndroid* layer) { m_contentLayer = layer; }
+ void setName(const String& name) { m_name = name; }
+ String name() { return m_name; }
+ virtual PassRefPtr<AndroidAnimationValue> result() = 0;
+
+ protected:
+ RefPtr<LayerAndroid> m_contentLayer;
+ double m_beginTime;
+ double m_elapsedTime;
+ double m_duration;
+ int m_iterationCount;
+ int m_currentIteration;
+ int m_direction;
+ TimingFunction m_timingFunction;
+ String m_name;
+};
+
+class AndroidOpacityAnimation : public AndroidAnimation {
+ public:
+ static PassRefPtr<AndroidOpacityAnimation> create(LayerAndroid* contentLayer,
+ float fromValue, float toValue,
+ const Animation* animation,
+ double beginTime);
+ AndroidOpacityAnimation(LayerAndroid* contentLayer,
+ float fromValue, float toValue,
+ const Animation* animation,
+ double beginTime);
+ AndroidOpacityAnimation(AndroidOpacityAnimation* anim);
+ virtual AndroidAnimation* copy();
+ virtual PassRefPtr<AndroidAnimationValue> result() { return m_result.release(); }
+
+ virtual void swapDirection();
+ virtual bool evaluate(double time);
+
+ private:
+ RefPtr<AndroidOpacityAnimationValue> m_result;
+ float m_fromValue;
+ float m_toValue;
+};
+
+class AndroidTransformAnimation : public AndroidAnimation {
+ public:
+ static PassRefPtr<AndroidTransformAnimation> create(LayerAndroid* contentLayer,
+ const Animation* animation,
+ double beginTime);
+ AndroidTransformAnimation(LayerAndroid* contentLayer,
+ const Animation* animation,
+ double beginTime);
+
+ AndroidTransformAnimation(AndroidTransformAnimation* anim);
+ virtual AndroidAnimation* copy();
+
+ void setOriginalPosition(FloatPoint position) { m_position = position; }
+ void setRotation(float fA, float tA);
+ void setTranslation(float fX, float fY, float fZ,
+ float tX, float tY, float tZ);
+ void setScale(float fX, float fY, float fZ,
+ float tX, float tY, float tZ);
+ virtual void swapDirection();
+ virtual bool evaluate(double time);
+ virtual PassRefPtr<AndroidAnimationValue> result() { return m_result.release(); }
+
+ private:
+ RefPtr<AndroidTransformAnimationValue> m_result;
+ bool m_doTranslation;
+ bool m_doScaling;
+ bool m_doRotation;
+ FloatPoint m_position;
+ float m_fromX, m_fromY, m_fromZ;
+ float m_toX, m_toY, m_toZ;
+ float m_fromAngle, m_toAngle;
+ float m_fromScaleX, m_fromScaleY, m_fromScaleZ;
+ float m_toScaleX, m_toScaleY, m_toScaleZ;
+};
+
+class AndroidAnimationTimer : public TimerBase {
+ public:
+
+ AndroidAnimationTimer(GraphicsLayerAndroid* layer, double beginTime)
+ {
+ m_layer = layer;
+ m_notificationSent = false;
+ m_beginTime = beginTime;
+ }
+
+ private:
+ void fired();
+ GraphicsLayerAndroid* m_layer;
+ double m_beginTime;
+ bool m_notificationSent;
+};
+
+} // namespace WebCore
+
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif // AndroidAnimation_h
diff --git a/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp b/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp
new file mode 100644
index 0000000..7637be9
--- /dev/null
+++ b/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp
@@ -0,0 +1,852 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+#include "config.h"
+#include "GraphicsLayerAndroid.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "AndroidAnimation.h"
+#include "Animation.h"
+#include "CString.h"
+#include "FloatRect.h"
+#include "GraphicsContext.h"
+#include "Image.h"
+#include "PlatformBridge.h"
+#include "PlatformGraphicsContext.h"
+#include "RenderLayerBacking.h"
+#include "RenderView.h"
+#include "RotateTransformOperation.h"
+#include "ScaleTransformOperation.h"
+#include "SkCanvas.h"
+#include "TransformationMatrix.h"
+#include "TranslateTransformOperation.h"
+
+#include <cutils/log.h>
+#include <wtf/CurrentTime.h>
+
+#undef LOG
+#define LOG(...) android_printLog(ANDROID_LOG_DEBUG, "GraphicsLayer", __VA_ARGS__)
+#define MLOG(...) android_printLog(ANDROID_LOG_DEBUG, "GraphicsLayer", __VA_ARGS__)
+#define TLOG(...) android_printLog(ANDROID_LOG_DEBUG, "GraphicsLayer", __VA_ARGS__)
+
+#undef LOG
+#define LOG(...)
+#undef MLOG
+#define MLOG(...)
+#undef TLOG
+#define TLOG(...)
+#undef LAYER_DEBUG
+
+using namespace std;
+
+static bool gPaused;
+static double gPausedDelay;
+
+namespace WebCore {
+
+static int gDebugGraphicsLayerAndroidInstances = 0;
+inline int GraphicsLayerAndroid::instancesCount()
+{
+ return gDebugGraphicsLayerAndroidInstances;
+}
+
+static String propertyIdToString(AnimatedPropertyID property)
+{
+ switch (property) {
+ case AnimatedPropertyWebkitTransform:
+ return "transform";
+ case AnimatedPropertyOpacity:
+ return "opacity";
+ case AnimatedPropertyBackgroundColor:
+ return "backgroundColor";
+ case AnimatedPropertyInvalid:
+ ASSERT_NOT_REACHED();
+ }
+ ASSERT_NOT_REACHED();
+ return "";
+}
+
+GraphicsLayer::CompositingCoordinatesOrientation GraphicsLayer::compositingCoordinatesOrientation()
+{
+ return CompositingCoordinatesBottomUp;
+}
+
+PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client)
+{
+ return new GraphicsLayerAndroid(client);
+}
+
+GraphicsLayerAndroid::GraphicsLayerAndroid(GraphicsLayerClient* client) :
+ GraphicsLayer(client),
+ m_needsSyncChildren(false),
+ m_needsSyncMask(false),
+ m_needsRepaint(false),
+ m_needsDisplay(false),
+ m_haveContents(false),
+ m_haveImage(false),
+ m_translateX(0),
+ m_translateY(0),
+ m_currentTranslateX(0),
+ m_currentTranslateY(0),
+ m_currentPosition(0, 0)
+{
+ m_contentLayer = new LayerAndroid(true);
+ if (client) {
+ RenderLayerBacking* backing = static_cast<RenderLayerBacking*>(client);
+ RenderLayer* renderLayer = backing->owningLayer();
+ m_contentLayer->setIsRootLayer(renderLayer->isRootLayer());
+ RenderView* view = static_cast<RenderView*>(renderLayer->renderer());
+ if (view->isPositioned() && view->style()->position() == FixedPosition) {
+ FloatPoint position(view->style()->left().value(),
+ view->style()->right().value());
+ m_contentLayer->setFixedPosition(position);
+ }
+ }
+ gDebugGraphicsLayerAndroidInstances++;
+}
+
+GraphicsLayerAndroid::~GraphicsLayerAndroid()
+{
+ if (!parent() && m_frame && m_frame->view())
+ PlatformBridge::setRootLayer(m_frame->view(), 0);
+
+ gDebugGraphicsLayerAndroidInstances--;
+}
+
+void GraphicsLayerAndroid::setName(const String& name)
+{
+ GraphicsLayer::setName(name);
+}
+
+NativeLayer GraphicsLayerAndroid::nativeLayer() const
+{
+ LOG("(%x) nativeLayer", this);
+ return 0;
+}
+
+bool GraphicsLayerAndroid::setChildren(const Vector<GraphicsLayer*>& children)
+{
+ bool childrenChanged = GraphicsLayer::setChildren(children);
+ if (childrenChanged) {
+ m_needsSyncChildren = true;
+ askForSync();
+ }
+
+ return childrenChanged;
+}
+
+void GraphicsLayerAndroid::addChild(GraphicsLayer* childLayer)
+{
+#ifndef NDEBUG
+ const char* n = (static_cast<GraphicsLayerAndroid*>(childLayer))->m_name.latin1().data();
+ LOG("(%x) addChild: %x (%s)", this, childLayer, n);
+#endif
+ GraphicsLayer::addChild(childLayer);
+ m_needsSyncChildren = true;
+ askForSync();
+}
+
+void GraphicsLayerAndroid::addChildAtIndex(GraphicsLayer* childLayer, int index)
+{
+ LOG("(%x) addChild %x AtIndex %d", this, childLayer, index);
+ GraphicsLayer::addChildAtIndex(childLayer, index);
+ m_needsSyncChildren = true;
+ askForSync();
+}
+
+void GraphicsLayerAndroid::addChildBelow(GraphicsLayer* childLayer, GraphicsLayer* sibling)
+{
+ LOG("(%x) addChild %x Below %x", this, childLayer, sibling);
+ GraphicsLayer::addChildBelow(childLayer, sibling);
+ m_needsSyncChildren = true;
+ askForSync();
+}
+
+void GraphicsLayerAndroid::addChildAbove(GraphicsLayer* childLayer, GraphicsLayer* sibling)
+{
+ LOG("(%x) addChild %x Above %x", this, childLayer, sibling);
+ GraphicsLayer::addChildAbove(childLayer, sibling);
+ m_needsSyncChildren = true;
+ askForSync();
+}
+
+bool GraphicsLayerAndroid::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild)
+{
+ LOG("(%x) replaceChild %x by %x", this, oldChild, newChild);
+ bool ret = GraphicsLayer::replaceChild(oldChild, newChild);
+ m_needsSyncChildren = true;
+ askForSync();
+ return ret;
+}
+
+void GraphicsLayerAndroid::removeFromParent()
+{
+ LOG("(%x) removeFromParent()", this);
+ if (m_parent)
+ static_cast<GraphicsLayerAndroid*>(m_parent)->needsSyncChildren();
+ GraphicsLayer::removeFromParent();
+ m_needsSyncChildren = true;
+ askForSync();
+}
+
+void GraphicsLayerAndroid::needsSyncChildren()
+{
+ m_needsSyncChildren = true;
+ askForSync();
+}
+
+void GraphicsLayerAndroid::setPosition(const FloatPoint& point)
+{
+ m_currentPosition = point;
+ m_needsDisplay = true;
+#ifdef LAYER_DEBUG_2
+ LOG("(%x) setPosition(%.2f,%.2f) pos(%.2f, %.2f) anchor(%.2f,%.2f) size(%.2f, %.2f)",
+ this, point.x(), point.y(), m_currentPosition.x(), m_currentPosition.y(),
+ m_anchorPoint.x(), m_anchorPoint.y(), m_size.width(), m_size.height());
+#endif
+ askForSync();
+}
+
+void GraphicsLayerAndroid::setAnchorPoint(const FloatPoint3D& point)
+{
+ GraphicsLayer::setAnchorPoint(point);
+ m_contentLayer->setAnchorPoint(point);
+ askForSync();
+}
+
+void GraphicsLayerAndroid::setSize(const FloatSize& size)
+{
+ if ((size.width() != m_size.width())
+ || (size.height() != m_size.height())) {
+ MLOG("(%x) setSize (%.2f,%.2f)", this, size.width(), size.height());
+ GraphicsLayer::setSize(size);
+ m_contentLayer->setSize(size);
+ askForSync();
+ }
+}
+
+void GraphicsLayerAndroid::setTransform(const TransformationMatrix& t)
+{
+ TransformationMatrix::DecomposedType tDecomp;
+ t.decompose(tDecomp);
+ LOG("(%x) setTransform, translate (%.2f, %.2f), mpos(%.2f,%.2f)",
+ this, tDecomp.translateX, tDecomp.translateY,
+ m_position.x(), m_position.y());
+
+ if ((m_currentTranslateX != tDecomp.translateX)
+ || (m_currentTranslateY != tDecomp.translateY)) {
+ m_currentTranslateX = tDecomp.translateX;
+ m_currentTranslateY = tDecomp.translateY;
+ m_needsDisplay = true;
+ askForSync();
+ }
+}
+
+void GraphicsLayerAndroid::setChildrenTransform(const TransformationMatrix& t)
+{
+ if (t == m_childrenTransform)
+ return;
+ LOG("(%x) setChildrenTransform", this);
+
+ GraphicsLayer::setChildrenTransform(t);
+ for (unsigned int i = 0; i < m_children.size(); i++) {
+ GraphicsLayer* layer = m_children[i];
+ layer->setTransform(t);
+ if (layer->children().size())
+ layer->setChildrenTransform(t);
+ }
+ askForSync();
+}
+
+void GraphicsLayerAndroid::setMaskLayer(GraphicsLayer* layer)
+{
+ if (layer == m_maskLayer)
+ return;
+
+ GraphicsLayer::setMaskLayer(layer);
+ m_needsSyncMask = true;
+ askForSync();
+}
+
+void GraphicsLayerAndroid::setMasksToBounds(bool masksToBounds)
+{
+ GraphicsLayer::setMasksToBounds(masksToBounds);
+ m_needsSyncMask = true;
+ askForSync();
+}
+
+void GraphicsLayerAndroid::setDrawsContent(bool drawsContent)
+{
+ GraphicsLayer::setDrawsContent(drawsContent);
+ m_contentLayer->setDrawsContent(m_drawsContent);
+
+ if (m_drawsContent) {
+ m_haveContents = true;
+ m_contentLayer->setHaveContents(true);
+ setNeedsDisplay();
+ }
+ askForSync();
+}
+
+void GraphicsLayerAndroid::setBackgroundColor(const Color& color)
+{
+ LOG("(%x) setBackgroundColor", this);
+ GraphicsLayer::setBackgroundColor(color);
+ m_contentLayer->setBackgroundColor(color);
+ m_haveContents = true;
+ askForSync();
+}
+
+void GraphicsLayerAndroid::clearBackgroundColor()
+{
+ LOG("(%x) clearBackgroundColor", this);
+ GraphicsLayer::clearBackgroundColor();
+ askForSync();
+}
+
+void GraphicsLayerAndroid::setContentsOpaque(bool opaque)
+{
+ LOG("(%x) setContentsOpaque (%d)", this, opaque);
+ GraphicsLayer::setContentsOpaque(opaque);
+ m_haveContents = true;
+ m_contentLayer->setHaveContents(true);
+ m_contentLayer->setDrawsContent(true);
+ askForSync();
+}
+
+void GraphicsLayerAndroid::setOpacity(float opacity)
+{
+ LOG("(%x) setOpacity: %.2f", this, opacity);
+ float clampedOpacity = max(0.0f, min(opacity, 1.0f));
+
+ if (clampedOpacity == m_opacity)
+ return;
+
+ MLOG("(%x) setFinalOpacity: %.2f=>%.2f (%.2f)", this,
+ opacity, clampedOpacity, m_opacity);
+ GraphicsLayer::setOpacity(clampedOpacity);
+ askForSync();
+}
+
+bool GraphicsLayerAndroid::repaintAll()
+{
+ LOG("(%x) repaintAll", this);
+ bool ret = false;
+ for (unsigned int i = 0; i < m_children.size(); i++) {
+ GraphicsLayerAndroid* layer = static_cast<GraphicsLayerAndroid*>(m_children[i]);
+ if (layer && layer->repaintAll())
+ ret = true;
+ }
+ int nbRects = m_invalidatedRects.size();
+
+ for (int i = 0; !gPaused && i < nbRects; i++) {
+ FloatRect rect = m_invalidatedRects[i];
+ if (repaint(rect))
+ ret = true;
+ }
+ if (!gPaused) {
+ m_needsRepaint = false;
+ m_invalidatedRects.clear();
+ }
+ return ret;
+}
+
+void GraphicsLayerAndroid::setNeedsDisplay()
+{
+ LOG("(%x) setNeedsDisplay()", this);
+ FloatRect rect(0, 0, m_size.width(), m_size.height());
+ setNeedsDisplayInRect(rect);
+}
+
+void GraphicsLayerAndroid::setFrame(Frame* f)
+{
+ m_frame = f;
+}
+
+void GraphicsLayerAndroid::sendImmediateRepaint()
+{
+ LOG("(%x) sendImmediateRepaint()", this);
+ GraphicsLayerAndroid* rootGraphicsLayer = this;
+
+ while (rootGraphicsLayer->parent())
+ rootGraphicsLayer = static_cast<GraphicsLayerAndroid*>(rootGraphicsLayer->parent());
+
+ if (rootGraphicsLayer->m_frame
+ && rootGraphicsLayer->m_frame->view()) {
+ LayerAndroid* copyLayer = new LayerAndroid(m_contentLayer.get());
+ TLOG("(%x) sendImmediateRepaint, copy the layer, (%.2f,%.2f => %.2f,%.2f)",
+ this, m_contentLayer->size().width(), m_contentLayer->size().height(),
+ copyLayer->size().width(), copyLayer->size().height());
+ PlatformBridge::setRootLayer(m_frame->view(), (int)copyLayer);
+ PlatformBridge::immediateRepaint(m_frame->view());
+ }
+}
+
+bool GraphicsLayerAndroid::repaint(const FloatRect& rect)
+{
+ LOG("(%x) repaint(%.2f,%.2f,%.2f,%.2f), gPaused(%d) m_needsRepaint(%d) m_haveContents(%d) ",
+ this, rect.x(), rect.y(), rect.width(), rect.height(),
+ gPaused, m_needsRepaint, m_haveContents);
+
+ m_contentLayer->setDrawsContent(true);
+
+ if (!gPaused && m_haveContents && m_needsRepaint) {
+ SkAutoPictureRecord arp(m_contentLayer->recordContext(), m_size.width(), m_size.height());
+ SkCanvas* recordingCanvas = arp.getRecordingCanvas();
+
+ if (!recordingCanvas)
+ return false;
+
+ if ((rect.width() > 0.5) && (rect.height() > 0.5)) {
+ IntRect r((int)rect.x(), (int)rect.y(),
+ (int)rect.width(), (int)rect.height());
+
+ PlatformGraphicsContext pgc(recordingCanvas, 0);
+ GraphicsContext gc(&pgc);
+
+ // with SkPicture, we request the entire layer's content.
+ r.setX(0);
+ r.setY(0);
+ r.setWidth(m_contentLayer->size().width());
+ r.setHeight(m_contentLayer->size().height());
+ paintGraphicsLayerContents(gc, r);
+
+ TLOG("(%x) repaint(%.2f,%.2f,%.2f,%.2f) on (%.2f,%.2f) contentlayer(%.2f,%.2f,%.2f,%.2f)paintGraphicsLayer called!",
+ this, rect.x(), rect.y(), rect.width(),
+ rect.height(), m_size.width(), m_size.height(),
+ m_contentLayer->position().x(),
+ m_contentLayer->position().y(),
+ m_contentLayer->size().width(),
+ m_contentLayer->size().height());
+ }
+ return true;
+ }
+ return false;
+}
+
+void GraphicsLayerAndroid::setNeedsDisplayInRect(const FloatRect& rect)
+{
+ for (unsigned int i = 0; i < m_children.size(); i++) {
+ GraphicsLayerAndroid* layer = static_cast<GraphicsLayerAndroid*>(m_children[i]);
+ if (layer) {
+ FloatRect childrenRect(m_position.x() + m_translateX + rect.x(),
+ m_position.y() + m_translateY + rect.y(),
+ rect.width(), rect.height());
+ layer->setNeedsDisplayInRect(childrenRect);
+ }
+ }
+ if (!m_haveImage && !drawsContent()) {
+ LOG("(%x) setNeedsDisplay(%.2f,%.2f,%.2f,%.2f) doesn't have content, bypass...",
+ this, rect.x(), rect.y(), rect.width(), rect.height());
+ return;
+ }
+
+ const size_t maxDirtyRects = 8;
+ for (size_t i = 0; i < m_invalidatedRects.size(); ++i) {
+ if (m_invalidatedRects[i].contains(rect))
+ return;
+ }
+
+#ifdef LAYER_DEBUG
+ LOG("(%x) setNeedsDisplayInRect(%d) - (%.2f, %.2f, %.2f, %.2f)", this,
+ m_needsRepaint, rect.x(), rect.y(), rect.width(), rect.height());
+#endif
+
+ if (m_invalidatedRects.size() < maxDirtyRects)
+ m_invalidatedRects.append(rect);
+ else
+ m_invalidatedRects[0].unite(rect);
+
+ m_needsRepaint = true;
+ askForSync();
+}
+
+void GraphicsLayerAndroid::pauseDisplay(bool state)
+{
+ gPaused = state;
+ if (gPaused)
+ gPausedDelay = WTF::currentTime() + 1;
+}
+
+bool GraphicsLayerAndroid::addAnimation(const KeyframeValueList& valueList,
+ const IntSize& boxSize,
+ const Animation* anim,
+ const String& keyframesName,
+ double beginTime)
+{
+ if (!anim || anim->isEmptyOrZeroDuration() || valueList.size() < 2)
+ return false;
+
+ bool createdAnimations = false;
+ if (valueList.property() == AnimatedPropertyWebkitTransform) {
+ createdAnimations = createTransformAnimationsFromKeyframes(valueList,
+ anim,
+ keyframesName,
+ beginTime,
+ boxSize);
+ } else {
+ createdAnimations = createAnimationFromKeyframes(valueList,
+ anim,
+ keyframesName,
+ beginTime);
+ }
+ askForSync();
+ return createdAnimations;
+}
+
+bool GraphicsLayerAndroid::createAnimationFromKeyframes(const KeyframeValueList& valueList,
+ const Animation* animation, const String& keyframesName, double beginTime)
+{
+ bool isKeyframe = valueList.size() > 2;
+ TLOG("createAnimationFromKeyframes(%d), name(%s) beginTime(%.2f)",
+ isKeyframe, keyframesName.latin1().data(), beginTime);
+ // TODO: handles keyframe animations correctly
+
+ switch (valueList.property()) {
+ case AnimatedPropertyInvalid: break;
+ case AnimatedPropertyWebkitTransform: break;
+ case AnimatedPropertyBackgroundColor: break;
+ case AnimatedPropertyOpacity: {
+ MLOG("ANIMATEDPROPERTYOPACITY");
+ const FloatAnimationValue* startVal =
+ static_cast<const FloatAnimationValue*>(valueList.at(0));
+ const FloatAnimationValue* endVal =
+ static_cast<const FloatAnimationValue*>(valueList.at(1));
+ RefPtr<AndroidOpacityAnimation> anim = AndroidOpacityAnimation::create(m_contentLayer.get(),
+ startVal->value(),
+ endVal->value(),
+ animation,
+ beginTime);
+ if (keyframesName.isEmpty())
+ anim->setName(propertyIdToString(valueList.property()));
+ else
+ anim->setName(keyframesName);
+
+ m_contentLayer->addAnimation(anim.release());
+ AndroidAnimationTimer* timer = new AndroidAnimationTimer(this, WTF::currentTime());
+ timer->startOneShot(0);
+ return true;
+ } break;
+ }
+ return false;
+}
+
+bool GraphicsLayerAndroid::createTransformAnimationsFromKeyframes(const KeyframeValueList& valueList,
+ const Animation* animation,
+ const String& keyframesName,
+ double beginTime,
+ const IntSize& boxSize)
+{
+ ASSERT(valueList.property() == AnimatedPropertyWebkitTransform);
+ TLOG("createTransformAnimationFromKeyframes, name(%s) beginTime(%.2f)",
+ keyframesName.latin1().data(), beginTime);
+
+ TransformOperationList functionList;
+ bool listsMatch, hasBigRotation;
+ fetchTransformOperationList(valueList, functionList, listsMatch, hasBigRotation);
+
+ // If functionLists don't match we do a matrix animation, otherwise we do a component hardware animation.
+ // Also, we can't do component animation unless we have valueFunction, so we need to do matrix animation
+ // if that's not true as well.
+
+ bool isMatrixAnimation = !listsMatch;
+ size_t numAnimations = isMatrixAnimation ? 1 : functionList.size();
+ bool isKeyframe = valueList.size() > 2;
+
+ float fromTranslateX = 0;
+ float fromTranslateY = 0;
+ float fromTranslateZ = 0;
+ float toTranslateX = 0;
+ float toTranslateY = 0;
+ float toTranslateZ = 0;
+ float fromAngle = 0;
+ float toAngle = 0;
+ float fromScaleX = 1;
+ float fromScaleY = 1;
+ float fromScaleZ = 1;
+ float toScaleX = 1;
+ float toScaleY = 1;
+ float toScaleZ = 1;
+
+ bool doTranslation = false;
+ bool doRotation = false;
+ bool doScaling = false;
+
+ TLOG("(%x) animateTransform, valueList(%d) functionList(%d) duration(%.2f)", this,
+ valueList.size(), functionList.size(), animation->duration());
+
+ for (unsigned int i = 0; i < valueList.size(); i++) {
+ const TransformOperations* operation = ((TransformAnimationValue*)valueList.at(i))->value();
+ Vector<RefPtr<TransformOperation> > ops = operation->operations();
+ TLOG("(%x) animateTransform, dealing with the %d operation, with %d ops", this, i, ops.size());
+ for (unsigned int j = 0; j < ops.size(); j++) {
+ TransformOperation* op = ops[j].get();
+ TLOG("(%x) animateTransform, dealing with the %d:%d operation, current op: %d (translate is %d, rotate %d, scale %d)",
+ this, i, j, op->getOperationType(), TransformOperation::TRANSLATE, TransformOperation::ROTATE, TransformOperation::SCALE);
+ if (op->getOperationType() == TransformOperation::TRANSLATE) {
+ TranslateTransformOperation* translateOperation = (TranslateTransformOperation*) op;
+ IntSize bounds(m_size.width(), m_size.height());
+ float x = translateOperation->x(bounds);
+ float y = translateOperation->y(bounds);
+ float z = translateOperation->z(bounds);
+ if (!i) {
+ fromTranslateX = x;
+ fromTranslateY = y;
+ fromTranslateZ = z;
+ } else {
+ toTranslateX = x;
+ toTranslateY = y;
+ toTranslateZ = z;
+ }
+ TLOG("(%x) animateTransform, the %d operation is a translation(%.2f,%.2f,%.2f)",
+ this, j, x, y, z);
+ doTranslation = true;
+ } else if (op->getOperationType() == TransformOperation::TRANSLATE_X) {
+ TranslateTransformOperation* translateOperation = (TranslateTransformOperation*) op;
+ IntSize bounds(m_size.width(), m_size.height());
+ float x = translateOperation->x(bounds);
+ if (!i)
+ fromTranslateX = x;
+ else
+ toTranslateX = x;
+ TLOG("(%x) animateTransform, the %d operation is a translation_x(%.2f)",
+ this, j, x);
+ doTranslation = true;
+ } else if (op->getOperationType() == TransformOperation::TRANSLATE_Y) {
+ TranslateTransformOperation* translateOperation = (TranslateTransformOperation*) op;
+ IntSize bounds(m_size.width(), m_size.height());
+ float y = translateOperation->y(bounds);
+ if (!i)
+ fromTranslateY = y;
+ else
+ toTranslateY = y;
+ TLOG("(%x) animateTransform, the %d operation is a translation_y(%.2f)",
+ this, j, y);
+ doTranslation = true;
+ } else if ((op->getOperationType() == TransformOperation::ROTATE)
+ || (op->getOperationType() == TransformOperation::ROTATE_X)
+ || (op->getOperationType() == TransformOperation::ROTATE_Y)) {
+ LOG("(%x) animateTransform, the %d operation is a rotation", this, j);
+ RotateTransformOperation* rotateOperation = (RotateTransformOperation*) op;
+ float angle = rotateOperation->angle();
+ TLOG("(%x) animateTransform, the %d operation is a rotation (%d), of angle %.2f",
+ this, j, op->getOperationType(), angle);
+
+ if (!i)
+ fromAngle = angle;
+ else
+ toAngle = angle;
+ doRotation = true;
+ } else if (op->getOperationType() == TransformOperation::SCALE_X) {
+ ScaleTransformOperation* scaleOperation = (ScaleTransformOperation*) op;
+ if (!i)
+ fromScaleX = scaleOperation->x();
+ else
+ toScaleX = scaleOperation->x();
+ doScaling = true;
+ } else if (op->getOperationType() == TransformOperation::SCALE_Y) {
+ ScaleTransformOperation* scaleOperation = (ScaleTransformOperation*) op;
+ if (!i)
+ fromScaleY = scaleOperation->y();
+ else
+ toScaleY = scaleOperation->y();
+ doScaling = true;
+ } else if (op->getOperationType() == TransformOperation::SCALE_Z) {
+ ScaleTransformOperation* scaleOperation = (ScaleTransformOperation*) op;
+ if (!i)
+ fromScaleZ = scaleOperation->z();
+ else
+ toScaleZ = scaleOperation->z();
+ doScaling = true;
+ } else if (op->getOperationType() == TransformOperation::SCALE) {
+ ScaleTransformOperation* scaleOperation = (ScaleTransformOperation*) op;
+ if (!i) {
+ fromScaleX = scaleOperation->x();
+ fromScaleY = scaleOperation->y();
+ fromScaleZ = scaleOperation->z();
+ } else {
+ toScaleX = scaleOperation->x();
+ toScaleY = scaleOperation->y();
+ toScaleZ = scaleOperation->z();
+ }
+ doScaling = true;
+ } else {
+ TLOG("(%x) animateTransform, the %d operation is not a rotation (%d)",
+ this, j, op->getOperationType());
+ }
+ }
+ }
+
+ RefPtr<AndroidTransformAnimation> anim = AndroidTransformAnimation::create(m_contentLayer.get(),
+ animation, beginTime);
+
+ if (keyframesName.isEmpty())
+ anim->setName(propertyIdToString(valueList.property()));
+ else
+ anim->setName(keyframesName);
+
+ anim->setOriginalPosition(m_position);
+
+ if (doTranslation)
+ anim->setTranslation(fromTranslateX, fromTranslateY, fromTranslateZ,
+ toTranslateX, toTranslateY, toTranslateZ);
+ if (doRotation)
+ anim->setRotation(fromAngle, toAngle);
+ if (doScaling)
+ anim->setScale(fromScaleX, fromScaleY, fromScaleZ,
+ toScaleX, toScaleY, toScaleZ);
+ m_contentLayer->addAnimation(anim.release());
+
+ AndroidAnimationTimer* timer = new AndroidAnimationTimer(this, WTF::currentTime());
+ timer->startOneShot(0);
+ return true;
+}
+
+void GraphicsLayerAndroid::removeAnimationsForProperty(AnimatedPropertyID anID)
+{
+ TLOG("NRO removeAnimationsForProperty(%d)", anID);
+ m_contentLayer->removeAnimation(propertyIdToString(anID));
+ askForSync();
+}
+
+void GraphicsLayerAndroid::removeAnimationsForKeyframes(const String& keyframesName)
+{
+ TLOG("NRO removeAnimationsForKeyframes(%s)", keyframesName.latin1().data());
+ m_contentLayer->removeAnimation(keyframesName);
+ askForSync();
+}
+
+void GraphicsLayerAndroid::pauseAnimation(const String& keyframesName)
+{
+ TLOG("NRO pauseAnimation(%s)", keyframesName.latin1().data());
+}
+
+void GraphicsLayerAndroid::suspendAnimations(double time)
+{
+ TLOG("NRO suspendAnimations(%.2f)", time);
+}
+
+void GraphicsLayerAndroid::resumeAnimations()
+{
+ TLOG("NRO resumeAnimations()");
+}
+
+void GraphicsLayerAndroid::setContentsToImage(Image* image)
+{
+ TLOG("(%x) setContentsToImage", this, image);
+ if (image) {
+ m_haveContents = true;
+ m_contentLayer->setHaveContents(true);
+ m_contentLayer->setDrawsContent(true);
+ m_contentLayer->setHaveImage(true);
+ if (!m_haveImage) {
+ m_haveImage = true;
+ setNeedsDisplay();
+ askForSync();
+ }
+ } else
+ m_contentLayer->setHaveImage(false);
+}
+
+PlatformLayer* GraphicsLayerAndroid::platformLayer() const
+{
+ LOG("platformLayer");
+ return (PlatformLayer*) m_contentLayer.get();
+}
+
+#ifndef NDEBUG
+void GraphicsLayerAndroid::setDebugBackgroundColor(const Color& color)
+{
+}
+
+void GraphicsLayerAndroid::setDebugBorder(const Color& color, float borderWidth)
+{
+}
+#endif
+
+void GraphicsLayerAndroid::setZPosition(float position)
+{
+ LOG("(%x) setZPosition: %.2f", this, position);
+ GraphicsLayer::setZPosition(position);
+ askForSync();
+}
+
+void GraphicsLayerAndroid::askForSync()
+{
+ if (m_client)
+ m_client->notifySyncRequired(this);
+}
+
+void GraphicsLayerAndroid::syncChildren()
+{
+ if (m_needsSyncChildren) {
+ m_contentLayer->removeAllChildren();
+ for (unsigned int i = 0; i < m_children.size(); i++) {
+ m_contentLayer->addChildren(
+ (static_cast<GraphicsLayerAndroid*>(m_children[i]))->contentLayer());
+ }
+ m_needsSyncChildren = false;
+ }
+}
+
+void GraphicsLayerAndroid::syncMask()
+{
+ if (m_needsSyncMask) {
+ if (m_maskLayer) {
+ GraphicsLayerAndroid* layer = static_cast<GraphicsLayerAndroid*>(m_maskLayer);
+ LayerAndroid* mask = reinterpret_cast<LayerAndroid*>(layer->platformLayer());
+ m_contentLayer->setMaskLayer(mask);
+ } else
+ m_contentLayer->setMaskLayer(0);
+
+ m_contentLayer->setMasksToBounds(m_masksToBounds);
+ m_needsSyncMask = false;
+ }
+}
+
+void GraphicsLayerAndroid::syncPositionState()
+{
+ if (m_needsDisplay) {
+ m_translateX = m_currentTranslateX;
+ m_translateY = m_currentTranslateY;
+ m_position = m_currentPosition;
+ FloatPoint translation(m_currentTranslateX, m_currentTranslateY);
+ m_contentLayer->setTranslation(translation);
+ m_contentLayer->setPosition(m_currentPosition);
+ m_needsDisplay = false;
+ }
+}
+
+void GraphicsLayerAndroid::syncCompositingState()
+{
+ for (unsigned int i = 0; i < m_children.size(); i++) {
+ GraphicsLayerAndroid* layer = static_cast<GraphicsLayerAndroid*>(m_children[i]);
+ layer->syncCompositingState();
+ }
+
+ syncChildren();
+ syncMask();
+ syncPositionState();
+
+ if (!gPaused || WTF::currentTime() >= gPausedDelay)
+ repaintAll();
+}
+
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/WebCore/platform/graphics/android/GraphicsLayerAndroid.h b/WebCore/platform/graphics/android/GraphicsLayerAndroid.h
new file mode 100644
index 0000000..fc88fbf
--- /dev/null
+++ b/WebCore/platform/graphics/android/GraphicsLayerAndroid.h
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2009 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 GraphicsLayerAndroid_h
+#define GraphicsLayerAndroid_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "FloatRect.h"
+#include "Frame.h"
+#include "GraphicsLayer.h"
+#include "GraphicsLayerClient.h"
+#include "LayerAndroid.h"
+#include "RefPtr.h"
+#include "Vector.h"
+
+class FloatPoint3D;
+class Image;
+
+namespace WebCore {
+
+class GraphicsLayerAndroid : public GraphicsLayer {
+public:
+
+ GraphicsLayerAndroid(GraphicsLayerClient*);
+ virtual ~GraphicsLayerAndroid();
+
+ virtual void setName(const String&);
+
+ // for hosting this GraphicsLayer in a native layer hierarchy
+ virtual NativeLayer nativeLayer() const;
+
+ virtual bool setChildren(const Vector<GraphicsLayer*>&);
+ virtual void addChild(GraphicsLayer*);
+ virtual void addChildAtIndex(GraphicsLayer*, int index);
+ virtual void addChildAbove(GraphicsLayer* layer, GraphicsLayer* sibling);
+ virtual void addChildBelow(GraphicsLayer* layer, GraphicsLayer* sibling);
+ virtual bool replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild);
+
+ virtual void removeFromParent();
+
+ virtual void setPosition(const FloatPoint&);
+ virtual void setAnchorPoint(const FloatPoint3D&);
+ virtual void setSize(const FloatSize&);
+
+ virtual void setTransform(const TransformationMatrix&);
+
+ virtual void setChildrenTransform(const TransformationMatrix&);
+
+ virtual void setMaskLayer(GraphicsLayer*);
+ virtual void setMasksToBounds(bool);
+ virtual void setDrawsContent(bool);
+
+ virtual void setBackgroundColor(const Color&);
+ virtual void clearBackgroundColor();
+
+ virtual void setContentsOpaque(bool);
+
+ virtual void setOpacity(float);
+
+ virtual void setNeedsDisplay();
+ virtual void setNeedsDisplayInRect(const FloatRect&);
+
+ virtual bool addAnimation(const KeyframeValueList& valueList,
+ const IntSize& boxSize,
+ const Animation* anim,
+ const String& keyframesName,
+ double beginTime);
+ bool createTransformAnimationsFromKeyframes(const KeyframeValueList&,
+ const Animation*,
+ const String& keyframesName,
+ double beginTime,
+ const IntSize& boxSize);
+ bool createAnimationFromKeyframes(const KeyframeValueList&,
+ const Animation*,
+ const String& keyframesName,
+ double beginTime);
+
+ virtual void removeAnimationsForProperty(AnimatedPropertyID);
+ virtual void removeAnimationsForKeyframes(const String& keyframesName);
+ virtual void pauseAnimation(const String& keyframesName);
+
+ virtual void suspendAnimations(double time);
+ virtual void resumeAnimations();
+
+ virtual void setContentsToImage(Image*);
+ bool repaintAll();
+ virtual PlatformLayer* platformLayer() const;
+
+ void pauseDisplay(bool state);
+
+#ifndef NDEBUG
+ virtual void setDebugBackgroundColor(const Color&);
+ virtual void setDebugBorder(const Color&, float borderWidth);
+#endif
+
+ virtual void setZPosition(float);
+
+ void askForSync();
+ void syncPositionState();
+ void needsSyncChildren();
+ void syncChildren();
+ void syncMask();
+ virtual void syncCompositingState();
+ void setFrame(Frame*);
+
+ void sendImmediateRepaint();
+ LayerAndroid* contentLayer() { return m_contentLayer.get(); }
+
+ static int instancesCount();
+
+private:
+
+ bool repaint(const FloatRect& rect);
+
+ bool m_needsSyncChildren;
+ bool m_needsSyncMask;
+ bool m_needsRepaint;
+ bool m_needsDisplay;
+
+ bool m_haveContents;
+ bool m_haveImage;
+
+ float m_translateX;
+ float m_translateY;
+ float m_currentTranslateX;
+ float m_currentTranslateY;
+
+ FloatPoint m_currentPosition;
+
+ RefPtr<Frame> m_frame;
+
+ Vector<FloatRect> m_invalidatedRects;
+
+ RefPtr<LayerAndroid> m_contentLayer;
+};
+
+} // namespace WebCore
+
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif // GraphicsLayerAndroid_h
diff --git a/WebCore/platform/graphics/android/LayerAndroid.cpp b/WebCore/platform/graphics/android/LayerAndroid.cpp
new file mode 100644
index 0000000..347021a
--- /dev/null
+++ b/WebCore/platform/graphics/android/LayerAndroid.cpp
@@ -0,0 +1,353 @@
+#include "config.h"
+#include "LayerAndroid.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "AndroidAnimation.h"
+#include "CString.h"
+#include "GraphicsLayerAndroid.h"
+#include "PlatformGraphicsContext.h"
+#include "RenderLayer.h"
+#include "RenderLayerBacking.h"
+#include "RenderView.h"
+#include "SkDevice.h"
+#include "SkDrawFilter.h"
+#include <wtf/CurrentTime.h>
+
+#define LAYER_DEBUG // Add diagonals for debugging
+#undef LAYER_DEBUG
+
+namespace WebCore {
+
+static int gDebugLayerAndroidInstances;
+inline int LayerAndroid::instancesCount()
+{
+ return gDebugLayerAndroidInstances;
+}
+
+class OpacityDrawFilter : public SkDrawFilter {
+ public:
+ OpacityDrawFilter(int opacity) : m_opacity(opacity) { }
+ virtual bool filter(SkCanvas* canvas, SkPaint* paint, Type)
+ {
+ m_previousOpacity = paint->getAlpha();
+ paint->setAlpha(m_opacity);
+ return true;
+ }
+ virtual void restore(SkCanvas* canvas, SkPaint* paint, Type)
+ {
+ paint->setAlpha(m_previousOpacity);
+ }
+ private:
+ int m_opacity;
+ int m_previousOpacity;
+};
+
+PassRefPtr<LayerAndroid> LayerAndroid::create(bool isRootLayer)
+{
+ return adoptRef(new LayerAndroid(isRootLayer));
+}
+
+LayerAndroid::LayerAndroid(bool isRootLayer) :
+ m_doRotation(false),
+ m_isRootLayer(isRootLayer),
+ m_isFixed(false),
+ m_haveContents(false),
+ m_drawsContent(true),
+ m_haveImage(false),
+ m_haveClip(false),
+ m_backgroundColorSet(false),
+ m_angleTransform(0),
+ m_opacity(1),
+ m_size(0, 0),
+ m_position(0, 0),
+ m_translation(0, 0),
+ m_fixedPosition(0, 0),
+ m_anchorPoint(0, 0, 0),
+ m_scale(1, 1, 1),
+ m_recordingPicture(0)
+{
+ gDebugLayerAndroidInstances++;
+}
+
+LayerAndroid::LayerAndroid(LayerAndroid* layer) :
+ m_doRotation(layer->m_doRotation),
+ m_isRootLayer(layer->m_isRootLayer),
+ m_isFixed(layer->m_isFixed),
+ m_haveContents(layer->m_haveContents),
+ m_drawsContent(layer->m_drawsContent),
+ m_haveImage(layer->m_haveImage),
+ m_haveClip(layer->m_haveClip),
+ m_backgroundColorSet(layer->m_backgroundColorSet),
+ m_angleTransform(layer->m_angleTransform),
+ m_opacity(layer->m_opacity),
+ m_size(layer->m_size),
+ m_position(layer->m_position),
+ m_translation(layer->m_translation),
+ m_fixedPosition(layer->m_fixedPosition),
+ m_anchorPoint(layer->m_anchorPoint),
+ m_scale(layer->m_scale)
+{
+ if (layer->m_recordingPicture) {
+ layer->m_recordingPicture->ref();
+ m_recordingPicture = layer->m_recordingPicture;
+ } else
+ m_recordingPicture = 0;
+
+ for (unsigned int i = 0; i < layer->m_children.size(); i++)
+ m_children.append(adoptRef(new LayerAndroid(layer->m_children[i].get())));
+
+ KeyframesMap::const_iterator end = layer->m_animations.end();
+ for (KeyframesMap::const_iterator it = layer->m_animations.begin(); it != end; ++it)
+ m_animations.add((it->second)->name(), adoptRef((it->second)->copy()));
+
+ end = m_animations.end();
+ for (KeyframesMap::const_iterator it = m_animations.begin(); it != end; ++it)
+ (it->second)->setLayer(this);
+
+ gDebugLayerAndroidInstances++;
+}
+
+LayerAndroid::~LayerAndroid()
+{
+ m_recordingPicture->safeUnref();
+ m_children.clear();
+ m_animations.clear();
+ gDebugLayerAndroidInstances--;
+}
+
+static int gDebugNbAnims = 0;
+
+Vector<RefPtr<AndroidAnimationValue> >* LayerAndroid::evaluateAnimations() const
+{
+ double time = WTF::currentTime();
+ Vector<RefPtr<AndroidAnimationValue> >* result = new Vector<RefPtr<AndroidAnimationValue> >();
+ gDebugNbAnims = 0;
+ if (evaluateAnimations(time, result))
+ return result;
+ return 0;
+}
+
+bool LayerAndroid::hasAnimations() const
+{
+ for (unsigned int i = 0; i < m_children.size(); i++) {
+ if (m_children[i]->hasAnimations())
+ return true;
+ }
+ return !!m_animations.size();
+}
+
+bool LayerAndroid::evaluateAnimations(double time,
+ Vector<RefPtr<AndroidAnimationValue> >* result) const
+{
+ bool hasRunningAnimations = false;
+ for (unsigned int i = 0; i < m_children.size(); i++) {
+ if (m_children[i]->evaluateAnimations(time, result))
+ hasRunningAnimations = true;
+ }
+ KeyframesMap::const_iterator end = m_animations.end();
+ for (KeyframesMap::const_iterator it = m_animations.begin(); it != end; ++it) {
+ gDebugNbAnims++;
+ if ((it->second)->evaluate(time)) {
+ result->append((it->second)->result());
+ hasRunningAnimations = true;
+ }
+ }
+
+ return hasRunningAnimations;
+}
+
+void LayerAndroid::addAnimation(PassRefPtr<AndroidAnimation> anim)
+{
+ m_animations.add(anim->name(), anim);
+}
+
+void LayerAndroid::removeAnimation(const String& name)
+{
+ m_animations.remove(name);
+}
+
+void LayerAndroid::setFixedPosition(FloatPoint position)
+{
+ m_fixedPosition = position;
+ m_isFixed = true;
+}
+
+void LayerAndroid::setDrawsContent(bool drawsContent)
+{
+ m_drawsContent = drawsContent;
+ for (unsigned int i = 0; i < m_children.size(); i++) {
+ LayerAndroid* layer = m_children[i].get();
+ layer->setDrawsContent(drawsContent);
+ }
+}
+
+// We only use the bounding rect of the layer as mask...
+// TODO: use a real mask?
+void LayerAndroid::setMaskLayer(LayerAndroid* layer)
+{
+ if (layer)
+ m_haveClip = true;
+}
+
+void LayerAndroid::setMasksToBounds(bool masksToBounds)
+{
+ m_haveClip = masksToBounds;
+}
+
+void LayerAndroid::setBackgroundColor(const Color& color)
+{
+ m_backgroundColor = color;
+ m_backgroundColorSet = true;
+ setHaveContents(true);
+ setDrawsContent(true);
+}
+
+static int gDebugChildLevel;
+
+void LayerAndroid::paintOn(float scrollX, float scrollY, float scale, SkCanvas* canvas)
+{
+ gDebugChildLevel = 0;
+ paintChildren(scrollX, scrollY, scale, canvas, 1);
+}
+
+void LayerAndroid::setClip(SkCanvas* canvas)
+{
+ SkRect clip;
+ clip.fLeft = m_position.x() + m_translation.x();
+ clip.fTop = m_position.y() + m_translation.y();
+ clip.fRight = clip.fLeft + m_size.width();
+ clip.fBottom = clip.fTop + m_size.height();
+ canvas->clipRect(clip);
+}
+
+void LayerAndroid::paintChildren(float scrollX, float scrollY,
+ float scale, SkCanvas* canvas,
+ float opacity)
+{
+ canvas->save();
+
+ if (m_haveClip)
+ setClip(canvas);
+
+ paintMe(scrollX, scrollY, scale, canvas, opacity);
+ canvas->translate(m_position.x() + m_translation.x(),
+ m_position.y() + m_translation.y());
+
+ for (unsigned int i = 0; i < m_children.size(); i++) {
+ LayerAndroid* layer = m_children[i].get();
+ if (layer) {
+ gDebugChildLevel++;
+ layer->paintChildren(scrollX, scrollY, scale, canvas, opacity * m_opacity);
+ gDebugChildLevel--;
+ }
+ }
+
+ canvas->restore();
+}
+
+void LayerAndroid::paintMe(float scrollX,
+ float scrollY,
+ float scale,
+ SkCanvas* canvas,
+ float opacity)
+{
+ if (!prepareContext())
+ return;
+
+ if (!m_haveImage && !m_drawsContent && !m_isRootLayer)
+ return;
+
+ SkAutoCanvasRestore restore(canvas, true);
+
+ int canvasOpacity = opacity * m_opacity * 255;
+ if (canvasOpacity != 255)
+ canvas->setDrawFilter(new OpacityDrawFilter(canvasOpacity));
+
+ SkPaint paintMode;
+ if (m_backgroundColorSet) {
+ paintMode.setARGB(m_backgroundColor.alpha(),
+ m_backgroundColor.red(),
+ m_backgroundColor.green(),
+ m_backgroundColor.blue());
+ } else
+ paintMode.setARGB(0, 0, 0, 0);
+
+ paintMode.setXfermodeMode(SkXfermode::kSrc_Mode);
+
+ float x, y;
+ if (m_isFixed) {
+ x = m_fixedPosition.x() + (scrollX / scale);
+ y = m_fixedPosition.y() + (scrollY / scale);
+ } else {
+ x = m_translation.x() + m_position.x();
+ y = m_translation.y() + m_position.y();
+ }
+
+ canvas->translate(x, y);
+
+ if (m_doRotation) {
+ float anchorX = m_anchorPoint.x() * m_size.width();
+ float anchorY = m_anchorPoint.y() * m_size.height();
+ canvas->translate(anchorX, anchorY);
+ canvas->rotate(m_angleTransform);
+ canvas->translate(-anchorX, -anchorY);
+ }
+
+ float sx = m_scale.x();
+ float sy = m_scale.y();
+ if (sx > 1.0f || sy > 1.0f) {
+ float dx = (sx * m_size.width()) - m_size.width();
+ float dy = (sy * m_size.height()) - m_size.height();
+ canvas->translate(-dx / 2.0f, -dy / 2.0f);
+ canvas->scale(sx, sy);
+ }
+
+ m_recordingPicture->draw(canvas);
+
+#ifdef LAYER_DEBUG
+ float w = m_size.width();
+ float h = m_size.height();
+ SkPaint paint;
+ paint.setARGB(128, 255, 0, 0);
+ 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);
+#endif
+}
+
+SkPicture* LayerAndroid::recordContext()
+{
+ if (prepareContext(true))
+ return m_recordingPicture;
+ return 0;
+}
+
+bool LayerAndroid::prepareContext(bool force)
+{
+ if (!m_haveContents)
+ return false;
+
+ if (!m_isRootLayer) {
+ if (force || !m_recordingPicture
+ || (m_recordingPicture
+ && ((m_recordingPicture->width() != (int) m_size.width())
+ || (m_recordingPicture->height() != (int) m_size.height())))) {
+ m_recordingPicture->safeUnref();
+ m_recordingPicture = new SkPicture();
+ }
+ } else if (m_recordingPicture) {
+ m_recordingPicture->safeUnref();
+ m_recordingPicture = 0;
+ }
+
+ return m_recordingPicture;
+}
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/WebCore/platform/graphics/android/LayerAndroid.h b/WebCore/platform/graphics/android/LayerAndroid.h
new file mode 100644
index 0000000..284185d
--- /dev/null
+++ b/WebCore/platform/graphics/android/LayerAndroid.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2009 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 LayerAndroid_h
+#define LayerAndroid_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "Color.h"
+#include "FloatPoint.h"
+#include "FloatPoint3D.h"
+#include "FloatSize.h"
+#include "GraphicsContext.h"
+#include "GraphicsLayer.h"
+#include "RefPtr.h"
+#include "StringHash.h"
+#include "Vector.h"
+#include <wtf/HashSet.h>
+
+class SkCanvas;
+class SkPicture;
+class SkRect;
+
+namespace WebCore {
+
+class AndroidAnimation;
+class AndroidAnimationValue;
+
+class LayerAndroid : public RefCounted<LayerAndroid> {
+
+public:
+ static PassRefPtr<LayerAndroid> create(bool isRootLayer);
+ LayerAndroid(bool isRootLayer);
+ LayerAndroid(LayerAndroid* layer);
+ ~LayerAndroid();
+
+ static int instancesCount();
+
+ void setSize(FloatSize size) { m_size = size; }
+ void setOpacity(float opacity) { m_opacity = opacity; }
+ void setTranslation(FloatPoint translation) { m_translation = translation; }
+ void setRotation(float a) { m_angleTransform = a; m_doRotation = true; }
+ void setScale(FloatPoint3D scale) { m_scale = scale; }
+ void setPosition(FloatPoint position) { m_position = position; }
+ void setAnchorPoint(FloatPoint3D point) { m_anchorPoint = point; }
+ void setHaveContents(bool haveContents) { m_haveContents = haveContents; }
+ void setHaveImage(bool haveImage) { m_haveImage = haveImage; }
+ void setDrawsContent(bool drawsContent);
+ void setMaskLayer(LayerAndroid*);
+ void setMasksToBounds(bool);
+ void setBackgroundColor(const Color& color);
+ void setIsRootLayer(bool isRootLayer) { m_isRootLayer = isRootLayer; }
+
+ void paintOn(float scrollX, float scrollY, float scale, SkCanvas*);
+ GraphicsContext* paintContext();
+ void removeAllChildren() { m_children.clear(); }
+ void addChildren(LayerAndroid* layer) { m_children.append(layer); }
+ bool prepareContext(bool force = false);
+ void startRecording();
+ void stopRecording();
+ SkPicture* recordContext();
+ void setClip(SkCanvas* clip);
+ FloatPoint position() { return m_position; }
+ FloatPoint translation() { return m_translation; }
+ FloatSize size() { return m_size; }
+
+ void setFixedPosition(FloatPoint position);
+ void addAnimation(PassRefPtr<AndroidAnimation> anim);
+ void removeAnimation(const String& name);
+ Vector<RefPtr<AndroidAnimationValue> >* evaluateAnimations() const;
+ bool evaluateAnimations(double time,
+ Vector<RefPtr<AndroidAnimationValue> >* result) const;
+ bool hasAnimations() const;
+
+private:
+
+ void paintChildren(float scrollX, float scrollY,
+ float scale, SkCanvas* canvas,
+ float opacity);
+
+ void paintMe(float scrollX, float scrollY,
+ float scale, SkCanvas* canvas,
+ float opacity);
+
+ bool m_doRotation;
+ bool m_isRootLayer;
+ bool m_isFixed;
+ bool m_haveContents;
+ bool m_drawsContent;
+ bool m_haveImage;
+ bool m_haveClip;
+ bool m_backgroundColorSet;
+
+ float m_angleTransform;
+ float m_opacity;
+
+ FloatSize m_size;
+ FloatPoint m_position;
+ FloatPoint m_translation;
+ FloatPoint m_fixedPosition;
+ FloatPoint3D m_anchorPoint;
+ FloatPoint3D m_scale;
+
+ SkPicture* m_recordingPicture;
+ Color m_backgroundColor;
+
+ Vector<RefPtr<LayerAndroid> > m_children;
+ typedef HashMap<String, RefPtr<AndroidAnimation> > KeyframesMap;
+ KeyframesMap m_animations;
+};
+
+}
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif // LayerAndroid_h
diff --git a/WebCore/rendering/RenderLayerBacking.cpp b/WebCore/rendering/RenderLayerBacking.cpp
index a62c1be..35aa7e1 100644
--- a/WebCore/rendering/RenderLayerBacking.cpp
+++ b/WebCore/rendering/RenderLayerBacking.cpp
@@ -1007,6 +1007,7 @@ void RenderLayerBacking::paintIntoLayer(RenderLayer* rootLayer, GraphicsContext*
ASSERT(!m_owningLayer->m_usedTransparency);
}
+#if ENABLE(INSPECTOR)
static InspectorTimelineAgent* inspectorTimelineAgent(RenderObject* renderer)
{
Frame* frame = renderer->document()->frame();
@@ -1017,6 +1018,7 @@ static InspectorTimelineAgent* inspectorTimelineAgent(RenderObject* renderer)
return 0;
return page->inspectorTimelineAgent();
}
+#endif
// Up-call from compositing layer drawing callback.
void RenderLayerBacking::paintContents(const GraphicsLayer*, GraphicsContext& context, GraphicsLayerPaintingPhase paintingPhase, const IntRect& clip)
diff --git a/WebCore/rendering/RenderLayerCompositor.cpp b/WebCore/rendering/RenderLayerCompositor.cpp
index 2f5e267..8ce59cb 100644
--- a/WebCore/rendering/RenderLayerCompositor.cpp
+++ b/WebCore/rendering/RenderLayerCompositor.cpp
@@ -891,6 +891,10 @@ bool RenderLayerCompositor::requiresCompositingLayer(const RenderLayer* layer) c
requiresCompositingForVideo(layer->renderer()) ||
requiresCompositingForCanvas(layer->renderer()) ||
layer->renderer()->style()->backfaceVisibility() == BackfaceVisibilityHidden ||
+#if PLATFORM(ANDROID)
+ (layer->renderer()->isPositioned() &&
+ layer->renderer()->style()->position() == FixedPosition) ||
+#endif
clipsCompositingDescendants(layer) ||
requiresCompositingForAnimation(layer->renderer());
}
@@ -1064,4 +1068,3 @@ bool RenderLayerCompositor::layerHas3DContent(const RenderLayer* layer) const
} // namespace WebCore
#endif // USE(ACCELERATED_COMPOSITING)
-
diff --git a/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp b/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp
index 8390cbc..f14c2c1 100644
--- a/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp
+++ b/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp
@@ -38,6 +38,7 @@
#include "FrameLoader.h"
#include "FrameView.h"
#include "Geolocation.h"
+#include "GraphicsLayerAndroid.h"
#include "Page.h"
#include "Screen.h"
#include "ScriptController.h"
@@ -49,6 +50,68 @@
namespace android {
+#if USE(ACCELERATED_COMPOSITING)
+
+void ChromeClientAndroid::syncTimerFired(Timer<ChromeClientAndroid>* client)
+{
+ m_syncTimer.stop();
+ compositingLayerSync();
+}
+
+void ChromeClientAndroid::compositingLayerSync()
+{
+ if (!m_rootGraphicsLayer) {
+ scheduleCompositingLayerSync();
+ return;
+ }
+
+ if (m_webFrame) {
+ FrameView* frameView = m_webFrame->page()->mainFrame()->view();
+ if (frameView && !frameView->layoutPending() && !frameView->needsLayout()) {
+ frameView->syncCompositingStateRecursive();
+ GraphicsLayerAndroid* androidGraphicsLayer =
+ static_cast<GraphicsLayerAndroid*>(m_rootGraphicsLayer);
+ if (androidGraphicsLayer)
+ androidGraphicsLayer->sendImmediateRepaint();
+ return;
+ }
+ }
+ if (m_askToDrawAgain) {
+ m_askToDrawAgain = false;
+ scheduleCompositingLayerSync();
+ }
+}
+
+void ChromeClientAndroid::scheduleCompositingLayerSync()
+{
+ if (!m_syncTimer.isActive())
+ m_syncTimer.startOneShot(0.001); // 1ms
+ else
+ m_askToDrawAgain = true;
+}
+
+void ChromeClientAndroid::setNeedsOneShotDrawingSynchronization()
+{
+ // This should not be needed
+}
+
+void ChromeClientAndroid::attachRootGraphicsLayer(WebCore::Frame* frame, WebCore::GraphicsLayer* layer)
+{
+ m_rootGraphicsLayer = layer;
+ if (!layer) {
+ WebViewCore::getWebViewCore(frame->view())->setRootLayer(0);
+ return;
+ }
+ WebCore::GraphicsLayerAndroid* androidGraphicsLayer = static_cast<GraphicsLayerAndroid*>(layer);
+ if (frame && frame->view() && androidGraphicsLayer) {
+ androidGraphicsLayer->setFrame(frame);
+ WebCore::LayerAndroid* androidLayer = new LayerAndroid(androidGraphicsLayer->contentLayer());
+ WebViewCore::getWebViewCore(frame->view())->setRootLayer((int)androidLayer);
+ }
+}
+
+#endif
+
void ChromeClientAndroid::setWebFrame(android::WebFrame* webframe)
{
Release(m_webFrame);
diff --git a/WebKit/android/WebCoreSupport/ChromeClientAndroid.h b/WebKit/android/WebCoreSupport/ChromeClientAndroid.h
index 7396997..45dd078 100644
--- a/WebKit/android/WebCoreSupport/ChromeClientAndroid.h
+++ b/WebKit/android/WebCoreSupport/ChromeClientAndroid.h
@@ -43,7 +43,13 @@ namespace android {
class ChromeClientAndroid : public ChromeClient {
public:
- ChromeClientAndroid() : m_webFrame(0), m_geolocationPermissions(0) { }
+ ChromeClientAndroid() : m_webFrame(0), m_geolocationPermissions(0)
+#if USE(ACCELERATED_COMPOSITING)
+ , m_rootGraphicsLayer(0)
+ , m_askToDrawAgain(false)
+ , m_syncTimer(this, &ChromeClientAndroid::syncTimerFired)
+#endif
+ { }
virtual void chromeDestroyed();
virtual void setWindowRect(const FloatRect&);
@@ -149,13 +155,27 @@ namespace android {
// Android-specific
void setWebFrame(android::WebFrame* webframe);
void wakeUpMainThreadWithNewQuota(long newQuota);
+
+#if USE(ACCELERATED_COMPOSITING)
+ virtual void attachRootGraphicsLayer(WebCore::Frame*, WebCore::GraphicsLayer* g);
+ virtual void setNeedsOneShotDrawingSynchronization();
+ virtual void scheduleCompositingLayerSync();
+ void compositingLayerSync();
+ void syncTimerFired(Timer<ChromeClientAndroid>*);
+#endif
+
private:
android::WebFrame* m_webFrame;
+ // The Geolocation permissions manager.
+ OwnPtr<GeolocationPermissions> m_geolocationPermissions;
+#if USE(ACCELERATED_COMPOSITING)
+ WebCore::GraphicsLayer* m_rootGraphicsLayer;
+ bool m_askToDrawAgain;
+ Timer<ChromeClientAndroid> m_syncTimer;
+#endif
WTF::ThreadCondition m_quotaThreadCondition;
WTF::Mutex m_quotaThreadLock;
long m_newQuota;
- // The Geolocation permissions manager.
- OwnPtr<GeolocationPermissions> m_geolocationPermissions;
};
}
diff --git a/WebKit/android/WebCoreSupport/PlatformBridge.cpp b/WebKit/android/WebCoreSupport/PlatformBridge.cpp
index e4fe4ce..e93d3da 100644
--- a/WebKit/android/WebCoreSupport/PlatformBridge.cpp
+++ b/WebKit/android/WebCoreSupport/PlatformBridge.cpp
@@ -28,11 +28,28 @@
#include "JavaSharedClient.h"
#include "KeyGeneratorClient.h"
+#include "WebViewCore.h"
using namespace android;
namespace WebCore {
+#if USE(ACCELERATED_COMPOSITING)
+
+void PlatformBridge::setRootLayer(const WebCore::FrameView* view, int layer)
+{
+ android::WebViewCore* core = android::WebViewCore::getWebViewCore(view);
+ core->setRootLayer(layer);
+}
+
+void PlatformBridge::immediateRepaint(const WebCore::FrameView* view)
+{
+ android::WebViewCore* core = android::WebViewCore::getWebViewCore(view);
+ core->immediateRepaint();
+}
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
WTF::Vector<String> PlatformBridge::getSupportedKeyStrengthList()
{
KeyGeneratorClient* client = JavaSharedClient::GetKeyGeneratorClient();
@@ -51,4 +68,4 @@ String PlatformBridge::getSignedPublicKeyAndChallengeString(unsigned index, cons
return client->getSignedPublicKeyAndChallengeString(index, challenge, url);
}
-} \ No newline at end of file
+}
diff --git a/WebKit/android/jni/WebViewCore.cpp b/WebKit/android/jni/WebViewCore.cpp
index 896d902..ee1f880 100644
--- a/WebKit/android/jni/WebViewCore.cpp
+++ b/WebKit/android/jni/WebViewCore.cpp
@@ -57,6 +57,7 @@
#include "HTMLElement.h"
#include "HTMLImageElement.h"
#include "HTMLInputElement.h"
+#include "HTMLLabelElement.h"
#include "HTMLMapElement.h"
#include "HTMLNames.h"
#include "HTMLOptGroupElement.h"
@@ -68,6 +69,7 @@
#include "KeyboardCodes.h"
#include "Navigator.h"
#include "Node.h"
+#include "NodeList.h"
#include "Page.h"
#include "PageGroup.h"
#include "PlatformKeyboardEvent.h"
@@ -130,6 +132,11 @@ FILE* gRenderTreeFile = 0;
#include "TimeCounter.h"
#endif
+#if USE(ACCELERATED_COMPOSITING)
+#include "GraphicsLayerAndroid.h"
+#include "RenderLayerCompositor.h"
+#endif
+
/* We pass this flag when recording the actual content, so that we don't spend
time actually regionizing complex path clips, when all we really want to do
is record them.
@@ -195,6 +202,8 @@ struct WebViewCore::JavaGlue {
jmethodID m_updateViewport;
jmethodID m_sendNotifyProgressFinished;
jmethodID m_sendViewInvalidate;
+ jmethodID m_sendImmediateRepaint;
+ jmethodID m_setRootLayer;
jmethodID m_updateTextfield;
jmethodID m_updateTextSelection;
jmethodID m_clearTextEntry;
@@ -277,6 +286,8 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m
m_javaGlue->m_updateViewport = GetJMethod(env, clazz, "updateViewport", "()V");
m_javaGlue->m_sendNotifyProgressFinished = GetJMethod(env, clazz, "sendNotifyProgressFinished", "()V");
m_javaGlue->m_sendViewInvalidate = GetJMethod(env, clazz, "sendViewInvalidate", "(IIII)V");
+ m_javaGlue->m_sendImmediateRepaint = GetJMethod(env, clazz, "sendImmediateRepaint", "()V");
+ m_javaGlue->m_setRootLayer = GetJMethod(env, clazz, "setRootLayer", "(I)V");
m_javaGlue->m_updateTextfield = GetJMethod(env, clazz, "updateTextfield", "(IZLjava/lang/String;I)V");
m_javaGlue->m_updateTextSelection = GetJMethod(env, clazz, "updateTextSelection", "(IIII)V");
m_javaGlue->m_clearTextEntry = GetJMethod(env, clazz, "clearTextEntry", "()V");
@@ -879,6 +890,28 @@ void WebViewCore::scrollBy(int dx, int dy, bool animate)
checkException(env);
}
+#if USE(ACCELERATED_COMPOSITING)
+
+void WebViewCore::immediateRepaint()
+{
+ LOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");
+ JNIEnv* env = JSC::Bindings::getJNIEnv();
+ env->CallVoidMethod(m_javaGlue->object(env).get(),
+ m_javaGlue->m_sendImmediateRepaint);
+ checkException(env);
+}
+
+void WebViewCore::setRootLayer(int layer)
+{
+ JNIEnv* env = JSC::Bindings::getJNIEnv();
+ env->CallVoidMethod(m_javaGlue->object(env).get(),
+ m_javaGlue->m_setRootLayer,
+ layer);
+ checkException(env);
+}
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
void WebViewCore::contentDraw()
{
JNIEnv* env = JSC::Bindings::getJNIEnv();
@@ -1156,14 +1189,14 @@ void WebViewCore::setSizeScreenWidthAndScale(int width, int height,
r->setNeedsLayoutAndPrefWidthsRecalc();
m_mainFrame->view()->forceLayout();
// scroll to restore current screen center
- if (!node)
- return;
- const WebCore::IntRect& newBounds = node->getRect();
- DBG_NAV_LOGD("nb:(x=%d,y=%d,w=%d,"
- "h=%d,ns=%d)", newBounds.x(), newBounds.y(),
- newBounds.width(), newBounds.height());
- scrollBy(newBounds.x() - bounds.x(), newBounds.y() - bounds.y(),
- false);
+ if (node) {
+ const WebCore::IntRect& newBounds = node->getRect();
+ DBG_NAV_LOGD("nb:(x=%d,y=%d,w=%d,"
+ "h=%d,ns=%d)", newBounds.x(), newBounds.y(),
+ newBounds.width(), newBounds.height());
+ scrollBy(newBounds.x() - bounds.x(), newBounds.y() - bounds.y(),
+ false);
+ }
}
}
@@ -1237,6 +1270,22 @@ WebCore::String WebViewCore::retrieveAnchorText(WebCore::Frame* frame, WebCore::
return anchor ? anchor->text() : WebCore::String();
}
+WebCore::String WebViewCore::requestLabel(WebCore::Frame* frame,
+ WebCore::Node* node)
+{
+ if (CacheBuilder::validNode(m_mainFrame, frame, node)) {
+ RefPtr<WebCore::NodeList> list = node->document()->getElementsByTagName("label");
+ unsigned length = list->length();
+ for (unsigned i = 0; i < length; i++) {
+ WebCore::HTMLLabelElement* label = static_cast<WebCore::HTMLLabelElement*>(
+ list->item(i));
+ if (label->correspondingControl() == node)
+ return label->innerHTML();
+ }
+ }
+ return WebCore::String();
+}
+
void WebViewCore::updateCacheOnNodeChange()
{
gCursorBoundsMutex.lock();
@@ -1267,6 +1316,12 @@ void WebViewCore::updateCacheOnNodeChange()
void WebViewCore::updateFrameCache()
{
+#if USE(ACCELERATED_COMPOSITING)
+ ChromeClientAndroid* chromeC = static_cast<ChromeClientAndroid*>(
+ mainFrame()->page()->chrome()->client());
+ chromeC->scheduleCompositingLayerSync();
+#endif
+
if (!m_frameCacheOutOfDate) {
DBG_NAV_LOG("!m_frameCacheOutOfDate");
return;
@@ -2098,6 +2153,16 @@ int WebViewCore::handleTouchEvent(int action, int x, int y)
{
int preventDefault = 0;
+#if USE(ACCELERATED_COMPOSITING)
+ RenderView* contentRenderer = m_mainFrame->contentRenderer();
+ GraphicsLayerAndroid* rootLayer = 0;
+ if (contentRenderer)
+ rootLayer = static_cast<GraphicsLayerAndroid*>(
+ contentRenderer->compositor()->rootPlatformLayer());
+ if (rootLayer)
+ rootLayer->pauseDisplay(true);
+#endif
+
#if ENABLE(TOUCH_EVENTS) // Android
WebCore::TouchEventType type = WebCore::TouchEventCancel;
switch (action) {
@@ -2125,6 +2190,10 @@ int WebViewCore::handleTouchEvent(int action, int x, int y)
preventDefault = m_mainFrame->eventHandler()->handleTouchEvent(te);
#endif
+#if USE(ACCELERATED_COMPOSITING)
+ if (rootLayer)
+ rootLayer->pauseDisplay(false);
+#endif
return preventDefault;
}
@@ -2677,6 +2746,13 @@ static jstring WebCoreStringToJString(JNIEnv *env, WebCore::String string)
return ret;
}
+static jstring RequestLabel(JNIEnv *env, jobject obj, int framePointer,
+ int nodePointer)
+{
+ return WebCoreStringToJString(env, GET_NATIVE_VIEW(env, obj)->requestLabel(
+ (WebCore::Frame*) framePointer, (WebCore::Node*) nodePointer));
+}
+
static void UpdateFrameCacheIfLoading(JNIEnv *env, jobject obj)
{
GET_NATIVE_VIEW(env, obj)->updateFrameCacheIfLoading();
@@ -3357,6 +3433,8 @@ static JNINativeMethod gJavaWebViewCoreMethods[] = {
{ "nativeResume", "()V", (void*) Resume },
{ "nativeFreeMemory", "()V", (void*) FreeMemory },
{ "nativeSetJsFlags", "(Ljava/lang/String;)V", (void*) SetJsFlags },
+ { "nativeRequestLabel", "(II)Ljava/lang/String;",
+ (void*) RequestLabel },
{ "nativeUpdateFrameCacheIfLoading", "()V",
(void*) UpdateFrameCacheIfLoading },
{ "nativeProvideVisitedHistory", "([Ljava/lang/String;)V",
diff --git a/WebKit/android/jni/WebViewCore.h b/WebKit/android/jni/WebViewCore.h
index 4c8de78..912b8e6 100644
--- a/WebKit/android/jni/WebViewCore.h
+++ b/WebKit/android/jni/WebViewCore.h
@@ -126,6 +126,11 @@ namespace android {
*/
void contentDraw();
+#if USE(ACCELERATED_COMPOSITING)
+ void immediateRepaint();
+ void setRootLayer(int layer);
+#endif
+
/** Invalidate the view/screen, NOT the content/DOM, but expressed in
* content/DOM coordinates (i.e. they need to eventually be scaled,
* by webview into view.java coordinates
@@ -241,7 +246,7 @@ namespace android {
WebCore::String retrieveHref(WebCore::Frame* frame, WebCore::Node* node);
WebCore::String retrieveAnchorText(WebCore::Frame* frame, WebCore::Node* node);
-
+ WebCore::String requestLabel(WebCore::Frame* , WebCore::Node* );
WebCore::String getSelection(SkRegion* );
// Create a single picture to represent the drawn DOM (used by navcache)
diff --git a/WebKit/android/nav/CacheBuilder.cpp b/WebKit/android/nav/CacheBuilder.cpp
index ce78c29..c4c25db 100644
--- a/WebKit/android/nav/CacheBuilder.cpp
+++ b/WebKit/android/nav/CacheBuilder.cpp
@@ -1099,7 +1099,7 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame,
goto keepTextNode;
}
if (node->hasTagName(WebCore::HTMLNames::inputTag)) {
- HTMLInputElement* input = (HTMLInputElement*) node;
+ HTMLInputElement* input = static_cast<HTMLInputElement*>(node);
HTMLInputElement::InputType inputType = input->inputType();
if (input->isTextField()) {
type = TEXT_INPUT_CACHEDNODETYPE;
diff --git a/WebKit/android/nav/CachedFrame.cpp b/WebKit/android/nav/CachedFrame.cpp
index a95a401..299dc53 100644
--- a/WebKit/android/nav/CachedFrame.cpp
+++ b/WebKit/android/nav/CachedFrame.cpp
@@ -441,14 +441,18 @@ const CachedFrame* CachedFrame::findBestFrameAt(int x, int y) const
}
const CachedNode* CachedFrame::findBestHitAt(const WebCore::IntRect& rect,
- int* best, const CachedFrame** framePtr, int* x, int* y) const
+ const CachedFrame** framePtr, int* x, int* y) const
{
- const CachedNode* result = NULL;
- int rectWidth = rect.width();
- WebCore::IntPoint center = WebCore::IntPoint(rect.x() + (rectWidth >> 1),
- rect.y() + (rect.height() >> 1));
mRoot->setupScrolledBounds();
- for (const CachedNode* test = mCachedNodes.begin(); test != mCachedNodes.end(); test++) {
+ for (const CachedFrame* frame = mCachedFrames.end() - 1;
+ frame != mCachedFrames.begin() - 1; frame--) {
+ const CachedNode* frameResult = frame->findBestHitAt(rect,
+ framePtr, x, y);
+ if (NULL != frameResult)
+ return frameResult;
+ }
+ for (const CachedNode* test = mCachedNodes.end() - 1;
+ test != mCachedNodes.begin() - 1; test--) {
if (test->disabled())
continue;
const WebCore::IntRect& testRect = test->hitBounds();
@@ -459,29 +463,19 @@ const CachedNode* CachedFrame::findBestHitAt(const WebCore::IntRect& rect,
testData.mMouseBounds = testData.mNodeBounds = testRect;
if (mRoot->maskIfHidden(&testData) == true)
continue;
- const WebCore::IntRect& bounds = testData.mMouseBounds;
- WebCore::IntPoint testCenter = WebCore::IntPoint(bounds.x() +
- (bounds.width() >> 1), bounds.y() + (bounds.height() >> 1));
- int dx = testCenter.x() - center.x();
- int dy = testCenter.y() - center.y();
- int distance = dx * dx + dy * dy;
- if (*best < distance)
- continue;
- *best = distance;
- result = test;
- *framePtr = this;
- const WebCore::IntRect& cursorRect = test->cursorRings().at(0);
- *x = cursorRect.x() + (cursorRect.width() >> 1);
- *y = cursorRect.y() + (cursorRect.height() >> 1);
- }
- for (const CachedFrame* frame = mCachedFrames.begin();
- frame != mCachedFrames.end(); frame++) {
- const CachedNode* frameResult = frame->findBestHitAt(rect, best,
- framePtr, x, y);
- if (NULL != frameResult)
- result = frameResult;
+ for (unsigned i = 0; i < test->cursorRings().size(); i++) {
+ const WebCore::IntRect& cursorRect = test->cursorRings().at(i);
+ if (cursorRect.intersects(rect)) {
+ WebCore::IntRect intersection(cursorRect);
+ intersection.intersect(rect);
+ *x = intersection.x() + (intersection.width() >> 1);
+ *y = intersection.y() + (intersection.height() >> 1);
+ *framePtr = this;
+ return test;
+ }
+ }
}
- return result;
+ return NULL;
}
void CachedFrame::findClosest(BestData* bestData, Direction originalDirection,
diff --git a/WebKit/android/nav/CachedFrame.h b/WebKit/android/nav/CachedFrame.h
index f0996f7..7a00539 100644
--- a/WebKit/android/nav/CachedFrame.h
+++ b/WebKit/android/nav/CachedFrame.h
@@ -85,7 +85,7 @@ public:
int* y, bool checkForHidden) const;
const CachedFrame* findBestFrameAt(int x, int y) const;
const CachedNode* findBestHitAt(const WebCore::IntRect& ,
- int* best, const CachedFrame** , int* x, int* y) const;
+ const CachedFrame** , int* x, int* y) const;
void finishInit();
CachedFrame* firstChild() { return mCachedFrames.begin(); }
const CachedFrame* firstChild() const { return mCachedFrames.begin(); }
diff --git a/WebKit/android/nav/CachedInput.cpp b/WebKit/android/nav/CachedInput.cpp
index 52d2066..d7b96e3 100644
--- a/WebKit/android/nav/CachedInput.cpp
+++ b/WebKit/android/nav/CachedInput.cpp
@@ -38,18 +38,23 @@ CachedInput* CachedInput::Debug::base() const {
return nav;
}
-void CachedInput::Debug::print() const
-{
- CachedInput* b = base();
+static void printWebCoreString(const char* label,
+ const WebCore::String& string) {
char scratch[256];
- size_t index = snprintf(scratch, sizeof(scratch), "// char* mName=\"");
- const UChar* ch = b->mName.characters();
+ size_t index = snprintf(scratch, sizeof(scratch), label);
+ const UChar* ch = string.characters();
while (ch && *ch && index < sizeof(scratch)) {
UChar c = *ch++;
if (c < ' ' || c >= 0x7f) c = ' ';
scratch[index++] = c;
}
DUMP_NAV_LOGD("%.*s\"\n", index, scratch);
+}
+
+void CachedInput::Debug::print() const
+{
+ CachedInput* b = base();
+ printWebCoreString("// char* mName=\"", b->mName);
DUMP_NAV_LOGD("// void* mForm=%p;", b->mForm);
DUMP_NAV_LOGD("// int mMaxLength=%d;\n", b->mMaxLength);
DUMP_NAV_LOGD("// int mTextSize=%d;\n", b->mTextSize);
diff --git a/WebKit/android/nav/CachedRoot.cpp b/WebKit/android/nav/CachedRoot.cpp
index 2354ebc..e783eae 100644
--- a/WebKit/android/nav/CachedRoot.cpp
+++ b/WebKit/android/nav/CachedRoot.cpp
@@ -756,14 +756,17 @@ bool CachedRoot::checkRings(const WTF::Vector<WebCore::IntRect>& rings,
return ringCheck.success();
}
-CachedRoot::ImeAction CachedRoot::cursorTextFieldAction() const
+CachedRoot::ImeAction CachedRoot::currentTextFieldAction() const
{
- const CachedFrame* cursorFrame;
- const CachedNode* cursor = currentCursor(&cursorFrame);
- if (!cursor) {
- // Error case. The cursor has no action, because there is no node under
- // the cursor
- return FAILURE;
+ const CachedFrame* currentFrame;
+ const CachedNode* current = currentCursor(&currentFrame);
+ if (!current) {
+ // Although the cursor is not on a textfield, a textfield may have
+ // focus. Find the action for that textfield.
+ current = currentFocus(&currentFrame);
+ if (!current)
+ // Error case. No cursor and no focus.
+ return FAILURE;
}
const CachedNode* firstTextfield = nextTextField(0, 0, false);
if (!firstTextfield) {
@@ -773,8 +776,8 @@ CachedRoot::ImeAction CachedRoot::cursorTextFieldAction() const
// Now find the next textfield/area starting with the cursor
const CachedFrame* potentialFrame;
const CachedNode* potentialNext
- = cursorFrame->nextTextField(cursor, &potentialFrame, true);
- if (potentialNext && cursorFrame->textInput(cursor)->formPointer()
+ = currentFrame->nextTextField(current, &potentialFrame, true);
+ if (potentialNext && currentFrame->textInput(current)->formPointer()
== potentialFrame->textInput(potentialNext)->formPointer()) {
// There is a textfield/area after the cursor in the same form,
// so the textfield under the cursor should have the NEXT action
@@ -797,7 +800,7 @@ const CachedNode* CachedRoot::findAt(const WebCore::IntRect& rect,
DBG_NAV_LOGD("node=%d (%p)", node == NULL ? 0 : node->index(),
node == NULL ? NULL : node->nodePointer());
if (node == NULL) {
- node = findBestHitAt(rect, &best, framePtr, x, y);
+ node = findBestHitAt(rect, framePtr, x, y);
DBG_NAV_LOGD("node=%d (%p)", node == NULL ? 0 : node->index(),
node == NULL ? NULL : node->nodePointer());
}
diff --git a/WebKit/android/nav/CachedRoot.h b/WebKit/android/nav/CachedRoot.h
index 435937a..5fdf8df 100644
--- a/WebKit/android/nav/CachedRoot.h
+++ b/WebKit/android/nav/CachedRoot.h
@@ -52,11 +52,12 @@ public:
void checkForJiggle(int* ) const;
bool checkRings(const WTF::Vector<WebCore::IntRect>& rings,
const WebCore::IntRect& bounds) const;
- WebCore::IntPoint cursorLocation() const;
// This method returns the desired ImeAction for the textfield where the
- // mouse cursor currently is. If the mouse cursor is not on a textfield,
+ // mouse cursor currently is, or where the focus is if there is no mouse
+ // cursor. If the mouse cursor is not on a textfield,
// it will return FAILURE
- ImeAction cursorTextFieldAction() const;
+ ImeAction currentTextFieldAction() const;
+ WebCore::IntPoint cursorLocation() const;
int documentHeight() { return mContents.height(); }
int documentWidth() { return mContents.width(); }
const CachedNode* findAt(const WebCore::IntRect& , const CachedFrame** ,
diff --git a/WebKit/android/nav/WebView.cpp b/WebKit/android/nav/WebView.cpp
index c29cb22..1267647 100644
--- a/WebKit/android/nav/WebView.cpp
+++ b/WebKit/android/nav/WebView.cpp
@@ -28,6 +28,7 @@
#include <config.h>
#include "android_graphics.h"
+#include "AndroidAnimation.h"
#include "AndroidLog.h"
#include "AtomicString.h"
#include "CachedFrame.h"
@@ -39,6 +40,7 @@
#include "HTMLInputElement.h"
#include "IntPoint.h"
#include "IntRect.h"
+#include "LayerAndroid.h"
#include "Node.h"
#include "PlatformGraphicsContext.h"
#include "PlatformString.h"
@@ -104,11 +106,11 @@ struct JavaGlue {
jmethodID m_sendMoveMouse;
jmethodID m_sendMoveMouseIfLatest;
jmethodID m_sendMotionUp;
+ jmethodID m_domChangedFocus;
jmethodID m_getScaledMaxXScroll;
jmethodID m_getScaledMaxYScroll;
jmethodID m_getVisibleRect;
jmethodID m_rebuildWebTextView;
- jmethodID m_setOkayToNotMatch;
jmethodID m_displaySoftKeyboard;
jmethodID m_viewInvalidate;
jmethodID m_viewInvalidateRect;
@@ -134,11 +136,11 @@ WebView(JNIEnv* env, jobject javaWebView, int viewImpl)
m_javaGlue.m_sendMoveMouse = GetJMethod(env, clazz, "sendMoveMouse", "(IIII)V");
m_javaGlue.m_sendMoveMouseIfLatest = GetJMethod(env, clazz, "sendMoveMouseIfLatest", "(Z)V");
m_javaGlue.m_sendMotionUp = GetJMethod(env, clazz, "sendMotionUp", "(IIIII)V");
+ m_javaGlue.m_domChangedFocus = GetJMethod(env, clazz, "domChangedFocus", "()V");
m_javaGlue.m_getScaledMaxXScroll = GetJMethod(env, clazz, "getScaledMaxXScroll", "()I");
m_javaGlue.m_getScaledMaxYScroll = GetJMethod(env, clazz, "getScaledMaxYScroll", "()I");
m_javaGlue.m_getVisibleRect = GetJMethod(env, clazz, "sendOurVisibleRect", "()Landroid/graphics/Rect;");
m_javaGlue.m_rebuildWebTextView = GetJMethod(env, clazz, "rebuildWebTextView", "()V");
- m_javaGlue.m_setOkayToNotMatch = GetJMethod(env, clazz, "setOkayNotToMatch", "()V");
m_javaGlue.m_displaySoftKeyboard = GetJMethod(env, clazz, "displaySoftKeyboard", "(Z)V");
m_javaGlue.m_viewInvalidate = GetJMethod(env, clazz, "viewInvalidate", "()V");
m_javaGlue.m_viewInvalidateRect = GetJMethod(env, clazz, "viewInvalidate", "(IIII)V");
@@ -613,6 +615,7 @@ CachedRoot* getFrameCache(FrameCachePermission allowNewer)
}
DBG_NAV_LOGD("%s", "m_viewImpl->m_updatedFrameCache == true");
bool hadCursor = m_frameCacheUI && m_frameCacheUI->currentCursor();
+ const CachedNode* oldFocus = m_frameCacheUI ? m_frameCacheUI->currentFocus() : 0;
m_viewImpl->gFrameCacheMutex.lock();
delete m_frameCacheUI;
delete m_navPictureUI;
@@ -623,6 +626,19 @@ CachedRoot* getFrameCache(FrameCachePermission allowNewer)
m_viewImpl->m_navPictureKit = 0;
m_viewImpl->gFrameCacheMutex.unlock();
fixCursor();
+ if (oldFocus && m_frameCacheUI) {
+ const CachedNode* newFocus = m_frameCacheUI->currentFocus();
+ if (newFocus && oldFocus != newFocus && newFocus->isTextInput()
+ && oldFocus->isTextInput()
+ && newFocus != m_frameCacheUI->currentCursor()) {
+ // The focus has changed. We may need to update things.
+ LOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!");
+ JNIEnv* env = JSC::Bindings::getJNIEnv();
+ env->CallVoidMethod(m_javaGlue.object(env).get(),
+ m_javaGlue.m_domChangedFocus);
+ checkException(env);
+ }
+ }
if (hadCursor && (!m_frameCacheUI || !m_frameCacheUI->currentCursor()))
viewInvalidate(); // redraw in case cursor ring is still visible
return m_frameCacheUI;
@@ -839,7 +855,7 @@ bool moveCursor(int keyCode, int count, bool ignoreScroll)
void notifyProgressFinished()
{
DBG_NAV_LOGD("cursorIsTextInput=%d", cursorIsTextInput(DontAllowNewer));
- rebuildWebTextView(false);
+ rebuildWebTextView();
#if DEBUG_NAV_UI
if (m_frameCacheUI) {
const CachedNode* focus = m_frameCacheUI->currentFocus();
@@ -951,7 +967,9 @@ bool motionUp(int x, int y, int slop)
}
DBG_NAV_LOGD("CachedNode:%p (%d) x=%d y=%d rx=%d ry=%d", result,
result->index(), x, y, rx, ry);
- setNavBounds(WebCore::IntRect(rx, ry, 1, 1));
+ WebCore::IntRect navBounds = WebCore::IntRect(rx, ry, 1, 1);
+ setNavBounds(navBounds);
+ root->rootHistory()->setMouseBounds(navBounds);
updateCursorBounds(root, frame, result);
root->setCursor(const_cast<CachedFrame*>(frame),
const_cast<CachedNode*>(result));
@@ -964,7 +982,7 @@ bool motionUp(int x, int y, int slop)
viewInvalidate();
if (result->isTextInput()) {
bool isReadOnly = frame->textInput(result)->isReadOnly();
- rebuildWebTextView(true);
+ rebuildWebTextView();
if (!isReadOnly)
displaySoftKeyboard(true);
} else {
@@ -1277,7 +1295,7 @@ bool hasFocusNode()
return focusNode;
}
-void rebuildWebTextView(bool needNotMatchFocus)
+void rebuildWebTextView()
{
JNIEnv* env = JSC::Bindings::getJNIEnv();
AutoJObject obj = m_javaGlue.object(env);
@@ -1287,10 +1305,6 @@ void rebuildWebTextView(bool needNotMatchFocus)
return;
env->CallVoidMethod(obj.get(), m_javaGlue.m_rebuildWebTextView);
checkException(env);
- if (needNotMatchFocus) {
- env->CallVoidMethod(obj.get(), m_javaGlue.m_setOkayToNotMatch);
- checkException(env);
- }
}
void displaySoftKeyboard(bool isTextView)
@@ -1592,6 +1606,86 @@ static void nativeDrawMatches(JNIEnv *env, jobject obj, jobject canv)
view->drawMatches(canvas);
}
+static void nativeDrawLayers(JNIEnv *env, jobject obj,
+ jint layer, jfloat scrollX, jfloat scrollY,
+ jfloat scale, jobject canv)
+{
+ if (!env)
+ return;
+ if (!layer)
+ return;
+ if (!canv)
+ return;
+
+#if USE(ACCELERATED_COMPOSITING)
+ LayerAndroid* layerImpl = reinterpret_cast<LayerAndroid*>(layer);
+ SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, canv);
+ if (canvas)
+ layerImpl->paintOn(scrollX, scrollY, scale, canvas);
+#endif
+}
+
+static void nativeUpdateLayers(JNIEnv *env, jobject obj,
+ jint layer, jint updates)
+{
+ if (!env)
+ return;
+ if (!layer)
+ return;
+ if (!updates)
+ return;
+
+#if USE(ACCELERATED_COMPOSITING)
+ Vector<RefPtr<AndroidAnimationValue> >* updatesImpl =
+ reinterpret_cast<Vector<RefPtr<AndroidAnimationValue> >* >(updates);
+ if (updatesImpl) {
+ for (unsigned int i = 0; i < updatesImpl->size(); i++)
+ (updatesImpl->at(i))->apply();
+ delete updatesImpl;
+ }
+#endif
+}
+
+static bool nativeLayersHaveAnimations(JNIEnv *env, jobject obj, jint layer)
+{
+ if (!env)
+ return false;
+ if (!layer)
+ return false;
+#if USE(ACCELERATED_COMPOSITING)
+ LayerAndroid* layerImpl = reinterpret_cast<LayerAndroid*>(layer);
+ return layerImpl->hasAnimations();
+#else
+ return false;
+#endif
+}
+
+static int nativeEvaluateLayersAnimations(JNIEnv *env, jobject obj, jint layer)
+{
+ if (!env)
+ return 0;
+ if (!layer)
+ return 0;
+#if USE(ACCELERATED_COMPOSITING)
+ LayerAndroid* layerImpl = reinterpret_cast<LayerAndroid*>(layer);
+ return reinterpret_cast<int>(layerImpl->evaluateAnimations());
+#else
+ return 0;
+#endif
+}
+
+static void nativeDestroyLayer(JNIEnv *env, jobject obj, jint layer)
+{
+ if (!env)
+ return;
+ if (!layer)
+ return;
+#if USE(ACCELERATED_COMPOSITING)
+ LayerAndroid* layerImpl = reinterpret_cast<LayerAndroid*>(layer);
+ delete layerImpl;
+#endif
+}
+
static void nativeDrawCursorRing(JNIEnv *env, jobject obj, jobject canv)
{
SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, canv);
@@ -1767,12 +1861,6 @@ static int nativeFocusCandidateType(JNIEnv *env, jobject obj)
}
}
-static bool nativeFocusCandidateIsPlugin(JNIEnv *env, jobject obj)
-{
- const CachedNode* node = getFocusCandidate(env, obj);
- return node ? node->isPlugin() : false;
-}
-
static bool nativeFocusIsPlugin(JNIEnv *env, jobject obj)
{
const CachedNode* node = getFocusNode(env, obj);
@@ -2002,11 +2090,13 @@ static void nativeMoveCursorToNextTextInput(JNIEnv *env, jobject obj)
CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer);
if (!root)
return;
- const CachedNode* cursor = root->currentCursor();
- if (!cursor)
+ const CachedNode* current = root->currentCursor();
+ if (!current)
+ current = root->currentFocus();
+ if (!current)
return;
const CachedFrame* frame;
- const CachedNode* next = root->nextTextField(cursor, &frame, true);
+ const CachedNode* next = root->nextTextField(current, &frame, true);
if (!next)
return;
const WebCore::IntRect& bounds = next->bounds();
@@ -2027,7 +2117,7 @@ static jint nativeTextFieldAction(JNIEnv *env, jobject obj)
CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer);
if (!root)
return static_cast<jint>(CachedRoot::FAILURE);
- return static_cast<jint>(root->cursorTextFieldAction());
+ return static_cast<jint>(root->currentTextFieldAction());
}
static int nativeMoveGeneration(JNIEnv *env, jobject obj)
@@ -2131,6 +2221,16 @@ static JNINativeMethod gJavaWebViewMethods[] = {
(void*) nativeDestroy },
{ "nativeDrawCursorRing", "(Landroid/graphics/Canvas;)V",
(void*) nativeDrawCursorRing },
+ { "nativeDestroyLayer", "(I)V",
+ (void*) nativeDestroyLayer },
+ { "nativeLayersHaveAnimations", "(I)Z",
+ (void*) nativeLayersHaveAnimations },
+ { "nativeEvaluateLayersAnimations", "(I)I",
+ (void*) nativeEvaluateLayersAnimations },
+ { "nativeDrawLayers", "(IFFFLandroid/graphics/Canvas;)V",
+ (void*) nativeDrawLayers },
+ { "nativeUpdateLayers", "(II)V",
+ (void*) nativeUpdateLayers },
{ "nativeDrawMatches", "(Landroid/graphics/Canvas;)V",
(void*) nativeDrawMatches },
{ "nativeDrawSelectionPointer", "(Landroid/graphics/Canvas;FIIZ)V",
@@ -2147,8 +2247,6 @@ static JNINativeMethod gJavaWebViewMethods[] = {
(void*) nativeFocusCandidateFramePointer },
{ "nativeFocusCandidateIsPassword", "()Z",
(void*) nativeFocusCandidateIsPassword },
- { "nativeFocusCandidateIsPlugin", "()Z",
- (void*) nativeFocusCandidateIsPlugin },
{ "nativeFocusCandidateIsRtlText", "()Z",
(void*) nativeFocusCandidateIsRtlText },
{ "nativeFocusCandidateIsTextInput", "()Z",