summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Android.mk11
-rw-r--r--Source/JavaScriptCore/wtf/Platform.h3
-rw-r--r--Source/WebCore/Android.mk12
-rw-r--r--Source/WebCore/dom/Document.cpp8
-rw-r--r--Source/WebCore/dom/Document.h8
-rw-r--r--Source/WebCore/dom/Element.cpp20
-rw-r--r--Source/WebCore/editing/TextIterator.cpp1
-rw-r--r--Source/WebCore/html/HTMLInputElement.cpp10
-rw-r--r--Source/WebCore/html/HTMLMediaElement.cpp16
-rw-r--r--Source/WebCore/html/HTMLMetaElement.cpp14
-rw-r--r--Source/WebCore/html/HTMLTextAreaElement.cpp2
-rw-r--r--Source/WebCore/loader/EmptyClients.h4
-rw-r--r--Source/WebCore/page/ChromeClient.h4
-rw-r--r--Source/WebCore/page/Geolocation.cpp12
-rw-r--r--Source/WebCore/page/GeolocationController.cpp3
-rw-r--r--Source/WebCore/page/Settings.cpp2
-rw-r--r--Source/WebCore/page/Settings.h8
-rw-r--r--Source/WebCore/platform/GeolocationService.h5
-rw-r--r--Source/WebCore/platform/android/GeolocationServiceAndroid.cpp204
-rw-r--r--Source/WebCore/platform/android/GeolocationServiceAndroid.h79
-rw-r--r--Source/WebCore/platform/android/PlatformBridge.h6
-rw-r--r--Source/WebCore/platform/android/RenderThemeAndroid.cpp64
-rw-r--r--Source/WebCore/platform/graphics/MediaPlayer.cpp8
-rw-r--r--Source/WebCore/platform/graphics/MediaPlayer.h1
-rw-r--r--Source/WebCore/platform/graphics/MediaPlayerPrivate.h4
-rw-r--r--Source/WebCore/platform/graphics/android/GLWebViewState.cpp4
-rw-r--r--Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp84
-rw-r--r--Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.h19
-rw-r--r--Source/WebCore/platform/graphics/android/ImageAndroid.cpp1
-rw-r--r--Source/WebCore/platform/graphics/android/ImageBufferAndroid.cpp20
-rw-r--r--Source/WebCore/platform/graphics/android/ImageBufferDataAndroid.h5
-rw-r--r--Source/WebCore/platform/graphics/android/PathAndroid.cpp1
-rw-r--r--Source/WebCore/platform/graphics/android/PatternAndroid.cpp3
-rw-r--r--Source/WebCore/platform/graphics/android/context/GraphicsContextAndroid.cpp12
-rw-r--r--Source/WebCore/platform/graphics/android/context/GraphicsOperation.cpp (renamed from Source/WebCore/platform/graphics/android/context/android_graphics.h)37
-rw-r--r--Source/WebCore/platform/graphics/android/context/GraphicsOperation.h620
-rw-r--r--Source/WebCore/platform/graphics/android/context/GraphicsOperationCollection.cpp63
-rw-r--r--Source/WebCore/platform/graphics/android/context/PlatformGraphicsContext.cpp46
-rw-r--r--Source/WebCore/platform/graphics/android/context/PlatformGraphicsContext.h40
-rw-r--r--Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.cpp870
-rw-r--r--Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.h127
-rw-r--r--Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextSkia.cpp39
-rw-r--r--Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextSkia.h25
-rw-r--r--Source/WebCore/platform/graphics/android/context/RTree.cpp598
-rw-r--r--Source/WebCore/platform/graphics/android/context/RTree.h186
-rw-r--r--Source/WebCore/platform/graphics/android/context/RecordingContextCanvasProxy.cpp68
-rw-r--r--Source/WebCore/platform/graphics/android/context/RecordingContextCanvasProxy.h102
-rw-r--r--Source/WebCore/platform/graphics/android/fonts/FontAndroid.cpp145
-rw-r--r--Source/WebCore/platform/graphics/android/fonts/FontPlatformData.h36
-rw-r--r--Source/WebCore/platform/graphics/android/fonts/FontPlatformDataAndroid.cpp155
-rw-r--r--Source/WebCore/platform/graphics/android/layers/CanvasTexture.cpp7
-rw-r--r--Source/WebCore/platform/graphics/android/layers/DumpLayer.cpp88
-rw-r--r--Source/WebCore/platform/graphics/android/layers/DumpLayer.h66
-rw-r--r--Source/WebCore/platform/graphics/android/layers/FixedPositioning.cpp28
-rw-r--r--Source/WebCore/platform/graphics/android/layers/FixedPositioning.h2
-rw-r--r--Source/WebCore/platform/graphics/android/layers/IFrameLayerAndroid.cpp6
-rw-r--r--Source/WebCore/platform/graphics/android/layers/IFrameLayerAndroid.h2
-rw-r--r--Source/WebCore/platform/graphics/android/layers/LayerAndroid.cpp175
-rw-r--r--Source/WebCore/platform/graphics/android/layers/LayerAndroid.h18
-rw-r--r--Source/WebCore/platform/graphics/android/layers/LayerContent.h2
-rw-r--r--Source/WebCore/platform/graphics/android/layers/MediaPlayerPrivateAndroid.h4
-rw-r--r--Source/WebCore/platform/graphics/android/layers/PictureLayerContent.cpp15
-rw-r--r--Source/WebCore/platform/graphics/android/layers/PictureLayerContent.h1
-rw-r--r--Source/WebCore/platform/graphics/android/layers/PicturePileLayerContent.cpp10
-rw-r--r--Source/WebCore/platform/graphics/android/layers/PicturePileLayerContent.h13
-rw-r--r--Source/WebCore/platform/graphics/android/layers/VideoLayerAndroid.h2
-rw-r--r--Source/WebCore/platform/graphics/android/layers/VideoLayerManager.cpp5
-rw-r--r--Source/WebCore/platform/graphics/android/layers/VideoLayerManager.h3
-rw-r--r--Source/WebCore/platform/graphics/android/rendering/BaseRenderer.cpp19
-rw-r--r--Source/WebCore/platform/graphics/android/rendering/BaseRenderer.h6
-rw-r--r--Source/WebCore/platform/graphics/android/rendering/GLExtras.cpp1
-rw-r--r--Source/WebCore/platform/graphics/android/rendering/GLUtils.cpp6
-rw-r--r--Source/WebCore/platform/graphics/android/rendering/GLUtils.h4
-rw-r--r--Source/WebCore/platform/graphics/android/rendering/GaneshRenderer.cpp3
-rw-r--r--Source/WebCore/platform/graphics/android/rendering/GaneshRenderer.h4
-rw-r--r--Source/WebCore/platform/graphics/android/rendering/ImageTexture.cpp1
-rw-r--r--Source/WebCore/platform/graphics/android/rendering/ImagesManager.cpp12
-rw-r--r--Source/WebCore/platform/graphics/android/rendering/ImagesManager.h3
-rw-r--r--Source/WebCore/platform/graphics/android/rendering/InstrumentedPlatformCanvas.h314
-rw-r--r--Source/WebCore/platform/graphics/android/rendering/PaintTileOperation.cpp4
-rw-r--r--Source/WebCore/platform/graphics/android/rendering/PaintTileOperation.h2
-rw-r--r--Source/WebCore/platform/graphics/android/rendering/QueuedOperation.h4
-rw-r--r--Source/WebCore/platform/graphics/android/rendering/RasterRenderer.cpp53
-rw-r--r--Source/WebCore/platform/graphics/android/rendering/RasterRenderer.h8
-rw-r--r--Source/WebCore/platform/graphics/android/rendering/ShaderProgram.cpp85
-rw-r--r--Source/WebCore/platform/graphics/android/rendering/ShaderProgram.h6
-rw-r--r--Source/WebCore/platform/graphics/android/rendering/Surface.cpp4
-rw-r--r--Source/WebCore/platform/graphics/android/rendering/SurfaceBacking.cpp28
-rw-r--r--Source/WebCore/platform/graphics/android/rendering/SurfaceBacking.h3
-rw-r--r--Source/WebCore/platform/graphics/android/rendering/SurfaceCollection.cpp22
-rw-r--r--Source/WebCore/platform/graphics/android/rendering/SurfaceCollectionManager.cpp32
-rw-r--r--Source/WebCore/platform/graphics/android/rendering/TexturesGenerator.cpp21
-rw-r--r--Source/WebCore/platform/graphics/android/rendering/TexturesGenerator.h10
-rw-r--r--Source/WebCore/platform/graphics/android/rendering/Tile.cpp11
-rw-r--r--Source/WebCore/platform/graphics/android/rendering/Tile.h8
-rw-r--r--Source/WebCore/platform/graphics/android/rendering/TilesManager.cpp52
-rw-r--r--Source/WebCore/platform/graphics/android/rendering/TilesManager.h25
-rw-r--r--Source/WebCore/platform/graphics/android/rendering/TransferQueue.cpp23
-rw-r--r--Source/WebCore/platform/graphics/android/rendering/TransferQueue.h6
-rw-r--r--Source/WebCore/platform/graphics/android/utils/LinearAllocator.cpp225
-rw-r--r--Source/WebCore/platform/graphics/android/utils/LinearAllocator.h (renamed from Source/WebCore/platform/graphics/android/context/GraphicsOperationCollection.h)64
-rw-r--r--Source/WebCore/platform/mock/GeolocationServiceMock.cpp5
-rwxr-xr-xSource/WebCore/platform/mock/GeolocationServiceMock.h5
-rw-r--r--Source/WebCore/plugins/android/PluginViewAndroid.cpp16
-rw-r--r--Source/WebKit/Android.mk4
-rw-r--r--Source/WebKit/android/AndroidLog.h4
-rw-r--r--Source/WebKit/android/RenderSkinMediaButton.cpp14
-rw-r--r--Source/WebKit/android/RenderSkinMediaButton.h34
-rw-r--r--Source/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp62
-rw-r--r--Source/WebKit/android/WebCoreSupport/ChromeClientAndroid.h26
-rw-r--r--Source/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.cpp1
-rw-r--r--Source/WebKit/android/WebCoreSupport/GeolocationClientAndroid.cpp96
-rw-r--r--Source/WebKit/android/WebCoreSupport/GeolocationClientAndroid.h61
-rw-r--r--Source/WebKit/android/WebCoreSupport/GeolocationClientImpl.cpp223
-rw-r--r--Source/WebKit/android/WebCoreSupport/GeolocationClientImpl.h86
-rw-r--r--Source/WebKit/android/WebCoreSupport/GeolocationManager.cpp125
-rw-r--r--Source/WebKit/android/WebCoreSupport/GeolocationManager.h80
-rwxr-xr-xSource/WebKit/android/WebCoreSupport/GeolocationPermissions.cpp21
-rw-r--r--Source/WebKit/android/WebCoreSupport/GeolocationPermissions.h11
-rw-r--r--Source/WebKit/android/WebCoreSupport/MediaPlayerPrivateAndroid.cpp58
-rw-r--r--Source/WebKit/android/WebCoreSupport/MemoryUsage.cpp44
-rw-r--r--Source/WebKit/android/WebCoreSupport/PlatformBridge.cpp21
-rw-r--r--Source/WebKit/android/WebCoreSupport/WebCookieJar.cpp2
-rw-r--r--Source/WebKit/android/WebCoreSupport/WebRequest.cpp7
-rw-r--r--Source/WebKit/android/WebCoreSupport/WebRequest.h2
-rw-r--r--Source/WebKit/android/WebCoreSupport/WebUrlLoaderClient.cpp2
-rw-r--r--Source/WebKit/android/jni/GeolocationServiceBridge.cpp (renamed from Source/WebCore/platform/android/GeolocationServiceBridge.cpp)42
-rw-r--r--Source/WebKit/android/jni/GeolocationServiceBridge.h (renamed from Source/WebCore/platform/android/GeolocationServiceBridge.h)33
-rwxr-xr-xSource/WebKit/android/jni/MockGeolocation.cpp68
-rw-r--r--Source/WebKit/android/jni/PicturePile.cpp225
-rw-r--r--Source/WebKit/android/jni/PicturePile.h38
-rw-r--r--Source/WebKit/android/jni/ViewStateSerializer.cpp65
-rw-r--r--Source/WebKit/android/jni/WebCoreFrameBridge.cpp25
-rw-r--r--Source/WebKit/android/jni/WebCoreFrameBridge.h2
-rw-r--r--Source/WebKit/android/jni/WebFrameView.cpp1
-rw-r--r--Source/WebKit/android/jni/WebHistory.cpp65
-rw-r--r--Source/WebKit/android/jni/WebSettings.cpp6
-rw-r--r--Source/WebKit/android/jni/WebStorage.cpp10
-rw-r--r--Source/WebKit/android/jni/WebViewCore.cpp376
-rw-r--r--Source/WebKit/android/jni/WebViewCore.h39
-rw-r--r--Source/WebKit/android/nav/DrawExtra.cpp8
-rw-r--r--Source/WebKit/android/nav/DrawExtra.h3
-rw-r--r--Source/WebKit/android/nav/SelectText.h10
-rw-r--r--Source/WebKit/android/nav/WebView.cpp72
-rw-r--r--Source/WebKit/android/plugins/ANPSoundInterface.cpp2
-rw-r--r--Source/WebKit/android/plugins/ANPSurfaceInterface.cpp1
-rw-r--r--Source/WebKit/android/plugins/PluginWidgetAndroid.cpp8
-rw-r--r--Source/WebKit/android/plugins/PluginWidgetAndroid.h3
-rw-r--r--Source/WebKit/android/smoke/MessageThread.cpp146
-rw-r--r--Source/WebKit/android/smoke/MessageThread.h108
-rw-r--r--Source/WebKit/android/smoke/MessageTypes.h159
-rw-r--r--ThirdPartyProject.prop13
-rw-r--r--WEBKIT_MERGE_REVISION5
153 files changed, 5137 insertions, 2737 deletions
diff --git a/Android.mk b/Android.mk
index 6759a84..ecff19e 100644
--- a/Android.mk
+++ b/Android.mk
@@ -341,6 +341,11 @@ WEBKIT_LDLIBS := $(LOCAL_LDLIBS)
WEBKIT_SHARED_LIBRARIES := $(LOCAL_SHARED_LIBRARIES)
WEBKIT_STATIC_LIBRARIES := $(LOCAL_STATIC_LIBRARIES)
+ifneq ($(strip $(WITH_ADDRESS_SANITIZER)),)
+ LOCAL_MODULE_PATH := $(TARGET_OUT_STATIC_LIBRARIES)/asan
+ LOCAL_ADDRESS_SANITIZER := true
+endif
+
# Build the library all at once
include $(BUILD_STATIC_LIBRARY)
@@ -382,6 +387,12 @@ endif
# We make all of our object files depend on those files so that they are built
# before we try to compile the file.
LOCAL_ADDITIONAL_DEPENDENCIES := $(filter %.h, $(WEBKIT_GENERATED_SOURCES))
+
+ifneq ($(strip $(WITH_ADDRESS_SANITIZER)),)
+ LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/asan
+ LOCAL_ADDRESS_SANITIZER := true
+endif
+
include $(BUILD_SHARED_LIBRARY)
# Build the wds client
diff --git a/Source/JavaScriptCore/wtf/Platform.h b/Source/JavaScriptCore/wtf/Platform.h
index a1db9d6..41850ee 100644
--- a/Source/JavaScriptCore/wtf/Platform.h
+++ b/Source/JavaScriptCore/wtf/Platform.h
@@ -726,6 +726,7 @@
#define ENABLE_OFFLINE_WEB_APPLICATIONS 1
#define ENABLE_TOUCH_EVENTS 1
#define ENABLE_GEOLOCATION 1
+#define ENABLE_CLIENT_BASED_GEOLOCATION 1
#define ENABLE_INSPECTOR 0
#define ENABLE_EVENT_SOURCE 0
#define ENABLE_DEVICE_ORIENTATION 1
@@ -779,8 +780,6 @@
#define ANDROID_ANIMATED_GIF
// apple-touch-icon support in <link> tags
#define ANDROID_APPLE_TOUCH_ICON
-// track changes to the style that may change what is drawn
-#define ANDROID_STYLE_VERSION
// This is present in JavaScriptCore/config.h, which Android does not use.
#define WTF_CHANGES 1
diff --git a/Source/WebCore/Android.mk b/Source/WebCore/Android.mk
index 742fade..10eb822 100644
--- a/Source/WebCore/Android.mk
+++ b/Source/WebCore/Android.mk
@@ -496,6 +496,7 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \
page/FrameTree.cpp \
page/FrameView.cpp \
page/Geolocation.cpp \
+ page/GeolocationController.cpp \
page/GeolocationPositionCache.cpp \
page/GroupSettings.cpp \
page/History.cpp \
@@ -545,7 +546,6 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \
platform/FileChooser.cpp \
platform/FileStream.cpp \
platform/FileSystem.cpp \
- platform/GeolocationService.cpp \
platform/KURL.cpp \
platform/KURLGoogle.cpp \
platform/KillRingNone.cpp \
@@ -576,8 +576,6 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \
platform/android/EventLoopAndroid.cpp \
platform/android/FileChooserAndroid.cpp \
platform/android/FileSystemAndroid.cpp \
- platform/android/GeolocationServiceAndroid.cpp \
- platform/android/GeolocationServiceBridge.cpp \
platform/android/KeyEventAndroid.cpp \
platform/android/LanguageAndroid.cpp \
platform/android/LocalizedStringsAndroid.cpp \
@@ -644,10 +642,12 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \
platform/graphics/android/SharedBufferStream.cpp \
\
platform/graphics/android/context/GraphicsContextAndroid.cpp \
- platform/graphics/android/context/GraphicsOperationCollection.cpp \
+ platform/graphics/android/context/GraphicsOperation.cpp \
platform/graphics/android/context/PlatformGraphicsContext.cpp \
platform/graphics/android/context/PlatformGraphicsContextRecording.cpp \
platform/graphics/android/context/PlatformGraphicsContextSkia.cpp \
+ platform/graphics/android/context/RecordingContextCanvasProxy.cpp \
+ platform/graphics/android/context/RTree.cpp \
\
platform/graphics/android/fonts/FontAndroid.cpp \
platform/graphics/android/fonts/FontCacheAndroid.cpp \
@@ -699,7 +699,8 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \
platform/graphics/android/rendering/TilesProfiler.cpp \
platform/graphics/android/rendering/TransferQueue.cpp \
\
- platform/graphics/android/utils/ClassTracker.cpp
+ platform/graphics/android/utils/ClassTracker.cpp \
+ platform/graphics/android/utils/LinearAllocator.cpp
ifeq ($(ENABLE_SVG), true)
LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \
@@ -757,7 +758,6 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \
\
platform/mock/DeviceOrientationClientMock.cpp \
platform/mock/GeolocationClientMock.cpp \
- platform/mock/GeolocationServiceMock.cpp \
platform/mock/SpeechInputClientMock.cpp \
\
platform/network/AuthenticationChallengeBase.cpp \
diff --git a/Source/WebCore/dom/Document.cpp b/Source/WebCore/dom/Document.cpp
index b6a1393..063b8a2 100644
--- a/Source/WebCore/dom/Document.cpp
+++ b/Source/WebCore/dom/Document.cpp
@@ -387,9 +387,6 @@ Document::Document(Frame* frame, const KURL& url, bool isXHTML, bool isHTML)
, m_compatibilityMode(NoQuirksMode)
, m_compatibilityModeLocked(false)
, m_domTreeVersion(++s_globalTreeVersion)
-#ifdef ANDROID_STYLE_VERSION
- , m_styleVersion(0)
-#endif
, m_styleSheets(StyleSheetList::create(this))
, m_readyState(Complete)
, m_styleRecalcTimer(this, &Document::styleRecalcTimerFired)
@@ -4880,11 +4877,6 @@ void Document::webkitCancelFullScreen()
return;
page()->chrome()->client()->exitFullScreenForElement(m_fullScreenElement.get());
-#if PLATFORM(ANDROID)
- // The next time we try to enter full screen, we need this change to know
- // we are not in full screen any more.
- m_fullScreenElement = 0;
-#endif
}
void Document::webkitWillEnterFullScreenForElement(Element* element)
diff --git a/Source/WebCore/dom/Document.h b/Source/WebCore/dom/Document.h
index ce82b2e..c4ccb9c 100644
--- a/Source/WebCore/dom/Document.h
+++ b/Source/WebCore/dom/Document.h
@@ -905,11 +905,6 @@ public:
void incDOMTreeVersion() { m_domTreeVersion = ++s_globalTreeVersion; }
uint64_t domTreeVersion() const { return m_domTreeVersion; }
-#ifdef ANDROID_STYLE_VERSION
- void incStyleVersion() { ++m_styleVersion; }
- unsigned styleVersion() const { return m_styleVersion; }
-#endif
-
void setDocType(PassRefPtr<DocumentType>);
#if ENABLE(XPATH)
@@ -1223,9 +1218,6 @@ private:
uint64_t m_domTreeVersion;
static uint64_t s_globalTreeVersion;
-#ifdef ANDROID_STYLE_VERSION
- unsigned m_styleVersion;
-#endif
HashSet<NodeIterator*> m_nodeIterators;
HashSet<Range*> m_ranges;
diff --git a/Source/WebCore/dom/Element.cpp b/Source/WebCore/dom/Element.cpp
index 64d3eed..5fb6cdc 100644
--- a/Source/WebCore/dom/Element.cpp
+++ b/Source/WebCore/dom/Element.cpp
@@ -1069,21 +1069,6 @@ bool Element::pseudoStyleCacheIsInvalid(const RenderStyle* currentStyle, RenderS
return false;
}
-#ifdef ANDROID_STYLE_VERSION
-static bool displayDiff(const RenderStyle* s1, const RenderStyle* s2)
-{
- if (!s1 && !s2)
- return false;
- else if ((!s1 && s2) || (s1 && !s2))
- return true;
-
- return s1->display() != s2->display()
- || s1->left() != s2->left() || s1->top() != s2->top()
- || s1->right() != s2->right() || s1->bottom() != s2->bottom()
- || s1->width() != s2->width() || s1->height() != s2->height();
-}
-#endif
-
void Element::recalcStyle(StyleChange change)
{
// Ref currentStyle in case it would otherwise be deleted when setRenderStyle() is called.
@@ -1092,11 +1077,6 @@ void Element::recalcStyle(StyleChange change)
bool hasDirectAdjacentRules = currentStyle && currentStyle->childrenAffectedByDirectAdjacentRules();
if ((change > NoChange || needsStyleRecalc())) {
-#ifdef ANDROID_STYLE_VERSION
- RefPtr<RenderStyle> newStyle = document()->styleForElementIgnoringPendingStylesheets(this);
- if (displayDiff(currentStyle.get(), newStyle.get()))
- document()->incStyleVersion();
-#endif
if (hasRareData())
rareData()->resetComputedStyle();
}
diff --git a/Source/WebCore/editing/TextIterator.cpp b/Source/WebCore/editing/TextIterator.cpp
index 3aa68af..871d1f9 100644
--- a/Source/WebCore/editing/TextIterator.cpp
+++ b/Source/WebCore/editing/TextIterator.cpp
@@ -298,6 +298,7 @@ TextIterator::TextIterator(const Range* r, TextIteratorBehavior behavior)
#if OS(ANDROID)
, m_stopsOnFormControls(behavior & TextIteratorStopsOnFormControls)
, m_shouldStop(false)
+ , m_needsAnotherNewline(false)
#endif
{
if (!r)
diff --git a/Source/WebCore/html/HTMLInputElement.cpp b/Source/WebCore/html/HTMLInputElement.cpp
index 36cdf51..27b29a8 100644
--- a/Source/WebCore/html/HTMLInputElement.cpp
+++ b/Source/WebCore/html/HTMLInputElement.cpp
@@ -444,10 +444,6 @@ void HTMLInputElement::setType(const String& type)
void HTMLInputElement::updateType()
{
OwnPtr<InputType> newType = InputType::create(this, fastGetAttribute(typeAttr));
-#ifdef ANDROID_ACCEPT_CHANGES_TO_FOCUSED_TEXTFIELDS
- if (newType->isPasswordField() && document()->focusedNode() == this)
- PlatformBridge::updateTextfield(document()->view(), this, true, String());
-#endif
bool hadType = m_hasType;
m_hasType = true;
if (m_inputType->formControlType() == newType->formControlType())
@@ -912,7 +908,7 @@ void HTMLInputElement::setValue(const String& value, bool sendChangeEvent)
unsigned max = m_data.value().length();
#ifdef ANDROID_ACCEPT_CHANGES_TO_FOCUSED_TEXTFIELDS
// Make sure our UI side textfield changes to match the RenderTextControl
- PlatformBridge::updateTextfield(document()->view(), this, false, value);
+ PlatformBridge::updateTextfield(document()->view(), this, value);
#endif
if (document()->focusedNode() == this)
InputElement::updateSelectionRange(this, this, max, max);
@@ -1573,7 +1569,11 @@ bool HTMLInputElement::hasSpinButton() const
bool HTMLInputElement::supportsPlaceholder() const
{
+#if PLATFORM(ANDROID)
+ return isTextType() || isNumberField();
+#else
return isTextType();
+#endif
}
CheckedRadioButtons& HTMLInputElement::checkedRadioButtons() const
diff --git a/Source/WebCore/html/HTMLMediaElement.cpp b/Source/WebCore/html/HTMLMediaElement.cpp
index 328b6db..f3cc170 100644
--- a/Source/WebCore/html/HTMLMediaElement.cpp
+++ b/Source/WebCore/html/HTMLMediaElement.cpp
@@ -185,9 +185,9 @@ HTMLMediaElement::HTMLMediaElement(const QualifiedName& tagName, Document* docum
document->registerForDocumentActivationCallbacks(this);
document->registerForMediaVolumeCallbacks(this);
document->registerForPrivateBrowsingStateChangedCallbacks(this);
-#if PLATFORM(ANDROID) && ENABLE(TOUCH_EVENTS)
- m_restrictions |= RequireUserGestureForRateChangeRestriction;
-#endif
+
+ if (document->settings() && document->settings()->mediaPlaybackRequiresUserGesture())
+ m_restrictions |= RequireUserGestureForRateChangeRestriction;
}
HTMLMediaElement::~HTMLMediaElement()
@@ -1036,7 +1036,10 @@ void HTMLMediaElement::setReadyState(MediaPlayer::ReadyState state)
if (isPotentiallyPlaying && oldState <= HAVE_CURRENT_DATA)
scheduleEvent(eventNames().playingEvent);
-
+#if PLATFORM(ANDROID)
+ // autoplay should not be honored if we require user gesture.
+ if (!(m_restrictions & RequireUserGestureForRateChangeRestriction))
+#endif
if (m_autoplaying && m_paused && autoplay()) {
m_paused = false;
invalidateCachedTime();
@@ -2272,8 +2275,11 @@ void HTMLMediaElement::stopPeriodicTimers()
void HTMLMediaElement::userCancelledLoad()
{
LOG(Media, "HTMLMediaElement::userCancelledLoad");
-
+#if PLATFORM(ANDROID)
+ if (m_networkState == NETWORK_EMPTY)
+#else
if (m_networkState == NETWORK_EMPTY || m_completelyLoaded)
+#endif
return;
// If the media data fetching process is aborted by the user:
diff --git a/Source/WebCore/html/HTMLMetaElement.cpp b/Source/WebCore/html/HTMLMetaElement.cpp
index cb7f4c0..4f65065 100644
--- a/Source/WebCore/html/HTMLMetaElement.cpp
+++ b/Source/WebCore/html/HTMLMetaElement.cpp
@@ -32,10 +32,6 @@
#include "Settings.h"
#endif
-#if ENABLE(ANDROID_INSTALLABLE_WEB_APPS)
-#include "ChromeClient.h"
-#endif
-
namespace WebCore {
using namespace HTMLNames;
@@ -89,16 +85,6 @@ void HTMLMetaElement::process()
}
#endif
-#if ENABLE(ANDROID_INSTALLABLE_WEB_APPS)
- // If this web site is informing us it is possible for it to be installed, inform the chrome
- // client so it can offer this to the user.
- if (equalIgnoringCase(name(), "fullscreen-web-app-capable")
- && equalIgnoringCase(m_content, "yes")) {
- if (Page* page = document()->page())
- page->chrome()->client()->webAppCanBeInstalled();
- }
-#endif
-
// Get the document to process the tag, but only if we're actually part of DOM tree (changing a meta tag while
// it's not in the tree shouldn't have any effect on the document)
if (!m_equiv.isNull())
diff --git a/Source/WebCore/html/HTMLTextAreaElement.cpp b/Source/WebCore/html/HTMLTextAreaElement.cpp
index 5b12a14..50471d1 100644
--- a/Source/WebCore/html/HTMLTextAreaElement.cpp
+++ b/Source/WebCore/html/HTMLTextAreaElement.cpp
@@ -329,7 +329,7 @@ void HTMLTextAreaElement::setValueCommon(const String& value)
if (document()->focusedNode() == this) {
#ifdef ANDROID_ACCEPT_CHANGES_TO_FOCUSED_TEXTFIELDS
// Make sure our UI side textfield changes to match the RenderTextControl
- PlatformBridge::updateTextfield(document()->view(), this, false, value);
+ PlatformBridge::updateTextfield(document()->view(), this, value);
#endif
unsigned endOfString = m_value.length();
setSelectionRange(endOfString, endOfString);
diff --git a/Source/WebCore/loader/EmptyClients.h b/Source/WebCore/loader/EmptyClients.h
index 45df6ec..058db37 100644
--- a/Source/WebCore/loader/EmptyClients.h
+++ b/Source/WebCore/loader/EmptyClients.h
@@ -97,10 +97,6 @@ public:
virtual float scaleFactor() { return 1.f; }
-#if ENABLE(ANDROID_INSTALLABLE_WEB_APPS)
- virtual void webAppCanBeInstalled() { }
-#endif
-
virtual void focus() { }
virtual void unfocus() { }
diff --git a/Source/WebCore/page/ChromeClient.h b/Source/WebCore/page/ChromeClient.h
index 91511ac..0ec366b 100644
--- a/Source/WebCore/page/ChromeClient.h
+++ b/Source/WebCore/page/ChromeClient.h
@@ -319,10 +319,6 @@ namespace WebCore {
};
virtual void willRunModalDialogDuringPageDismissal(const DialogType&) const { }
-#if ENABLE(ANDROID_INSTALLABLE_WEB_APPS)
- virtual void webAppCanBeInstalled() = 0;
-#endif
-
protected:
virtual ~ChromeClient() { }
};
diff --git a/Source/WebCore/page/Geolocation.cpp b/Source/WebCore/page/Geolocation.cpp
index f0dd76a..352e06b 100644
--- a/Source/WebCore/page/Geolocation.cpp
+++ b/Source/WebCore/page/Geolocation.cpp
@@ -708,20 +708,8 @@ bool Geolocation::startUpdating(GeoNotifier* notifier)
page->geolocationController()->addObserver(this, notifier->m_options->enableHighAccuracy());
return true;
#else
-#if PLATFORM(ANDROID)
- // TODO: Upstream to webkit.org. See https://bugs.webkit.org/show_bug.cgi?id=34082
- // Note that the correct fix is to use a 'paused' flag in WebCore, rather
- // than calling into PlatformBridge.
- if (!m_frame)
- return false;
- FrameView* view = m_frame->view();
- if (!view)
- return false;
- return m_service->startUpdating(notifier->m_options.get(), PlatformBridge::isWebViewPaused(view));
-#else
return m_service->startUpdating(notifier->m_options.get());
#endif
-#endif
}
void Geolocation::stopUpdating()
diff --git a/Source/WebCore/page/GeolocationController.cpp b/Source/WebCore/page/GeolocationController.cpp
index b9533ca..56c11a5 100644
--- a/Source/WebCore/page/GeolocationController.cpp
+++ b/Source/WebCore/page/GeolocationController.cpp
@@ -59,7 +59,10 @@ void GeolocationController::addObserver(Geolocation* observer, bool enableHighAc
if (m_client) {
if (enableHighAccuracy)
m_client->setEnableHighAccuracy(true);
+// See https://bugs.webkit.org/show_bug.cgi?id=87030
+#if !PLATFORM(ANDROID)
if (wasEmpty)
+#endif
m_client->startUpdating();
}
}
diff --git a/Source/WebCore/page/Settings.cpp b/Source/WebCore/page/Settings.cpp
index f668f3e..79e38d1 100644
--- a/Source/WebCore/page/Settings.cpp
+++ b/Source/WebCore/page/Settings.cpp
@@ -201,6 +201,8 @@ Settings::Settings(Page* page)
#else
, m_passwordEchoEnabled(false)
#endif
+ , m_mediaPlaybackRequiresUserGesture(false)
+ , m_mediaPlaybackAllowsInline(true)
{
// A Frame may not have been created yet, so we initialize the AtomicString
// hash before trying to use it.
diff --git a/Source/WebCore/page/Settings.h b/Source/WebCore/page/Settings.h
index 2cf7715..84828ab 100644
--- a/Source/WebCore/page/Settings.h
+++ b/Source/WebCore/page/Settings.h
@@ -479,6 +479,12 @@ namespace WebCore {
bool blockNetworkImage() const { return m_blockNetworkImage; }
#endif
+ void setMediaPlaybackRequiresUserGesture(bool flag) { m_mediaPlaybackRequiresUserGesture = flag; };
+ bool mediaPlaybackRequiresUserGesture() const { return m_mediaPlaybackRequiresUserGesture; }
+
+ void setMediaPlaybackAllowsInline(bool flag) { m_mediaPlaybackAllowsInline = flag; };
+ bool mediaPlaybackAllowsInline() const { return m_mediaPlaybackAllowsInline; }
+
private:
Page* m_page;
@@ -633,6 +639,8 @@ namespace WebCore {
#ifdef ANDROID_PLUGINS
bool m_pluginsOnDemand : 1;
#endif
+ bool m_mediaPlaybackRequiresUserGesture : 1;
+ bool m_mediaPlaybackAllowsInline : 1;
bool m_passwordEchoEnabled : 1;
#if USE(SAFARI_THEME)
diff --git a/Source/WebCore/platform/GeolocationService.h b/Source/WebCore/platform/GeolocationService.h
index 27be6c3..1045bb3 100644
--- a/Source/WebCore/platform/GeolocationService.h
+++ b/Source/WebCore/platform/GeolocationService.h
@@ -48,12 +48,7 @@ public:
static GeolocationService* create(GeolocationServiceClient*);
virtual ~GeolocationService() { }
-#if PLATFORM(ANDROID)
- // TODO: Upstream to webkit.org. See https://bugs.webkit.org/show_bug.cgi?id=34082
- virtual bool startUpdating(PositionOptions*, bool suspend) { return false; }
-#else
virtual bool startUpdating(PositionOptions*) { return false; }
-#endif
virtual void stopUpdating() { }
virtual void suspend() { }
diff --git a/Source/WebCore/platform/android/GeolocationServiceAndroid.cpp b/Source/WebCore/platform/android/GeolocationServiceAndroid.cpp
deleted file mode 100644
index 0f07722..0000000
--- a/Source/WebCore/platform/android/GeolocationServiceAndroid.cpp
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * Copyright 2009, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "GeolocationServiceAndroid.h"
-
-#include "Geolocation.h"
-#include "GeolocationServiceBridge.h"
-#include "Geoposition.h"
-#include "PositionError.h"
-#include "PositionOptions.h"
-
-#if PLATFORM(ANDROID)
-// Required for sim-eng build
-#include <math.h>
-#endif
-#include <wtf/CurrentTime.h>
-
-using JSC::Bindings::getJNIEnv;
-using namespace std;
-
-namespace WebCore {
-
-// GeolocationServiceAndroid is the Android implmentation of Geolocation
-// service. Each object of this class owns an object of type
-// GeolocationServiceBridge, which in turn owns a Java GeolocationService
-// object. Therefore, there is a 1:1 mapping between Geolocation,
-// GeolocationServiceAndroid, GeolocationServiceBridge and Java
-// GeolocationService objects. In the case where multiple Geolocation objects
-// exist simultaneously, the corresponsing Java GeolocationService objects all
-// register with the platform location service. It is the platform service that
-// handles making sure that updates are passed to all Geolocation objects.
-GeolocationService* GeolocationServiceAndroid::create(GeolocationServiceClient* client)
-{
- return new GeolocationServiceAndroid(client);
-}
-
-GeolocationService::FactoryFunction* GeolocationService::s_factoryFunction = &GeolocationServiceAndroid::create;
-
-GeolocationServiceAndroid::GeolocationServiceAndroid(GeolocationServiceClient* client)
- : GeolocationService(client)
- , m_timer(this, &GeolocationServiceAndroid::timerFired)
- , m_javaBridge(0)
-{
-}
-
-// ANDROID
-// TODO: Upstream to webkit.org. See https://bugs.webkit.org/show_bug.cgi?id=34082
-bool GeolocationServiceAndroid::startUpdating(PositionOptions* options, bool suspend)
-{
- // ANDROID
- // This is an ugly hack. A correct fix would require a change to WebCore,
- // but this isn't worth the effort as we're in the process of switching to a
- // client-based implementation. See https://bugs.webkit.org/show_bug.cgi?id=40373
- Frame* frame = reinterpret_cast<Geolocation*>(geolocationServiceClient())->frame();
- if (!frame)
- return false;
-
- // This method is called every time a new watch or one-shot position request
- // is started. If we already have a position or an error, call back
- // immediately.
- if (m_lastPosition || m_lastError) {
- ASSERT(m_javaBridge);
- m_timer.startOneShot(0);
- }
-
- // Lazilly create the Java object.
- bool haveJavaBridge = m_javaBridge;
- if (!haveJavaBridge)
- m_javaBridge.set(new GeolocationServiceBridge(this, frame));
- ASSERT(m_javaBridge);
-
- // On Android, high power == GPS. Set whether to use GPS before we start the
- // implementation.
- ASSERT(options);
- if (options->enableHighAccuracy())
- m_javaBridge->setEnableGps(true);
-
- // We need only start the service when it's first created.
- if (!haveJavaBridge) {
- // If the browser is paused, don't start the service. It will be started
- // when we get the call to resume.
- // ANDROID
- // TODO: Upstream to webkit.org. See https://bugs.webkit.org/show_bug.cgi?id=34082
- if (!suspend)
- return m_javaBridge->start();
- }
-
- return true;
-}
-
-void GeolocationServiceAndroid::stopUpdating()
-{
- // Called when the Geolocation object has no watches or one shots in
- // progress. This may be called repeatedly.
- m_javaBridge.clear();
- // Reset last position and error to make sure that we always try to get a
- // new position from the system service when a request is first made.
- m_lastPosition = 0;
- m_lastError = 0;
- // remove the pending timer
- if (m_timer.isActive())
- m_timer.stop();
-}
-
-void GeolocationServiceAndroid::suspend()
-{
- if (m_javaBridge)
- m_javaBridge->stop();
-}
-
-void GeolocationServiceAndroid::resume()
-{
- if (m_javaBridge)
- m_javaBridge->start();
-}
-
-// Note that there is no guarantee that subsequent calls to this method offer a
-// more accurate or updated position.
-void GeolocationServiceAndroid::newPositionAvailable(PassRefPtr<Geoposition> position)
-{
- ASSERT(position);
- if (!m_lastPosition
- || isPositionMovement(m_lastPosition.get(), position.get())
- || isPositionMoreAccurate(m_lastPosition.get(), position.get())
- || isPositionMoreTimely(m_lastPosition.get(), position.get())) {
- m_lastPosition = position;
- // Remove the last error.
- m_lastError = 0;
- positionChanged();
- }
-}
-
-void GeolocationServiceAndroid::newErrorAvailable(PassRefPtr<PositionError> error)
-{
- ASSERT(error);
- // We leave the last position
- m_lastError = error;
- errorOccurred();
-}
-
-void GeolocationServiceAndroid::timerFired(Timer<GeolocationServiceAndroid>* timer)
-{
- ASSERT(&m_timer == timer);
- ASSERT(m_lastPosition || m_lastError);
- if (m_lastPosition)
- positionChanged();
- else if (m_lastError)
- errorOccurred();
-}
-
-bool GeolocationServiceAndroid::isPositionMovement(Geoposition* position1, Geoposition* position2)
-{
- ASSERT(position1 && position2);
- // For the small distances in which we are likely concerned, it's reasonable
- // to approximate the distance between the two positions as the sum of the
- // differences in latitude and longitude.
- double delta = fabs(position1->coords()->latitude() - position2->coords()->latitude())
- + fabs(position1->coords()->longitude() - position2->coords()->longitude());
- // Approximate conversion from degrees of arc to metres.
- delta *= 60 * 1852;
- // The threshold is when the distance between the two positions exceeds the
- // worse (larger) of the two accuracies.
- int maxAccuracy = max(position1->coords()->accuracy(), position2->coords()->accuracy());
- return delta > maxAccuracy;
-}
-
-bool GeolocationServiceAndroid::isPositionMoreAccurate(Geoposition* position1, Geoposition* position2)
-{
- ASSERT(position1 && position2);
- return position2->coords()->accuracy() < position1->coords()->accuracy();
-}
-
-bool GeolocationServiceAndroid::isPositionMoreTimely(Geoposition* position1, Geoposition* position2)
-{
- ASSERT(position1 && position2);
- DOMTimeStamp currentTime = convertSecondsToDOMTimeStamp(WTF::currentTime());
- DOMTimeStamp maximumAge = convertSecondsToDOMTimeStamp(10 * 60); // 10 minutes
- return currentTime - position1->timestamp() > maximumAge;
-}
-
-} // namespace WebCore
diff --git a/Source/WebCore/platform/android/GeolocationServiceAndroid.h b/Source/WebCore/platform/android/GeolocationServiceAndroid.h
deleted file mode 100644
index 72532f6..0000000
--- a/Source/WebCore/platform/android/GeolocationServiceAndroid.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright 2009, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef GeolocationServiceAndroid_h
-#define GeolocationServiceAndroid_h
-
-#include "GeolocationService.h"
-#include "Timer.h"
-#include <wtf/OwnPtr.h>
-#include <wtf/PassRefPtr.h>
-#include <wtf/RefPtr.h>
-
-namespace WebCore {
-
-// The GeolocationServiceBridge is the bridge to the Java implementation of
-// the Geolocation service. It is an implementation detail of
-// GeolocationServiceAndroid.
-class GeolocationServiceBridge;
-
-class GeolocationServiceAndroid : public GeolocationService {
-public:
- static GeolocationService* create(GeolocationServiceClient*);
-
- virtual ~GeolocationServiceAndroid() { };
-
- // ANDROID
- // TODO: Upstream to webkit.org. See https://bugs.webkit.org/show_bug.cgi?id=34082
- virtual bool startUpdating(PositionOptions*, bool suspend);
- virtual void stopUpdating();
-
- virtual Geoposition* lastPosition() const { return m_lastPosition.get(); }
- virtual PositionError* lastError() const { return m_lastError.get(); }
-
- virtual void suspend();
- virtual void resume();
-
- // Android-specific
- void newPositionAvailable(PassRefPtr<Geoposition>);
- void newErrorAvailable(PassRefPtr<PositionError>);
- void timerFired(Timer<GeolocationServiceAndroid>* timer);
-
-private:
- GeolocationServiceAndroid(GeolocationServiceClient*);
-
- static bool isPositionMovement(Geoposition* position1, Geoposition* position2);
- static bool isPositionMoreAccurate(Geoposition* position1, Geoposition* position2);
- static bool isPositionMoreTimely(Geoposition* position1, Geoposition* position2);
-
- Timer<GeolocationServiceAndroid> m_timer;
- RefPtr<Geoposition> m_lastPosition;
- RefPtr<PositionError> m_lastError;
- OwnPtr<GeolocationServiceBridge> m_javaBridge;
-};
-
-} // namespace WebCore
-
-#endif // GeolocationServiceAndroid_h
diff --git a/Source/WebCore/platform/android/PlatformBridge.h b/Source/WebCore/platform/android/PlatformBridge.h
index a4c1048..5af5d2d 100644
--- a/Source/WebCore/platform/android/PlatformBridge.h
+++ b/Source/WebCore/platform/android/PlatformBridge.h
@@ -124,10 +124,6 @@ public:
};
static String* globalLocalizedName(rawResId resId);
- // Whether the WebView is paused.
- // ANDROID
- // TODO: Upstream to webkit.org. See https://bugs.webkit.org/show_bug.cgi?id=34082
- static bool isWebViewPaused(const FrameView*);
static String resolveFilePathForContentUri(const String&);
static int screenDepth();
@@ -136,7 +132,7 @@ public:
// Update the viewport meta data.
static void updateViewport(FrameView*);
- static void updateTextfield(FrameView*, Node*, bool changeToPassword, const WTF::String& text);
+ static void updateTextfield(FrameView*, Node*, const WTF::String& text);
static void setScrollPosition(ScrollView*, int x, int y);
diff --git a/Source/WebCore/platform/android/RenderThemeAndroid.cpp b/Source/WebCore/platform/android/RenderThemeAndroid.cpp
index 86380e7..eaf4593 100644
--- a/Source/WebCore/platform/android/RenderThemeAndroid.cpp
+++ b/Source/WebCore/platform/android/RenderThemeAndroid.cpp
@@ -39,6 +39,7 @@
#endif
#include "RenderSkinAndroid.h"
#include "RenderSkinMediaButton.h"
+#include "RenderSlider.h"
#include "RoundedIntRect.h"
#include "SkCanvas.h"
#include "UserAgentStyleSheets.h"
@@ -85,12 +86,6 @@ const float scaleFactor[RenderSkinAndroid::ResolutionCount] = {
2.0f // extra high res
};
-
-static SkCanvas* getCanvasFromInfo(const PaintInfo& info)
-{
- return info.context->platformContext()->getCanvas();
-}
-
static android::WebFrame* getWebFrame(const Node* node)
{
if (!node)
@@ -341,9 +336,7 @@ bool RenderThemeAndroid::paintMediaFullscreenButton(RenderObject* o, const Paint
bool translucent = false;
if (o && toParentMediaElement(o) && toParentMediaElement(o)->hasTagName(HTMLNames::videoTag))
translucent = true;
- if (!getCanvasFromInfo(paintInfo))
- return true;
- RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect, RenderSkinMediaButton::FULLSCREEN, translucent);
+ paintInfo.context->platformContext()->drawMediaButton(rect, RenderSkinMediaButton::FULLSCREEN, translucent);
return false;
}
@@ -352,9 +345,7 @@ bool RenderThemeAndroid::paintMediaMuteButton(RenderObject* o, const PaintInfo&
bool translucent = false;
if (o && toParentMediaElement(o) && toParentMediaElement(o)->hasTagName(HTMLNames::videoTag))
translucent = true;
- if (!getCanvasFromInfo(paintInfo))
- return true;
- RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect, RenderSkinMediaButton::MUTE, translucent);
+ paintInfo.context->platformContext()->drawMediaButton(rect, RenderSkinMediaButton::MUTE, translucent);
return false;
}
@@ -364,12 +355,10 @@ bool RenderThemeAndroid::paintMediaPlayButton(RenderObject* o, const PaintInfo&
if (o && toParentMediaElement(o) && toParentMediaElement(o)->hasTagName(HTMLNames::videoTag))
translucent = true;
if (MediaControlPlayButtonElement* btn = static_cast<MediaControlPlayButtonElement*>(o->node())) {
- if (!getCanvasFromInfo(paintInfo))
- return true;
if (btn->displayType() == MediaPlayButton)
- RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect, RenderSkinMediaButton::PLAY, translucent);
+ paintInfo.context->platformContext()->drawMediaButton(rect, RenderSkinMediaButton::PLAY, translucent);
else
- RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect, RenderSkinMediaButton::PAUSE, translucent);
+ paintInfo.context->platformContext()->drawMediaButton(rect, RenderSkinMediaButton::PAUSE, translucent);
return false;
}
return true;
@@ -380,9 +369,7 @@ bool RenderThemeAndroid::paintMediaSeekBackButton(RenderObject* o, const PaintIn
bool translucent = false;
if (o && toParentMediaElement(o) && toParentMediaElement(o)->hasTagName(HTMLNames::videoTag))
translucent = true;
- if (!getCanvasFromInfo(paintInfo))
- return true;
- RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect, RenderSkinMediaButton::REWIND, translucent);
+ paintInfo.context->platformContext()->drawMediaButton(rect, RenderSkinMediaButton::REWIND, translucent);
return false;
}
@@ -391,9 +378,7 @@ bool RenderThemeAndroid::paintMediaSeekForwardButton(RenderObject* o, const Pain
bool translucent = false;
if (o && toParentMediaElement(o) && toParentMediaElement(o)->hasTagName(HTMLNames::videoTag))
translucent = true;
- if (!getCanvasFromInfo(paintInfo))
- return true;
- RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect, RenderSkinMediaButton::FORWARD, translucent);
+ paintInfo.context->platformContext()->drawMediaButton(rect, RenderSkinMediaButton::FORWARD, translucent);
return false;
}
@@ -402,11 +387,9 @@ bool RenderThemeAndroid::paintMediaControlsBackground(RenderObject* o, const Pai
bool translucent = false;
if (o && toParentMediaElement(o) && toParentMediaElement(o)->hasTagName(HTMLNames::videoTag))
translucent = true;
- if (!getCanvasFromInfo(paintInfo))
- return true;
- RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect,
+ paintInfo.context->platformContext()->drawMediaButton(rect,
RenderSkinMediaButton::BACKGROUND_SLIDER,
- translucent, 0, false);
+ translucent, false);
return false;
}
@@ -415,10 +398,11 @@ bool RenderThemeAndroid::paintMediaSliderTrack(RenderObject* o, const PaintInfo&
bool translucent = false;
if (o && toParentMediaElement(o) && toParentMediaElement(o)->hasTagName(HTMLNames::videoTag))
translucent = true;
- if (!getCanvasFromInfo(paintInfo))
- return true;
- RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect,
- RenderSkinMediaButton::SLIDER_TRACK, translucent, o);
+ IntRect thumb;
+ if (o && o->isSlider())
+ thumb = toRenderSlider(o)->thumbRect();
+ paintInfo.context->platformContext()->drawMediaButton(rect,
+ RenderSkinMediaButton::SLIDER_TRACK, translucent, true, thumb);
return false;
}
@@ -427,11 +411,9 @@ bool RenderThemeAndroid::paintMediaSliderThumb(RenderObject* o, const PaintInfo&
bool translucent = false;
if (o && toParentMediaElement(o) && toParentMediaElement(o)->hasTagName(HTMLNames::videoTag))
translucent = true;
- if (!getCanvasFromInfo(paintInfo))
- return true;
- RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect,
+ paintInfo.context->platformContext()->drawMediaButton(rect,
RenderSkinMediaButton::SLIDER_THUMB,
- translucent, 0, false);
+ translucent, false);
return false;
}
@@ -647,25 +629,19 @@ bool RenderThemeAndroid::paintMenuListButton(RenderObject* obj, const PaintInfo&
bool RenderThemeAndroid::paintSliderTrack(RenderObject* o, const PaintInfo& i, const IntRect& r)
{
- SkCanvas* canvas = getCanvasFromInfo(i);
- if (!canvas)
- return true;
static const bool translucent = true;
- RenderSkinMediaButton::Draw(canvas, r,
+ i.context->platformContext()->drawMediaButton(r,
RenderSkinMediaButton::SLIDER_TRACK,
- translucent, o, false);
+ translucent, false);
return false;
}
bool RenderThemeAndroid::paintSliderThumb(RenderObject* o, const PaintInfo& i, const IntRect& r)
{
- SkCanvas* canvas = getCanvasFromInfo(i);
- if (!canvas)
- return true;
static const bool translucent = true;
- RenderSkinMediaButton::Draw(canvas, r,
+ i.context->platformContext()->drawMediaButton(r,
RenderSkinMediaButton::SLIDER_THUMB,
- translucent, 0, false);
+ translucent, false);
return false;
}
diff --git a/Source/WebCore/platform/graphics/MediaPlayer.cpp b/Source/WebCore/platform/graphics/MediaPlayer.cpp
index a7e4b90..4e00382 100644
--- a/Source/WebCore/platform/graphics/MediaPlayer.cpp
+++ b/Source/WebCore/platform/graphics/MediaPlayer.cpp
@@ -689,6 +689,14 @@ void MediaPlayer::exitFullscreen()
}
#endif
+#if PLATFORM(ANDROID)
+void MediaPlayer::enterFullscreenMode()
+{
+ // Tell the player to enter full screen mode.
+ m_private->enterFullscreenMode();
+}
+#endif
+
#if USE(ACCELERATED_COMPOSITING)
void MediaPlayer::acceleratedRenderingStateChanged()
{
diff --git a/Source/WebCore/platform/graphics/MediaPlayer.h b/Source/WebCore/platform/graphics/MediaPlayer.h
index 41cb6d2..884f915 100644
--- a/Source/WebCore/platform/graphics/MediaPlayer.h
+++ b/Source/WebCore/platform/graphics/MediaPlayer.h
@@ -190,6 +190,7 @@ public:
enum MediaElementType { Video, Audio };
void setMediaElementType(MediaElementType type) { m_mediaElementType = type; }
MediaElementType mediaElementType() { return m_mediaElementType; }
+ void enterFullscreenMode();
#endif
void setFrameView(FrameView* frameView) { m_frameView = frameView; }
diff --git a/Source/WebCore/platform/graphics/MediaPlayerPrivate.h b/Source/WebCore/platform/graphics/MediaPlayerPrivate.h
index b4490bc..fa92e06 100644
--- a/Source/WebCore/platform/graphics/MediaPlayerPrivate.h
+++ b/Source/WebCore/platform/graphics/MediaPlayerPrivate.h
@@ -113,7 +113,9 @@ public:
virtual void enterFullscreen() { }
virtual void exitFullscreen() { }
#endif
-
+#if PLATFORM(ANDROID)
+ virtual void enterFullscreenMode() { }
+#endif
#if USE(ACCELERATED_COMPOSITING)
// whether accelerated rendering is supported by the media engine for the current media.
virtual bool supportsAcceleratedRendering() const { return false; }
diff --git a/Source/WebCore/platform/graphics/android/GLWebViewState.cpp b/Source/WebCore/platform/graphics/android/GLWebViewState.cpp
index 55c4eec..256a678 100644
--- a/Source/WebCore/platform/graphics/android/GLWebViewState.cpp
+++ b/Source/WebCore/platform/graphics/android/GLWebViewState.cpp
@@ -353,10 +353,8 @@ int GLWebViewState::drawGL(IntRect& invScreenRect, SkRect& visibleContentRect,
if (ImagesManager::instance()->prepareTextures(this))
returnFlags |= DrawGlInfo::kStatusDraw;
- if (scale < MIN_SCALE_WARNING || scale > MAX_SCALE_WARNING) {
+ if (scale < MIN_SCALE_WARNING || scale > MAX_SCALE_WARNING)
ALOGW("WARNING, scale seems corrupted after update: %e", scale);
- scale = 1.0f; // WORKAROUND for corrupted scale: use 1.0
- }
double currentTime = setupDrawing(invScreenRect, visibleContentRect, screenRect,
titleBarHeight, screenClip, scale);
diff --git a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp
index 779dba5..9cb81e6 100644
--- a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp
@@ -41,6 +41,7 @@
#include "Length.h"
#include "MediaLayer.h"
#include "PictureLayerContent.h"
+#include "PicturePileLayerContent.h"
#include "PlatformBridge.h"
#include "PlatformGraphicsContextSkia.h"
#include "RenderLayerBacking.h"
@@ -115,7 +116,6 @@ GraphicsLayerAndroid::GraphicsLayerAndroid(GraphicsLayerClient* client) :
static_cast<HTMLCanvasElement*>(renderLayer->renderer()->node()));
} else
m_contentLayer = new LayerAndroid(renderLayer);
- m_dirtyRegion.setEmpty();
gDebugGraphicsLayerAndroidInstances++;
}
@@ -694,7 +694,7 @@ bool GraphicsLayerAndroid::repaint()
PaintingPhase phase(this);
// Paint the background into a separate context.
phase.set(GraphicsLayerPaintBackground);
- if (!paintContext(m_contentLayer, layerBounds))
+ if (!paintContext(m_contentLayer, m_contentLayerContent))
return false;
// Construct the foreground layer and draw.
@@ -711,11 +711,17 @@ bool GraphicsLayerAndroid::repaint()
// Paint everything else into the main recording canvas.
phase.clear(GraphicsLayerPaintBackground);
+ // Invalidate the entire layer for now, as webkit will only send the
+ // setNeedsDisplayInRect() for the visible (clipped) scrollable area,
+ // offsetting the invals by the scroll position would not be enough.
+ // TODO: have webkit send us invals even for non visible area
+ m_foregroundLayerContent.invalidate(IntRect(0, 0, contentsRect.width(), contentsRect.height()));
+
// Paint at 0,0.
IntSize scroll = layer->scrolledContentOffset();
layer->scrollToOffset(0, 0);
// At this point, it doesn't matter if painting failed.
- (void) paintContext(m_foregroundLayer, contentsRect);
+ (void) paintContext(m_foregroundLayer, m_foregroundLayerContent);
layer->scrollToOffset(scroll.width(), scroll.height());
// Construct the clip layer for masking the contents.
@@ -740,13 +746,8 @@ bool GraphicsLayerAndroid::repaint()
// Set the scrollable bounds of the layer.
setScrollLimits(static_cast<ScrollableLayerAndroid*>(m_foregroundLayer), layer);
- // Invalidate the entire layer for now, as webkit will only send the
- // setNeedsDisplayInRect() for the visible (clipped) scrollable area,
- // offsetting the invals by the scroll position would not be enough.
- // TODO: have webkit send us invals even for non visible area
- SkRegion region;
- region.setRect(0, 0, contentsRect.width(), contentsRect.height());
- m_foregroundLayer->markAsDirty(region);
+ m_foregroundLayer->markAsDirty(m_foregroundLayerContent.dirtyRegion());
+ m_foregroundLayerContent.dirtyRegion().setEmpty();
} else if (m_contentLayer->isFixedBackground()) {
SkPicture* picture = new SkPicture();
SkCanvas* canvas = picture->beginRecording(layerBounds.width(),
@@ -783,13 +784,13 @@ bool GraphicsLayerAndroid::repaint()
GraphicsLayerAndroid* replicatedLayer = static_cast<GraphicsLayerAndroid*>(replicaLayer());
if (replicatedLayer->maskLayer()) {
GraphicsLayerAndroid* mask = static_cast<GraphicsLayerAndroid*>(replicatedLayer->maskLayer());
- mask->paintContext(mask->m_contentLayer, layerBounds, false);
+ mask->paintContext(mask->m_contentLayer, m_contentLayerContent);
}
}
// If there is no contents clip, we can draw everything into one
// picture.
- bool painting = paintContext(m_contentLayer, layerBounds);
+ bool painting = paintContext(m_contentLayer, m_contentLayerContent);
if (!painting)
return false;
// Check for a scrollable iframe and report the scrolling
@@ -810,8 +811,8 @@ bool GraphicsLayerAndroid::repaint()
m_contentLayer->getSize().width(),
m_contentLayer->getSize().height());
- m_contentLayer->markAsDirty(m_dirtyRegion);
- m_dirtyRegion.setEmpty();
+ m_contentLayer->markAsDirty(m_contentLayerContent.dirtyRegion());
+ m_contentLayerContent.dirtyRegion().setEmpty();
m_needsRepaint = false;
return true;
@@ -819,8 +820,8 @@ bool GraphicsLayerAndroid::repaint()
if (m_needsRepaint && m_image && m_newImage) {
// We need to tell the GL thread that we will need to repaint the
// texture. Only do so if we effectively have a new image!
- m_contentLayer->markAsDirty(m_dirtyRegion);
- m_dirtyRegion.setEmpty();
+ m_contentLayer->markAsDirty(m_contentLayerContent.dirtyRegion());
+ m_contentLayerContent.dirtyRegion().setEmpty();
m_newImage = false;
m_needsRepaint = false;
return true;
@@ -828,44 +829,29 @@ bool GraphicsLayerAndroid::repaint()
return false;
}
-SkPicture* GraphicsLayerAndroid::paintPicture(const IntRect& rect)
+void GraphicsLayerAndroid::paintContents(GraphicsContext* gc, IntRect& dirty)
{
- SkPicture* picture = new SkPicture();
- SkCanvas* canvas = picture->beginRecording(rect.width(), rect.height(), 0);
- if (!canvas) {
- picture->endRecording();
- SkSafeUnref(picture);
- return 0;
- }
-
- PlatformGraphicsContextSkia platformContext(canvas);
- GraphicsContext graphicsContext(&platformContext);
-
- paintGraphicsLayerContents(graphicsContext, rect);
-
- return picture;
+ paintGraphicsLayerContents(*gc, dirty);
}
bool GraphicsLayerAndroid::paintContext(LayerAndroid* layer,
- const IntRect& rect,
- bool checkOptimisations)
+ PicturePile& picture)
{
if (!layer)
return false;
- SkPicture* picture = paintPicture(rect);
- if (!picture)
- return false;
- picture->endRecording();
+ TRACE_METHOD();
+
+ picture.setSize(IntSize(layer->getWidth(), layer->getHeight()));
+
+ // TODO: add content checks (text, opacity, etc.)
+ picture.updatePicturesIfNeeded(this);
+
+ // store the newly painted content in the layer if it's not empty
+ PicturePileLayerContent* content = new PicturePileLayerContent(picture);
+ layer->setContent(content->isEmpty() ? 0 : content);
+ SkSafeUnref(content);
- PictureLayerContent* layerContent = new PictureLayerContent(picture);
- if (checkOptimisations)
- layerContent->checkForOptimisations();
- else
- layerContent->setCheckForOptimisations(false);
- layer->setContent(layerContent);
- SkSafeUnref(layerContent);
- SkSafeUnref(picture);
return true;
}
@@ -879,11 +865,9 @@ void GraphicsLayerAndroid::setNeedsDisplayInRect(const FloatRect& rect)
return;
}
- SkRegion region;
- region.setRect(rect.x(), rect.y(),
- rect.x() + rect.width(),
- rect.y() + rect.height());
- m_dirtyRegion.op(region, SkRegion::kUnion_Op);
+ m_contentLayerContent.invalidate(enclosingIntRect(rect));
+ if (m_foregroundLayer)
+ m_foregroundLayerContent.invalidate(enclosingIntRect(rect));
m_needsRepaint = true;
askForSync();
diff --git a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.h b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.h
index 460e00f..28d4b09 100644
--- a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.h
+++ b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.h
@@ -24,6 +24,7 @@
#include "GraphicsLayer.h"
#include "GraphicsLayerClient.h"
#include "LayerContent.h"
+#include "PicturePile.h"
#include "RefPtr.h"
#include "ScrollableLayerAndroid.h"
#include "SkBitmapRef.h"
@@ -40,12 +41,18 @@ class LayerAndroid;
class FixedBackgroundImageLayerAndroid;
class ScrollableLayerAndroid;
-class GraphicsLayerAndroid : public GraphicsLayer {
+class GraphicsLayerAndroid : public GraphicsLayer, PicturePainter {
public:
GraphicsLayerAndroid(GraphicsLayerClient*);
virtual ~GraphicsLayerAndroid();
+ // PicturePainter
+
+ virtual void paintContents(GraphicsContext* gc, IntRect& dirty);
+
+ /////
+
virtual void setName(const String&);
// for hosting this GraphicsLayer in a native layer hierarchy
@@ -147,10 +154,7 @@ private:
bool repaint();
void needsNotifyClient();
- SkPicture* paintPicture(const IntRect& rect);
- bool paintContext(LayerAndroid* layer,
- const IntRect& rect,
- bool checkOptimisations = true);
+ bool paintContext(LayerAndroid* layer, PicturePile& picture);
bool m_needsSyncChildren;
bool m_needsSyncMask;
@@ -161,12 +165,13 @@ private:
bool m_newImage;
Image* m_image;
- SkRegion m_dirtyRegion;
-
LayerAndroid* m_contentLayer;
FixedBackgroundImageLayerAndroid* m_fixedBackgroundLayer;
LayerAndroid* m_foregroundLayer;
LayerAndroid* m_foregroundClipLayer;
+
+ PicturePile m_contentLayerContent;
+ PicturePile m_foregroundLayerContent;
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/ImageAndroid.cpp b/Source/WebCore/platform/graphics/android/ImageAndroid.cpp
index 08f72e0..4958622 100644
--- a/Source/WebCore/platform/graphics/android/ImageAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/ImageAndroid.cpp
@@ -34,7 +34,6 @@
#include "PlatformString.h"
#include "SharedBuffer.h"
-#include "android_graphics.h"
#include "SkBitmapRef.h"
#include "SkCanvas.h"
#include "SkColorPriv.h"
diff --git a/Source/WebCore/platform/graphics/android/ImageBufferAndroid.cpp b/Source/WebCore/platform/graphics/android/ImageBufferAndroid.cpp
index e56f424..f36200d 100644
--- a/Source/WebCore/platform/graphics/android/ImageBufferAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/ImageBufferAndroid.cpp
@@ -33,6 +33,7 @@
#include "NotImplemented.h"
#include "PlatformBridge.h"
#include "PlatformGraphicsContext.h"
+#include "PlatformGraphicsContextSkia.h"
#include "SkBitmapRef.h"
#include "SkCanvas.h"
#include "SkColorPriv.h"
@@ -41,12 +42,21 @@
#include "SkImageEncoder.h"
#include "SkStream.h"
#include "SkUnPreMultiply.h"
-#include "android_graphics.h"
using namespace std;
namespace WebCore {
+SkCanvas* imageBufferCanvas(const ImageBuffer* buffer)
+{
+ // We know that our PlatformGraphicsContext is a PlatformGraphicsContextSkia
+ // because that is what we create in GraphicsContext::createOffscreenContext
+ if (!buffer || !buffer->context())
+ return 0;
+ PlatformGraphicsContext* pc = buffer->context()->platformContext();
+ return static_cast<PlatformGraphicsContextSkia*>(pc)->canvas();
+}
+
ImageBufferData::ImageBufferData(const IntSize&)
{
}
@@ -82,7 +92,7 @@ PassRefPtr<Image> ImageBuffer::copyImage() const
{
ASSERT(context());
- SkCanvas* canvas = context()->platformContext()->getCanvas();
+ SkCanvas* canvas = imageBufferCanvas(this);
if (!canvas)
return 0;
@@ -123,7 +133,7 @@ PassRefPtr<ByteArray> ImageBuffer::getUnmultipliedImageData(const IntRect& rect)
return 0;
}
- const SkBitmap& src = android_gc2canvas(gc)->getDevice()->accessBitmap(false);
+ const SkBitmap& src = imageBufferCanvas(this)->getDevice()->accessBitmap(false);
SkAutoLockPixels alp(src);
if (!src.getPixels()) {
return 0;
@@ -185,7 +195,7 @@ void ImageBuffer::putUnmultipliedImageData(ByteArray* source, const IntSize& sou
return;
}
- const SkBitmap& dst = android_gc2canvas(gc)->getDevice()->accessBitmap(true);
+ const SkBitmap& dst = imageBufferCanvas(this)->getDevice()->accessBitmap(true);
SkAutoLockPixels alp(dst);
if (!dst.getPixels()) {
return;
@@ -240,7 +250,7 @@ String ImageBuffer::toDataURL(const String&, const double*) const
{
// Encode the image into a vector.
SkDynamicMemoryWStream pngStream;
- const SkBitmap& dst = android_gc2canvas(context())->getDevice()->accessBitmap(true);
+ const SkBitmap& dst = imageBufferCanvas(this)->getDevice()->accessBitmap(true);
SkImageEncoder::EncodeStream(&pngStream, dst, SkImageEncoder::kPNG_Type, 100);
// Convert it into base64.
diff --git a/Source/WebCore/platform/graphics/android/ImageBufferDataAndroid.h b/Source/WebCore/platform/graphics/android/ImageBufferDataAndroid.h
index 80cf79f..eeade6e 100644
--- a/Source/WebCore/platform/graphics/android/ImageBufferDataAndroid.h
+++ b/Source/WebCore/platform/graphics/android/ImageBufferDataAndroid.h
@@ -26,9 +26,14 @@
#ifndef ImageBufferDataAndroid_h
#define ImageBufferDataAndroid_h
+class SkCanvas;
+
namespace WebCore {
class IntSize;
+class ImageBuffer;
+
+SkCanvas* imageBufferCanvas(const ImageBuffer* buffer);
class ImageBufferData {
public:
diff --git a/Source/WebCore/platform/graphics/android/PathAndroid.cpp b/Source/WebCore/platform/graphics/android/PathAndroid.cpp
index 554e187..e70f983 100644
--- a/Source/WebCore/platform/graphics/android/PathAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/PathAndroid.cpp
@@ -37,7 +37,6 @@
#include "SkRegion.h"
#include "StrokeStyleApplier.h"
#include "TransformationMatrix.h"
-#include "android_graphics.h"
namespace WebCore {
diff --git a/Source/WebCore/platform/graphics/android/PatternAndroid.cpp b/Source/WebCore/platform/graphics/android/PatternAndroid.cpp
index 568036c..ed3265b 100644
--- a/Source/WebCore/platform/graphics/android/PatternAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/PatternAndroid.cpp
@@ -26,7 +26,6 @@
#include "config.h"
#include "Pattern.h"
-#include "android_graphics.h"
#include "GraphicsContext.h"
#include "SkBitmapRef.h"
#include "SkCanvas.h"
@@ -51,6 +50,8 @@ SkShader* Pattern::platformPattern(const AffineTransform&)
if (m_pattern)
return m_pattern;
+ if (!tileImage())
+ return 0;
SkBitmapRef* ref = tileImage()->nativeImageForCurrentFrame();
if (!ref)
return 0;
diff --git a/Source/WebCore/platform/graphics/android/context/GraphicsContextAndroid.cpp b/Source/WebCore/platform/graphics/android/context/GraphicsContextAndroid.cpp
index d6fa5ce..957040b 100644
--- a/Source/WebCore/platform/graphics/android/context/GraphicsContextAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/context/GraphicsContextAndroid.cpp
@@ -46,7 +46,6 @@
#include "SkString.h"
#include "SkiaUtils.h"
#include "TransformationMatrix.h"
-#include "android_graphics.h"
using namespace std;
@@ -110,7 +109,7 @@ GraphicsContext* GraphicsContext::createOffscreenContext(int width, int height)
bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height);
bitmap.allocPixels();
bitmap.eraseColor(0);
- pgc->getCanvas()->setBitmapDevice(bitmap);
+ pgc->canvas()->setBitmapDevice(bitmap);
GraphicsContext* ctx = new GraphicsContext(pgc);
return ctx;
@@ -511,6 +510,8 @@ void GraphicsContext::translate(float x, float y)
{
if (paintingDisabled())
return;
+ if (!x && !y)
+ return;
platformContext()->translate(x, y);
}
@@ -660,10 +661,3 @@ void GraphicsContext::drawHighlightForText(const Font& font, const TextRun& run,
}
} // namespace WebCore
-
-///////////////////////////////////////////////////////////////////////////////
-
-SkCanvas* android_gc2canvas(WebCore::GraphicsContext* gc)
-{
- return gc->platformContext()->getCanvas();
-}
diff --git a/Source/WebCore/platform/graphics/android/context/android_graphics.h b/Source/WebCore/platform/graphics/android/context/GraphicsOperation.cpp
index 7faa781..ab6e676 100644
--- a/Source/WebCore/platform/graphics/android/context/android_graphics.h
+++ b/Source/WebCore/platform/graphics/android/context/GraphicsOperation.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2007, The Android Open Source Project
+ * Copyright 2012, The Android Open Source Project
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -22,21 +22,34 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#define LOG_TAG "GraphicsOperation"
-#ifndef android_graphics_DEFINED
-#define android_graphics_DEFINED
+#include "config.h"
+#include "GraphicsOperation.h"
+
+#include "AndroidLog.h"
+#include "LinearAllocator.h"
namespace WebCore {
- class GraphicsContext;
-}
-class SkCanvas;
+namespace GraphicsOperation {
-// TODO: Move this somewhere else. The implementation for this is actually in
-// GraphicsContextAndroid.cpp, but this is used by a handful of other files
-SkCanvas* android_gc2canvas(WebCore::GraphicsContext* gc);
+void* Operation::operator new(size_t size, LinearAllocator* allocator)
+{
+ return allocator->alloc(size);
+}
-// used to inflate node cache entry
-#define CURSOR_RING_HIT_TEST_RADIUS 5
+void* Operation::operator new(size_t size)
+{
+ ALOGE("Cannot allocate a new Operation directly!");
+ CRASH();
+ return (void*) 0xBADBEEF;
+}
+void Operation::operator delete(void*)
+{
+ ALOGE("Cannot call delete on an Operation!");
+ CRASH();
+}
-#endif
+} // namespace GraphicsOperation
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/context/GraphicsOperation.h b/Source/WebCore/platform/graphics/android/context/GraphicsOperation.h
index 927ff0a..edcdc35 100644
--- a/Source/WebCore/platform/graphics/android/context/GraphicsOperation.h
+++ b/Source/WebCore/platform/graphics/android/context/GraphicsOperation.h
@@ -26,8 +26,6 @@
#ifndef GraphicsOperation_h
#define GraphicsOperation_h
-#if USE(ACCELERATED_COMPOSITING)
-
#include "Color.h"
#include "FloatRect.h"
#include "GlyphBuffer.h"
@@ -44,37 +42,54 @@
#define TYPE_CASE(type) case type: return #type;
+#define DEBUG_GRAPHICS_OPERATIONS false
+
+#if DEBUG_GRAPHICS_OPERATIONS
+#define TYPE(x) virtual OperationType type() { return x; }
+#else
+#define TYPE(x)
+#endif
+
namespace WebCore {
+class CanvasState;
+class LinearAllocator;
+
namespace GraphicsOperation {
-class Operation : public SkRefCnt {
+class Operation {
public:
+ Operation()
+ : m_state(0)
+ , m_canvasState(0)
+ {}
+
+ void* operator new(size_t size, LinearAllocator* allocator);
+
+ // Purposely not implemented - use a LinearAllocator please
+ void* operator new(size_t size);
+ void operator delete(void* ptr);
+
+ // This m_state is applied by ourselves
+ PlatformGraphicsContext::State* m_state;
+ // This is the canvas state that this operation needs
+ // Only used for drawing operations, state operations will be undefined
+ CanvasState* m_canvasState;
+
+ bool apply(PlatformGraphicsContext* context) {
+ if (m_state)
+ context->setRawState(m_state);
+ return applyImpl(context);
+ }
+ virtual bool applyImpl(PlatformGraphicsContext* context) = 0;
+ virtual ~Operation() {}
+
+ virtual const IntRect* opaqueRect() { return 0; }
+ virtual bool isOpaque() { return false; }
+ virtual void setOpaqueRect(const IntRect& bounds) {}
+
+#if DEBUG_GRAPHICS_OPERATIONS
typedef enum { UndefinedOperation
- // State management
- , BeginTransparencyLayerOperation
- , EndTransparencyLayerOperation
- , SaveOperation
- , RestoreOperation
- // State setters
- , SetAlphaOperation
- , SetCompositeOpOperation
- , SetFillColorOperation
- , SetFillShaderOperation
- , SetLineCapOperation
- , SetLineDashOperation
- , SetLineJoinOperation
- , SetMiterLimitOperation
- , SetShadowOperation
- , SetShouldAntialiasOperation
- , SetStrokeColorOperation
- , SetStrokeShaderOperation
- , SetStrokeStyleOperation
- , SetStrokeThicknessOperation
- // Paint setup
- , SetupPaintFillOperation
- , SetupPaintShadowOperation
- , SetupPaintStrokeOperation
// Matrix operations
, ConcatCTMOperation
, ScaleOperation
@@ -89,7 +104,9 @@ public:
// Drawing
, DrawBitmapPatternOperation
, DrawBitmapRectOperation
+ , DrawConvexPolygonQuadOperation
, DrawEllipseOperation
+ , DrawFocusRingOperation
, DrawLineOperation
, DrawLineForTextOperation
, DrawLineForTextCheckingOperation
@@ -100,43 +117,15 @@ public:
, StrokeArcOperation
, StrokePathOperation
, StrokeRectOperation
+ , DrawMediaButtonOperation
// Text
- , DrawComplexTextOperation
- , DrawTextOperation
+ , DrawPosTextOperation
} OperationType;
- virtual void apply(PlatformGraphicsContext* context) = 0;
- virtual ~Operation() {}
- virtual OperationType type() { return UndefinedOperation; }
- virtual String parameters() { return ""; }
- String name()
+ const char* name()
{
switch (type()) {
TYPE_CASE(UndefinedOperation)
- // State management
- TYPE_CASE(BeginTransparencyLayerOperation)
- TYPE_CASE(EndTransparencyLayerOperation)
- TYPE_CASE(SaveOperation)
- TYPE_CASE(RestoreOperation)
- // State setters
- TYPE_CASE(SetAlphaOperation)
- TYPE_CASE(SetCompositeOpOperation)
- TYPE_CASE(SetFillColorOperation)
- TYPE_CASE(SetFillShaderOperation)
- TYPE_CASE(SetLineCapOperation)
- TYPE_CASE(SetLineDashOperation)
- TYPE_CASE(SetLineJoinOperation)
- TYPE_CASE(SetMiterLimitOperation)
- TYPE_CASE(SetShadowOperation)
- TYPE_CASE(SetShouldAntialiasOperation)
- TYPE_CASE(SetStrokeColorOperation)
- TYPE_CASE(SetStrokeShaderOperation)
- TYPE_CASE(SetStrokeStyleOperation)
- TYPE_CASE(SetStrokeThicknessOperation)
- // Paint setup
- TYPE_CASE(SetupPaintFillOperation)
- TYPE_CASE(SetupPaintShadowOperation)
- TYPE_CASE(SetupPaintStrokeOperation)
// Matrix operations
TYPE_CASE(ConcatCTMOperation)
TYPE_CASE(ScaleOperation)
@@ -151,7 +140,9 @@ public:
// Drawing
TYPE_CASE(DrawBitmapPatternOperation)
TYPE_CASE(DrawBitmapRectOperation)
+ TYPE_CASE(DrawConvexPolygonQuadOperation)
TYPE_CASE(DrawEllipseOperation)
+ TYPE_CASE(DrawFocusRingOperation)
TYPE_CASE(DrawLineOperation)
TYPE_CASE(DrawLineForTextOperation)
TYPE_CASE(DrawLineForTextCheckingOperation)
@@ -162,258 +153,23 @@ public:
TYPE_CASE(StrokeArcOperation)
TYPE_CASE(StrokePathOperation)
TYPE_CASE(StrokeRectOperation)
+ TYPE_CASE(DrawMediaButtonOperation)
// Text
- TYPE_CASE(DrawComplexTextOperation)
- TYPE_CASE(DrawTextOperation)
+ TYPE_CASE(DrawPosTextOperation)
}
return "Undefined";
}
+#endif
+ TYPE(UndefinedOperation)
};
-//**************************************
-// State management
-//**************************************
-
-class BeginTransparencyLayer : public Operation {
-public:
- BeginTransparencyLayer(const float opacity) : m_opacity(opacity) {}
- virtual void apply(PlatformGraphicsContext* context) { context->beginTransparencyLayer(m_opacity); }
- virtual OperationType type() { return BeginTransparencyLayerOperation; }
-private:
- float m_opacity;
-};
-class EndTransparencyLayer : public Operation {
-public:
- EndTransparencyLayer() {}
- virtual void apply(PlatformGraphicsContext* context) { context->endTransparencyLayer(); }
- virtual OperationType type() { return EndTransparencyLayerOperation; }
-};
-class Save : public Operation {
-public:
- virtual void apply(PlatformGraphicsContext* context) { context->save(); }
- virtual OperationType type() { return SaveOperation; }
-};
-class Restore : public Operation {
-public:
- virtual void apply(PlatformGraphicsContext* context) { context->restore(); }
- virtual OperationType type() { return RestoreOperation; }
-};
-
-//**************************************
-// State setters
-//**************************************
-
-class SetAlpha : public Operation {
-public:
- SetAlpha(const float alpha) : m_alpha(alpha) {}
- virtual void apply(PlatformGraphicsContext* context) { context->setAlpha(m_alpha); }
- virtual OperationType type() { return SetAlphaOperation; }
-private:
- float m_alpha;
-};
-
-class SetCompositeOperation : public Operation {
-public:
- SetCompositeOperation(CompositeOperator op) : m_operator(op) {}
- virtual void apply(PlatformGraphicsContext* context) {
- context->setCompositeOperation(m_operator);
- }
- virtual OperationType type() { return SetCompositeOpOperation; }
-private:
- CompositeOperator m_operator;
-};
-
-class SetFillColor : public Operation {
-public:
- SetFillColor(Color color) : m_color(color) {}
- virtual void apply(PlatformGraphicsContext* context) {
- context->setFillColor(m_color);
- }
- virtual OperationType type() { return SetFillColorOperation; }
- virtual String parameters() {
- return String::format("r: %d g: %d b: %d a: %d",
- m_color.red(),
- m_color.green(),
- m_color.blue(),
- m_color.alpha());
- }
-private:
- Color m_color;
-};
-
-class SetFillShader : public Operation {
-public:
- SetFillShader(SkShader* shader) : m_shader(shader) {
- SkSafeRef(m_shader);
- }
- ~SetFillShader() { SkSafeUnref(m_shader); }
- virtual void apply(PlatformGraphicsContext* context) {
- context->setFillShader(m_shader);
- }
- virtual OperationType type() { return SetFillShaderOperation; }
-private:
- SkShader* m_shader;
-};
-
-class SetLineCap : public Operation {
-public:
- SetLineCap(LineCap cap) : m_cap(cap) {}
- virtual void apply(PlatformGraphicsContext* context) {
- context->setLineCap(m_cap);
- }
- virtual OperationType type() { return SetLineCapOperation; }
-private:
- LineCap m_cap;
-};
-
-class SetLineDash : public Operation {
-public:
- SetLineDash(const DashArray& dashes, float dashOffset)
- : m_dashes(dashes), m_dashOffset(dashOffset) {}
- virtual void apply(PlatformGraphicsContext* context) {
- context->setLineDash(m_dashes, m_dashOffset);
- }
- virtual OperationType type() { return SetLineDashOperation; }
-private:
- DashArray m_dashes;
- float m_dashOffset;
-};
-
-class SetLineJoin : public Operation {
-public:
- SetLineJoin(LineJoin join) : m_join(join) {}
- virtual void apply(PlatformGraphicsContext* context) {
- context->setLineJoin(m_join);
- }
- virtual OperationType type() { return SetLineJoinOperation; }
-private:
- LineJoin m_join;
-};
-
-class SetMiterLimit : public Operation {
-public:
- SetMiterLimit(float limit) : m_limit(limit) {}
- virtual void apply(PlatformGraphicsContext* context) {
- context->setMiterLimit(m_limit);
- }
- virtual OperationType type() { return SetMiterLimitOperation; }
-private:
- float m_limit;
-};
-
-class SetShadow : public Operation {
-public:
- SetShadow(int radius, int dx, int dy, SkColor c)
- : m_radius(radius), m_dx(dx), m_dy(dy), m_color(c) {}
- virtual void apply(PlatformGraphicsContext* context) {
- context->setShadow(m_radius, m_dx, m_dy, m_color);
- }
- virtual OperationType type() { return SetShadowOperation; }
-private:
- int m_radius;
- int m_dx;
- int m_dy;
- SkColor m_color;
-};
-
-class SetShouldAntialias : public Operation {
-public:
- SetShouldAntialias(bool useAA) : m_useAA(useAA) {}
- virtual void apply(PlatformGraphicsContext* context) {
- context->setShouldAntialias(m_useAA);
- }
- virtual OperationType type() { return SetShouldAntialiasOperation; }
-private:
- bool m_useAA;
-};
-
-class SetStrokeColor : public Operation {
-public:
- SetStrokeColor(const Color& c) : m_color(c) {}
- virtual void apply(PlatformGraphicsContext* context) {
- context->setStrokeColor(m_color);
- }
- virtual OperationType type() { return SetStrokeColorOperation; }
-private:
- Color m_color;
-};
-
-class SetStrokeShader : public Operation {
-public:
- SetStrokeShader(SkShader* strokeShader) : m_shader(strokeShader) {
- SkSafeRef(m_shader);
- }
- ~SetStrokeShader() { SkSafeUnref(m_shader); }
- virtual void apply(PlatformGraphicsContext* context) {
- context->setStrokeShader(m_shader);
- }
- virtual OperationType type() { return SetStrokeShaderOperation; }
-private:
- SkShader* m_shader;
-};
-
-class SetStrokeStyle : public Operation {
+class PossiblyOpaqueOperation : public Operation {
public:
- SetStrokeStyle(StrokeStyle style) : m_style(style) {}
- virtual void apply(PlatformGraphicsContext* context) {
- context->setStrokeStyle(m_style);
- }
- virtual OperationType type() { return SetStrokeStyleOperation; }
-private:
- StrokeStyle m_style;
-};
+ virtual const IntRect* opaqueRect() { return &m_absoluteOpaqueRect; }
+ virtual void setOpaqueRect(const IntRect& bounds) { m_absoluteOpaqueRect = bounds; }
-class SetStrokeThickness : public Operation {
-public:
- SetStrokeThickness(float thickness) : m_thickness(thickness) {}
- virtual void apply(PlatformGraphicsContext* context) {
- context->setStrokeThickness(m_thickness);
- }
- virtual OperationType type() { return SetStrokeThicknessOperation; }
private:
- float m_thickness;
-};
-
-//**************************************
-// Paint setup
-//**************************************
-
-class SetupPaintFill : public Operation {
-public:
- SetupPaintFill(SkPaint* paint) : m_paint(*paint) {}
- virtual void apply(PlatformGraphicsContext* context) {
- context->setupPaintFill(&m_paint);
- }
- virtual OperationType type() { return SetupPaintFillOperation; }
-private:
- SkPaint m_paint;
-};
-
-class SetupPaintShadow : public Operation {
-public:
- SetupPaintShadow(SkPaint* paint, SkPoint* offset)
- : m_paint(*paint), m_offset(*offset) {}
- virtual void apply(PlatformGraphicsContext* context) {
- context->setupPaintShadow(&m_paint, &m_offset);
- }
- virtual OperationType type() { return SetupPaintShadowOperation; }
-private:
- SkPaint m_paint;
- SkPoint m_offset;
-};
-
-class SetupPaintStroke : public Operation {
-public:
- SetupPaintStroke(SkPaint* paint, SkRect* rect, bool isHLine)
- : m_paint(*paint), m_rect(*rect), m_isHLine(isHLine) {}
- virtual void apply(PlatformGraphicsContext* context) {
- context->setupPaintStroke(&m_paint, &m_rect, m_isHLine);
- }
- virtual OperationType type() { return SetupPaintStrokeOperation; }
-private:
- SkPaint m_paint;
- SkRect m_rect;
- bool m_isHLine;
+ IntRect m_absoluteOpaqueRect;
};
//**************************************
@@ -423,10 +179,11 @@ private:
class ConcatCTM : public Operation {
public:
ConcatCTM(const AffineTransform& affine) : m_matrix(affine) {}
- virtual void apply(PlatformGraphicsContext* context) {
+ virtual bool applyImpl(PlatformGraphicsContext* context) {
context->concatCTM(m_matrix);
+ return true;
}
- virtual OperationType type() { return ConcatCTMOperation; }
+ TYPE(ConcatCTMOperation)
private:
AffineTransform m_matrix;
};
@@ -434,10 +191,11 @@ private:
class Rotate : public Operation {
public:
Rotate(float angleInRadians) : m_angle(angleInRadians) {}
- virtual void apply(PlatformGraphicsContext* context) {
+ virtual bool applyImpl(PlatformGraphicsContext* context) {
context->rotate(m_angle);
+ return true;
}
- virtual OperationType type() { return RotateOperation; }
+ TYPE(RotateOperation)
private:
float m_angle;
};
@@ -445,10 +203,11 @@ private:
class Scale : public Operation {
public:
Scale(const FloatSize& size) : m_scale(size) {}
- virtual void apply(PlatformGraphicsContext* context) {
+ virtual bool applyImpl(PlatformGraphicsContext* context) {
context->scale(m_scale);
+ return true;
}
- virtual OperationType type() { return ScaleOperation; }
+ TYPE(ScaleOperation)
private:
FloatSize m_scale;
};
@@ -456,10 +215,11 @@ private:
class Translate : public Operation {
public:
Translate(float x, float y) : m_x(x), m_y(y) {}
- virtual void apply(PlatformGraphicsContext* context) {
+ virtual bool applyImpl(PlatformGraphicsContext* context) {
context->translate(m_x, m_y);
+ return true;
}
- virtual OperationType type() { return TranslateOperation; }
+ TYPE(TranslateOperation)
private:
float m_x;
float m_y;
@@ -473,10 +233,11 @@ class InnerRoundedRectClip : public Operation {
public:
InnerRoundedRectClip(const IntRect& rect, int thickness)
: m_rect(rect), m_thickness(thickness) {}
- virtual void apply(PlatformGraphicsContext* context) {
+ virtual bool applyImpl(PlatformGraphicsContext* context) {
context->addInnerRoundedRectClip(m_rect, m_thickness);
+ return true;
}
- virtual OperationType type() { return InnerRoundedRectClipOperation; }
+ TYPE(InnerRoundedRectClipOperation)
private:
IntRect m_rect;
int m_thickness;
@@ -485,10 +246,10 @@ private:
class Clip : public Operation {
public:
Clip(const FloatRect& rect) : m_rect(rect) {}
- virtual void apply(PlatformGraphicsContext* context) {
- context->clip(m_rect);
+ virtual bool applyImpl(PlatformGraphicsContext* context) {
+ return context->clip(m_rect);
}
- virtual OperationType type() { return ClipOperation; }
+ TYPE(ClipOperation)
private:
const FloatRect m_rect;
};
@@ -498,17 +259,16 @@ public:
ClipPath(const Path& path, bool clipout = false)
: m_path(path), m_clipOut(clipout), m_hasWindRule(false) {}
void setWindRule(WindRule rule) { m_windRule = rule; m_hasWindRule = true; }
- virtual void apply(PlatformGraphicsContext* context) {
+ virtual bool applyImpl(PlatformGraphicsContext* context) {
if (m_hasWindRule) {
- context->clipPath(m_path, m_windRule);
- return;
+ return context->clipPath(m_path, m_windRule);
}
if (m_clipOut)
- context->clipOut(m_path);
+ return context->clipOut(m_path);
else
- context->clip(m_path);
+ return context->clip(m_path);
}
- virtual OperationType type() { return ClipPathOperation; }
+ TYPE(ClipPathOperation)
private:
const Path m_path;
bool m_clipOut;
@@ -519,10 +279,10 @@ private:
class ClipOut : public Operation {
public:
ClipOut(const IntRect& rect) : m_rect(rect) {}
- virtual void apply(PlatformGraphicsContext* context) {
- context->clipOut(m_rect);
+ virtual bool applyImpl(PlatformGraphicsContext* context) {
+ return context->clipOut(m_rect);
}
- virtual OperationType type() { return ClipOutOperation; }
+ TYPE(ClipOutOperation)
private:
const IntRect m_rect;
};
@@ -530,10 +290,11 @@ private:
class ClearRect : public Operation {
public:
ClearRect(const FloatRect& rect) : m_rect(rect) {}
- virtual void apply(PlatformGraphicsContext* context) {
+ virtual bool applyImpl(PlatformGraphicsContext* context) {
context->clearRect(m_rect);
+ return true;
}
- virtual OperationType type() { return ClearRectOperation; }
+ TYPE(ClearRectOperation)
private:
FloatRect m_rect;
};
@@ -542,63 +303,101 @@ private:
// Drawing
//**************************************
-class DrawBitmapPattern : public Operation {
+class DrawBitmapPattern : public PossiblyOpaqueOperation {
public:
DrawBitmapPattern(const SkBitmap& bitmap, const SkMatrix& matrix,
CompositeOperator op, const FloatRect& destRect)
: m_bitmap(bitmap), m_matrix(matrix), m_operator(op), m_destRect(destRect) {}
- virtual void apply(PlatformGraphicsContext* context) {
+ virtual bool applyImpl(PlatformGraphicsContext* context) {
context->drawBitmapPattern(m_bitmap, m_matrix, m_operator, m_destRect);
+ return true;
}
- virtual OperationType type() { return DrawBitmapPatternOperation; }
+ virtual bool isOpaque() { return m_bitmap.isOpaque(); }
+ TYPE(DrawBitmapPatternOperation)
+
private:
- // TODO: use refcounted bitmap
- const SkBitmap m_bitmap;
+ SkBitmap m_bitmap;
SkMatrix m_matrix;
CompositeOperator m_operator;
FloatRect m_destRect;
};
-class DrawBitmapRect : public Operation {
+class DrawBitmapRect : public PossiblyOpaqueOperation {
public:
DrawBitmapRect(const SkBitmap& bitmap, const SkIRect& srcR,
const SkRect& dstR, CompositeOperator op)
: m_bitmap(bitmap), m_srcR(srcR), m_dstR(dstR), m_operator(op) {}
- virtual void apply(PlatformGraphicsContext* context) {
+ virtual bool applyImpl(PlatformGraphicsContext* context) {
context->drawBitmapRect(m_bitmap, &m_srcR, m_dstR, m_operator);
+ return true;
}
- virtual OperationType type() { return DrawBitmapRectOperation; }
- virtual String parameters() {
- return String::format("%.2f, %.2f - %.2f x %.2f",
- m_dstR.fLeft, m_dstR.fTop,
- m_dstR.width(), m_dstR.height());
- }
+ virtual bool isOpaque() { return m_bitmap.isOpaque(); }
+ TYPE(DrawBitmapRectOperation)
private:
- const SkBitmap& m_bitmap;
+ SkBitmap m_bitmap;
SkIRect m_srcR;
SkRect m_dstR;
CompositeOperator m_operator;
};
+class DrawConvexPolygonQuad : public Operation {
+public:
+ DrawConvexPolygonQuad(const FloatPoint* points, bool shouldAntiAlias)
+ : m_shouldAntiAlias(shouldAntiAlias)
+ {
+ memcpy(m_points, points, 4 * sizeof(FloatPoint));
+ }
+ virtual bool applyImpl(PlatformGraphicsContext* context) {
+ context->drawConvexPolygon(4, m_points, m_shouldAntiAlias);
+ return true;
+ }
+ TYPE(DrawConvexPolygonQuadOperation)
+private:
+ bool m_shouldAntiAlias;
+ FloatPoint m_points[4];
+};
+
class DrawEllipse : public Operation {
public:
DrawEllipse(const IntRect& rect) : m_rect(rect) {}
- virtual void apply(PlatformGraphicsContext* context) {
+ virtual bool applyImpl(PlatformGraphicsContext* context) {
context->drawEllipse(m_rect);
+ return true;
}
- virtual OperationType type() { return DrawEllipseOperation; }
+ TYPE(DrawEllipseOperation)
private:
IntRect m_rect;
};
+class DrawFocusRing : public Operation {
+public:
+ DrawFocusRing(const Vector<IntRect>& rects, int width, int offset, const Color& color)
+ : m_rects(rects)
+ , m_width(width)
+ , m_offset(offset)
+ , m_color(color)
+ {}
+ virtual bool applyImpl(PlatformGraphicsContext* context) {
+ context->drawFocusRing(m_rects, m_width, m_offset, m_color);
+ return true;
+ }
+ TYPE(DrawFocusRingOperation)
+private:
+ Vector<IntRect> m_rects;
+ int m_width;
+ int m_offset;
+ Color m_color;
+};
+
class DrawLine : public Operation {
public:
DrawLine(const IntPoint& point1, const IntPoint& point2)
: m_point1(point1), m_point2(point2) {}
- virtual void apply(PlatformGraphicsContext* context) {
+ virtual bool applyImpl(PlatformGraphicsContext* context) {
context->drawLine(m_point1, m_point2);
+ return true;
}
- virtual OperationType type() { return DrawLineOperation; }
+ TYPE(DrawLineOperation)
private:
IntPoint m_point1;
IntPoint m_point2;
@@ -608,10 +407,11 @@ class DrawLineForText : public Operation {
public:
DrawLineForText(const FloatPoint& pt, float width)
: m_point(pt), m_width(width) {}
- virtual void apply(PlatformGraphicsContext* context) {
+ virtual bool applyImpl(PlatformGraphicsContext* context) {
context->drawLineForText(m_point, m_width);
+ return true;
}
- virtual OperationType type() { return DrawLineForTextOperation; }
+ TYPE(DrawLineForTextOperation)
private:
FloatPoint m_point;
float m_width;
@@ -622,10 +422,11 @@ public:
DrawLineForTextChecking(const FloatPoint& pt, float width,
GraphicsContext::TextCheckingLineStyle lineStyle)
: m_point(pt), m_width(width), m_lineStyle(lineStyle) {}
- virtual void apply(PlatformGraphicsContext* context) {
+ virtual bool applyImpl(PlatformGraphicsContext* context) {
context->drawLineForTextChecking(m_point, m_width, m_lineStyle);
+ return true;
}
- virtual OperationType type() { return DrawLineForTextCheckingOperation; }
+ TYPE(DrawLineForTextCheckingOperation)
private:
FloatPoint m_point;
float m_width;
@@ -635,10 +436,11 @@ private:
class DrawRect : public Operation {
public:
DrawRect(const IntRect& rect) : m_rect(rect) {}
- virtual void apply(PlatformGraphicsContext* context) {
+ virtual bool applyImpl(PlatformGraphicsContext* context) {
context->drawRect(m_rect);
+ return true;
}
- virtual OperationType type() { return DrawRectOperation; }
+ TYPE(DrawRectOperation)
private:
IntRect m_rect;
};
@@ -647,26 +449,30 @@ class FillPath : public Operation {
public:
FillPath(const Path& pathToFill, WindRule fillRule)
: m_path(pathToFill), m_fillRule(fillRule) {}
- virtual void apply(PlatformGraphicsContext* context) {
+ virtual bool applyImpl(PlatformGraphicsContext* context) {
context->fillPath(m_path, m_fillRule);
+ return true;
}
- virtual OperationType type() { return FillPathOperation; }
+ TYPE(FillPathOperation)
private:
Path m_path;
WindRule m_fillRule;
};
-class FillRect : public Operation {
+class FillRect : public PossiblyOpaqueOperation {
public:
FillRect(const FloatRect& rect) : m_rect(rect), m_hasColor(false) {}
void setColor(Color c) { m_color = c; m_hasColor = true; }
- virtual void apply(PlatformGraphicsContext* context) {
+ virtual bool applyImpl(PlatformGraphicsContext* context) {
if (m_hasColor)
context->fillRect(m_rect, m_color);
else
context->fillRect(m_rect);
+ return true;
}
- virtual OperationType type() { return FillRectOperation; }
+ virtual bool isOpaque() { return (m_hasColor && !m_color.hasAlpha())
+ || (!m_hasColor && SkColorGetA(m_state->fillColor) == 0xFF); }
+ TYPE(FillRectOperation)
private:
FloatRect m_rect;
Color m_color;
@@ -688,12 +494,13 @@ public:
, m_bottomRight(bottomRight)
, m_color(color)
{}
- virtual void apply(PlatformGraphicsContext* context) {
+ virtual bool applyImpl(PlatformGraphicsContext* context) {
context->fillRoundedRect(m_rect, m_topLeft, m_topRight,
m_bottomLeft, m_bottomRight,
m_color);
+ return true;
}
- virtual OperationType type() { return FillRoundedRectOperation; }
+ TYPE(FillRoundedRectOperation)
private:
IntRect m_rect;
IntSize m_topLeft;
@@ -710,10 +517,11 @@ public:
, m_startAngle(startAngle)
, m_angleSpan(angleSpan)
{}
- virtual void apply(PlatformGraphicsContext* context) {
+ virtual bool applyImpl(PlatformGraphicsContext* context) {
context->strokeArc(m_rect, m_startAngle, m_angleSpan);
+ return true;
}
- virtual OperationType type() { return StrokeArcOperation; }
+ TYPE(StrokeArcOperation)
private:
IntRect m_rect;
int m_startAngle;
@@ -723,10 +531,11 @@ private:
class StrokePath : public Operation {
public:
StrokePath(const Path& path) : m_path(path) {}
- virtual void apply(PlatformGraphicsContext* context) {
+ virtual bool applyImpl(PlatformGraphicsContext* context) {
context->strokePath(m_path);
+ return true;
}
- virtual OperationType type() { return StrokePathOperation; }
+ TYPE(StrokePathOperation)
private:
Path m_path;
};
@@ -736,74 +545,67 @@ class StrokeRect : public Operation {
public:
StrokeRect(const FloatRect& rect, float lineWidth)
: m_rect(rect), m_lineWidth(lineWidth) {}
- virtual void apply(PlatformGraphicsContext* context) {
+ virtual bool applyImpl(PlatformGraphicsContext* context) {
context->strokeRect(m_rect, m_lineWidth);
+ return true;
}
- virtual OperationType type() { return StrokeRectOperation; }
+ TYPE(StrokeRectOperation)
private:
FloatRect m_rect;
float m_lineWidth;
};
-//**************************************
-// Text
-//**************************************
-
-class DrawComplexText : public Operation {
+class DrawMediaButton : public Operation {
public:
- DrawComplexText(SkPicture* picture) : m_picture(picture) {
- SkSafeRef(m_picture);
- }
- ~DrawComplexText() { SkSafeUnref(m_picture); }
- virtual void apply(PlatformGraphicsContext* context) {
- if (!context->getCanvas())
- return;
- context->getCanvas()->drawPicture(*m_picture);
+ DrawMediaButton(const IntRect& rect, RenderSkinMediaButton::MediaButton buttonType,
+ bool translucent, bool drawBackground,
+ const IntRect& thumb)
+ : m_rect(rect)
+ , m_thumb(thumb)
+ , m_buttonType(buttonType)
+ , m_translucent(translucent)
+ , m_drawBackground(drawBackground)
+ {}
+ virtual bool applyImpl(PlatformGraphicsContext* context) {
+ context->drawMediaButton(m_rect, m_buttonType, m_translucent, m_drawBackground, m_thumb);
+ return true;
}
- virtual OperationType type() { return DrawComplexTextOperation; }
+ TYPE(DrawMediaButtonOperation)
private:
- SkPicture* m_picture;
+ IntRect m_rect;
+ IntRect m_thumb;
+ RenderSkinMediaButton::MediaButton m_buttonType;
+ bool m_translucent : 1;
+ bool m_drawBackground : 1;
};
-class DrawText : public Operation {
+//**************************************
+// Text
+//**************************************
+
+class DrawPosText : public Operation {
public:
- DrawText(const Font* font, const SimpleFontData* simpleFont,
- const GlyphBuffer& glyphBuffer,
- int from, int numGlyphs, const FloatPoint& point)
- : m_font(font), m_simpleFont(simpleFont)
- , m_glyphBuffer(glyphBuffer), m_from(from)
- , m_numGlyphs(numGlyphs), m_point(point) {
-
- SkPicture* picture = new SkPicture();
- SkCanvas* canvas = picture->beginRecording(0, 0, 0);
- PlatformGraphicsContextSkia platformContext(canvas);
- GraphicsContext graphicsContext(&platformContext);
- m_font->drawGlyphs(&graphicsContext, m_simpleFont,
- m_glyphBuffer, m_from, m_numGlyphs, m_point);
- picture->endRecording();
- m_picture = picture;
- }
- ~DrawText() { SkSafeUnref(m_picture); }
- virtual void apply(PlatformGraphicsContext* context) {
- if (!context->getCanvas())
- return;
- context->getCanvas()->drawPicture(*m_picture);
+ DrawPosText(const void* text, size_t byteLength,
+ const SkPoint pos[], const SkPaint* paint)
+ : m_text(text)
+ , m_byteLength(byteLength)
+ , m_pos(pos)
+ , m_paint(paint)
+ {}
+ virtual bool applyImpl(PlatformGraphicsContext* context) {
+ context->drawPosText(m_text, m_byteLength, m_pos, *m_paint);
+ return true;
}
- virtual OperationType type() { return DrawTextOperation; }
+ TYPE(DrawPosTextOperation)
private:
- SkPicture* m_picture;
- const Font* m_font;
- const SimpleFontData* m_simpleFont;
- const GlyphBuffer m_glyphBuffer;
- int m_from;
- int m_numGlyphs;
- const FloatPoint m_point;
+ const void* m_text;
+ size_t m_byteLength;
+ const SkPoint* m_pos;
+ const SkPaint* m_paint;
};
}
}
-#endif // USE(ACCELERATED_COMPOSITING)
-
#endif // GraphicsOperation_h
diff --git a/Source/WebCore/platform/graphics/android/context/GraphicsOperationCollection.cpp b/Source/WebCore/platform/graphics/android/context/GraphicsOperationCollection.cpp
deleted file mode 100644
index 9e6208d..0000000
--- a/Source/WebCore/platform/graphics/android/context/GraphicsOperationCollection.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-#define LOG_TAG "GraphicsOperationCollection"
-#define LOG_NDEBUG 1
-
-#include "config.h"
-#include "GraphicsOperationCollection.h"
-
-#include "AndroidLog.h"
-#include "GraphicsContext.h"
-#include "PlatformGraphicsContext.h"
-#include "PlatformGraphicsContextRecording.h"
-
-#if USE(ACCELERATED_COMPOSITING)
-
-namespace WebCore {
-
-GraphicsOperationCollection::GraphicsOperationCollection(const IntRect& drawArea)
- : m_drawArea(drawArea)
-{
-}
-
-GraphicsOperationCollection::~GraphicsOperationCollection()
-{
- for (unsigned int i = 0; i < m_operations.size(); i++)
- SkSafeUnref(m_operations[i]);
-}
-
-void GraphicsOperationCollection::apply(PlatformGraphicsContext* context)
-{
- ALOGD("\nApply GraphicsOperationCollection %x, %d operations", this, m_operations.size());
- for (unsigned int i = 0; i < m_operations.size(); i++) {
- ALOGD("[%d] (%x) %s %s", i, this, m_operations[i]->name().ascii().data(),
- m_operations[i]->parameters().ascii().data());
- m_operations[i]->apply(context);
- }
-}
-
-void GraphicsOperationCollection::append(GraphicsOperation::Operation* operation)
-{
- m_operations.append(operation);
-}
-
-bool GraphicsOperationCollection::isEmpty()
-{
- return !m_operations.size();
-}
-
-AutoGraphicsOperationCollection::AutoGraphicsOperationCollection(const IntRect& area)
-{
- m_graphicsOperationCollection = new GraphicsOperationCollection(area);
- m_platformGraphicsContext = new PlatformGraphicsContextRecording(m_graphicsOperationCollection);
- m_graphicsContext = new GraphicsContext(m_platformGraphicsContext);
-}
-
-AutoGraphicsOperationCollection::~AutoGraphicsOperationCollection()
-{
- SkSafeUnref(m_graphicsOperationCollection);
- delete m_graphicsContext;
- delete m_platformGraphicsContext;
-}
-
-} // namespace WebCore
-
-#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContext.cpp b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContext.cpp
index ce9ce5a..367abda 100644
--- a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContext.cpp
+++ b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContext.cpp
@@ -82,6 +82,8 @@ static bool setBitmapDash(SkPaint* paint, int width) {
s->setLocalMatrix(matrix);
paint->setShader(s)->unref();
+ paint->setFilterBitmap(true);
+ paint->setAntiAlias(true);
return true;
}
@@ -159,7 +161,7 @@ bool PlatformGraphicsContext::State::setupShadowPaint(SkPaint* paint, SkPoint* o
// HTMLCanvasElement have shadows ignore transforms set. This
// allows us to distinguish between CSS and Canvas shadows which
// have different rendering specifications.
- uint32_t flags = SkBlurMaskFilter::kHighQuality_BlurFlag;
+ uint32_t flags = SkBlurMaskFilter::kNone_BlurFlag;
if (shadowsIgnoreTransforms) {
offset->fY = -offset->fY;
flags |= SkBlurMaskFilter::kIgnoreTransform_BlurFlag;
@@ -167,7 +169,7 @@ bool PlatformGraphicsContext::State::setupShadowPaint(SkPaint* paint, SkPoint* o
if (shadow.blur > 0) {
paint->setMaskFilter(SkBlurMaskFilter::Create(shadow.blur,
- SkBlurMaskFilter::kNormal_BlurStyle))->unref();
+ SkBlurMaskFilter::kNormal_BlurStyle, flags))->unref();
}
return SkColorGetA(shadow.color) && (shadow.blur || shadow.dx || shadow.dy);
}
@@ -244,22 +246,31 @@ void PlatformGraphicsContext::setCompositeOperation(CompositeOperator op)
m_state->mode = WebCoreCompositeToSkiaComposite(op);
}
-void PlatformGraphicsContext::setFillColor(const Color& c)
+bool PlatformGraphicsContext::setFillColor(const Color& c)
{
- m_state->fillColor = c.rgb();
- setFillShader(0);
+ bool dirty = false;
+ if (m_state->fillColor != c.rgb()) {
+ m_state->fillColor = c.rgb();
+ dirty = true;
+ }
+ return setFillShader(0) || dirty;
}
-void PlatformGraphicsContext::setFillShader(SkShader* fillShader)
+bool PlatformGraphicsContext::setFillShader(SkShader* fillShader)
{
- if (fillShader)
+ bool dirty = false;
+ if (fillShader && m_state->fillColor != Color::black) {
m_state->fillColor = Color::black;
+ dirty = true;
+ }
if (fillShader != m_state->fillShader) {
SkSafeUnref(m_state->fillShader);
m_state->fillShader = fillShader;
SkSafeRef(m_state->fillShader);
+ dirty = true;
}
+ return dirty;
}
void PlatformGraphicsContext::setLineCap(LineCap cap)
@@ -331,22 +342,31 @@ void PlatformGraphicsContext::setShouldAntialias(bool useAA)
m_state->useAA = useAA;
}
-void PlatformGraphicsContext::setStrokeColor(const Color& c)
+bool PlatformGraphicsContext::setStrokeColor(const Color& c)
{
- m_state->strokeColor = c.rgb();
- setStrokeShader(0);
+ bool dirty = false;
+ if (m_state->strokeColor != c.rgb()) {
+ m_state->strokeColor = c.rgb();
+ dirty = true;
+ }
+ return setStrokeShader(0) || dirty;
}
-void PlatformGraphicsContext::setStrokeShader(SkShader* strokeShader)
+bool PlatformGraphicsContext::setStrokeShader(SkShader* strokeShader)
{
- if (strokeShader)
+ bool dirty = false;
+ if (strokeShader && m_state->strokeColor != Color::black) {
m_state->strokeColor = Color::black;
+ dirty = true;
+ }
if (strokeShader != m_state->strokeShader) {
SkSafeUnref(m_state->strokeShader);
m_state->strokeShader = strokeShader;
SkSafeRef(m_state->strokeShader);
+ dirty = true;
}
+ return dirty;
}
void PlatformGraphicsContext::setStrokeStyle(StrokeStyle style)
@@ -375,7 +395,7 @@ void PlatformGraphicsContext::setupPaintCommon(SkPaint* paint) const
// allows us to distinguish between CSS and Canvas shadows which
// have different rendering specifications.
SkScalar dy = m_state->shadow.dy;
- uint32_t flags = SkBlurDrawLooper::kHighQuality_BlurFlag;
+ uint32_t flags = SkBlurDrawLooper::kNone_BlurFlag;
if (shadowsIgnoreTransforms()) {
dy = -dy;
flags |= SkBlurDrawLooper::kIgnoreTransform_BlurFlag;
diff --git a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContext.h b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContext.h
index 1916014..56aceff 100644
--- a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContext.h
+++ b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContext.h
@@ -29,6 +29,7 @@
#include "IntRect.h"
#include "GraphicsContext.h"
#include "RenderSkinAndroid.h"
+#include "RenderSkinMediaButton.h"
#include "SkCanvas.h"
#include "SkPicture.h"
#include "SkTDArray.h"
@@ -40,10 +41,11 @@ namespace WebCore {
class PlatformGraphicsContext {
public:
+ class State;
+
PlatformGraphicsContext();
virtual ~PlatformGraphicsContext();
virtual bool isPaintingDisabled() = 0;
- virtual SkCanvas* getCanvas() = 0;
void setGraphicsContext(GraphicsContext* gc) { m_gc = gc; }
virtual bool deleteUs() const { return false; }
@@ -61,16 +63,16 @@ public:
virtual void setAlpha(float alpha);
int getNormalizedAlpha() const;
virtual void setCompositeOperation(CompositeOperator op);
- virtual void setFillColor(const Color& c);
- virtual void setFillShader(SkShader* fillShader);
+ virtual bool setFillColor(const Color& c);
+ virtual bool setFillShader(SkShader* fillShader);
virtual void setLineCap(LineCap cap);
virtual void setLineDash(const DashArray& dashes, float dashOffset);
virtual void setLineJoin(LineJoin join);
virtual void setMiterLimit(float limit);
virtual void setShadow(int radius, int dx, int dy, SkColor c);
virtual void setShouldAntialias(bool useAA);
- virtual void setStrokeColor(const Color& c);
- virtual void setStrokeShader(SkShader* strokeShader);
+ virtual bool setStrokeColor(const Color& c);
+ virtual bool setStrokeShader(SkShader* strokeShader);
virtual void setStrokeStyle(StrokeStyle style);
virtual void setStrokeThickness(float f);
@@ -92,19 +94,20 @@ public:
// Clipping
virtual void addInnerRoundedRectClip(const IntRect& rect, int thickness) = 0;
virtual void canvasClip(const Path& path) = 0;
- virtual void clip(const FloatRect& rect) = 0;
- virtual void clip(const Path& path) = 0;
- virtual void clipConvexPolygon(size_t numPoints, const FloatPoint*, bool antialias) = 0;
- virtual void clipOut(const IntRect& r) = 0;
- virtual void clipOut(const Path& p) = 0;
- virtual void clipPath(const Path& pathToClip, WindRule clipRule) = 0;
+ virtual bool clip(const FloatRect& rect) = 0;
+ virtual bool clip(const Path& path) = 0;
+ virtual bool clipConvexPolygon(size_t numPoints, const FloatPoint*, bool antialias) = 0;
+ virtual bool clipOut(const IntRect& r) = 0;
+ virtual bool clipOut(const Path& p) = 0;
+ virtual bool clipPath(const Path& pathToClip, WindRule clipRule) = 0;
+ virtual SkIRect getTotalClipBounds() = 0;
// Drawing
virtual void clearRect(const FloatRect& rect) = 0;
virtual void drawBitmapPattern(const SkBitmap& bitmap, const SkMatrix& matrix,
CompositeOperator compositeOp, const FloatRect& destRect) = 0;
virtual void drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src,
- const SkRect& dst, CompositeOperator op) = 0;
+ const SkRect& dst, CompositeOperator op = CompositeSourceOver) = 0;
virtual void drawConvexPolygon(size_t numPoints, const FloatPoint* points,
bool shouldAntialias) = 0;
virtual void drawEllipse(const IntRect& rect) = 0;
@@ -117,7 +120,7 @@ public:
virtual void drawLine(const IntPoint& point1, const IntPoint& point2) = 0;
virtual void drawLineForText(const FloatPoint& pt, float width) = 0;
virtual void drawLineForTextChecking(const FloatPoint& pt, float width,
- GraphicsContext::TextCheckingLineStyle) = 0;
+ GraphicsContext::TextCheckingLineStyle) = 0;
virtual void drawRect(const IntRect& rect) = 0;
virtual void fillPath(const Path& pathToFill, WindRule fillRule) = 0;
virtual void fillRect(const FloatRect& rect) = 0;
@@ -138,10 +141,15 @@ public:
virtual void strokePath(const Path& pathToStroke) = 0;
virtual void strokeRect(const FloatRect& rect, float lineWidth) = 0;
+ virtual void drawPosText(const void* text, size_t byteLength,
+ const SkPoint pos[], const SkPaint& paint) = 0;
+ virtual void drawMediaButton(const IntRect& rect, RenderSkinMediaButton::MediaButton buttonType,
+ bool translucent = false, bool drawBackground = true,
+ const IntRect& thumb = IntRect()) = 0;
+
virtual SkCanvas* recordingCanvas() = 0;
- virtual void endRecording(int type = 0) = 0;
-protected:
+ void setRawState(State* state) { m_state = state; }
struct ShadowRec {
SkScalar blur;
@@ -192,11 +200,11 @@ protected:
friend class PlatformGraphicsContextSkia;
};
+protected:
virtual bool shadowsIgnoreTransforms() const = 0;
void setupPaintCommon(SkPaint* paint) const;
GraphicsContext* m_gc; // Back-ptr to our parent
- struct State;
WTF::Vector<State> m_stateStack;
State* m_state;
};
diff --git a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.cpp b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.cpp
index d96124d..3237a80 100644
--- a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.cpp
+++ b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.cpp
@@ -1,3 +1,28 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
#define LOG_TAG "PlatformGraphicsContextRecording"
#define LOG_NDEBUG 1
@@ -5,71 +30,526 @@
#include "PlatformGraphicsContextRecording.h"
#include "AndroidLog.h"
+#include "FloatRect.h"
+#include "FloatQuad.h"
#include "Font.h"
#include "GraphicsContext.h"
-#include "GraphicsOperationCollection.h"
#include "GraphicsOperation.h"
+#include "LinearAllocator.h"
+#include "PlatformGraphicsContextSkia.h"
+#include "RTree.h"
+#include "SkDevice.h"
+
+#include "wtf/NonCopyingSort.h"
+#include "wtf/HashSet.h"
+#include "wtf/StringHasher.h"
+
+#define NEW_OP(X) new (heap()) GraphicsOperation::X
+
+#define USE_CLIPPING_PAINTER true
+#define MIN_TRACKED_OPAQUE_AREA 750
namespace WebCore {
+static FloatRect approximateTextBounds(size_t numGlyphs,
+ const SkPoint pos[], const SkPaint& paint)
+{
+ if (!numGlyphs || !pos) {
+ return FloatRect();
+ }
+
+ // get glyph position bounds
+ SkScalar minX = pos[0].x();
+ SkScalar maxX = minX;
+ SkScalar minY = pos[0].y();
+ SkScalar maxY = minY;
+ for (size_t i = 1; i < numGlyphs; ++i) {
+ SkScalar x = pos[i].x();
+ SkScalar y = pos[i].y();
+ minX = std::min(minX, x);
+ maxX = std::max(maxX, x);
+ minY = std::min(minY, y);
+ maxY = std::max(maxY, y);
+ }
+
+ // build final rect
+ SkPaint::FontMetrics metrics;
+ SkScalar bufY = paint.getFontMetrics(&metrics);
+ SkScalar bufX = bufY * 2;
+ SkScalar adjY = metrics.fAscent / 2;
+ minY += adjY;
+ maxY += adjY;
+ SkRect rect;
+ rect.set(minX - bufX, minY - bufY, maxX + bufX, maxY + bufY);
+ return rect;
+}
+
+class StateHash {
+public:
+ static unsigned hash(PlatformGraphicsContext::State* const& state)
+ {
+ return StringHasher::hashMemory(state, sizeof(PlatformGraphicsContext::State));
+ }
+
+ static bool equal(PlatformGraphicsContext::State* const& a,
+ PlatformGraphicsContext::State* const& b)
+ {
+ return a && b && !memcmp(a, b, sizeof(PlatformGraphicsContext::State));
+ }
+
+ static const bool safeToCompareToEmptyOrDeleted = false;
+};
+
+class SkPaintHash {
+public:
+ static unsigned hash(const SkPaint* const& paint)
+ {
+ return StringHasher::hashMemory(paint, sizeof(SkPaint));
+ }
+
+ static bool equal(const SkPaint* const& a,
+ const SkPaint* const& b)
+ {
+ return a && b && (*a == *b);
+ }
+
+ static const bool safeToCompareToEmptyOrDeleted = false;
+};
+
+typedef HashSet<PlatformGraphicsContext::State*, StateHash> StateHashSet;
+typedef HashSet<const SkPaint*, SkPaintHash> SkPaintHashSet;
+
+class CanvasState {
+public:
+ CanvasState(CanvasState* parent)
+ : m_parent(parent)
+ , m_isTransparencyLayer(false)
+ {}
+
+ CanvasState(CanvasState* parent, float opacity)
+ : m_parent(parent)
+ , m_isTransparencyLayer(true)
+ , m_opacity(opacity)
+ {}
+
+ ~CanvasState() {
+ ALOGV("Delete %p", this);
+ for (size_t i = 0; i < m_operations.size(); i++)
+ m_operations[i]->~RecordingData();
+ m_operations.clear();
+ }
+
+ bool isParentOf(CanvasState* other) {
+ while (other->m_parent) {
+ if (other->m_parent == this)
+ return true;
+ other = other->m_parent;
+ }
+ return false;
+ }
+
+ void playback(PlatformGraphicsContext* context, size_t fromId, size_t toId) const {
+ ALOGV("playback %p from %d->%d", this, fromId, toId);
+ for (size_t i = 0; i < m_operations.size(); i++) {
+ RecordingData *data = m_operations[i];
+ if (data->m_orderBy < fromId)
+ continue;
+ if (data->m_orderBy > toId)
+ break;
+ ALOGV("Applying operation[%d] %p->%s()", i, data->m_operation,
+ data->m_operation->name());
+ data->m_operation->apply(context);
+ }
+ }
+
+ CanvasState* parent() { return m_parent; }
+
+ void enterState(PlatformGraphicsContext* context) {
+ ALOGV("enterState %p", this);
+ if (m_isTransparencyLayer)
+ context->beginTransparencyLayer(m_opacity);
+ else
+ context->save();
+ }
+
+ void exitState(PlatformGraphicsContext* context) {
+ ALOGV("exitState %p", this);
+ if (m_isTransparencyLayer)
+ context->endTransparencyLayer();
+ else
+ context->restore();
+ }
+
+ void adoptAndAppend(RecordingData* data) {
+ m_operations.append(data);
+ }
+
+ bool isTransparencyLayer() {
+ return m_isTransparencyLayer;
+ }
+
+ void* operator new(size_t size, LinearAllocator* la) {
+ return la->alloc(size);
+ }
+
+private:
+ CanvasState *m_parent;
+ bool m_isTransparencyLayer;
+ float m_opacity;
+ Vector<RecordingData*> m_operations;
+};
+
+class RecordingImpl {
+private:
+ // Careful, ordering matters here. Ordering is first constructed == last destroyed,
+ // so we have to make sure our Heap is the first thing listed so that it is
+ // the last thing destroyed.
+ LinearAllocator m_heap;
+public:
+ RecordingImpl()
+ : m_tree(&m_heap)
+ , m_nodeCount(0)
+ {
+ }
+
+ ~RecordingImpl() {
+ clearStates();
+ clearCanvasStates();
+ clearSkPaints();
+ }
+
+ PlatformGraphicsContext::State* getState(PlatformGraphicsContext::State* inState) {
+ StateHashSet::iterator it = m_states.find(inState);
+ if (it != m_states.end())
+ return (*it);
+ void* buf = heap()->alloc(sizeof(PlatformGraphicsContext::State));
+ PlatformGraphicsContext::State* state = new (buf) PlatformGraphicsContext::State(*inState);
+ m_states.add(state);
+ return state;
+ }
+
+ const SkPaint* getSkPaint(const SkPaint& inPaint) {
+ SkPaintHashSet::iterator it = m_paints.find(&inPaint);
+ if (it != m_paints.end())
+ return (*it);
+ void* buf = heap()->alloc(sizeof(SkPaint));
+ SkPaint* paint = new (buf) SkPaint(inPaint);
+ m_paints.add(paint);
+ return paint;
+ }
+
+ void addCanvasState(CanvasState* state) {
+ m_canvasStates.append(state);
+ }
+
+ void removeCanvasState(const CanvasState* state) {
+ if (m_canvasStates.last() == state)
+ m_canvasStates.removeLast();
+ else {
+ size_t indx = m_canvasStates.find(state);
+ m_canvasStates.remove(indx);
+ }
+ }
+
+ void applyState(PlatformGraphicsContext* context,
+ CanvasState* fromState, size_t fromId,
+ CanvasState* toState, size_t toId) {
+ ALOGV("applyState(%p->%p, %d-%d)", fromState, toState, fromId, toId);
+ if (fromState != toState && fromState) {
+ if (fromState->isParentOf(toState)) {
+ // Going down the tree, playback any parent operations then save
+ // before playing back our current operations
+ applyState(context, fromState, fromId, toState->parent(), toId);
+ toState->enterState(context);
+ } else if (toState->isParentOf(fromState)) {
+ // Going up the tree, pop some states
+ while (fromState != toState) {
+ fromState->exitState(context);
+ fromState = fromState->parent();
+ }
+ } else {
+ // Siblings in the tree
+ fromState->exitState(context);
+ applyState(context, fromState->parent(), fromId, toState, toId);
+ return;
+ }
+ } else if (!fromState) {
+ if (toState->parent())
+ applyState(context, fromState, fromId, toState->parent(), toId);
+ toState->enterState(context);
+ }
+ toState->playback(context, fromId, toId);
+ }
+
+ LinearAllocator* heap() { return &m_heap; }
+
+ RTree::RTree m_tree;
+ int m_nodeCount;
+
+ void dumpMemoryStats() {
+ static const char* PREFIX = " ";
+ ALOGD("Heap:");
+ m_heap.dumpMemoryStats(PREFIX);
+ }
+
+private:
+
+ void clearStates() {
+ StateHashSet::iterator end = m_states.end();
+ for (StateHashSet::iterator it = m_states.begin(); it != end; ++it)
+ (*it)->~State();
+ m_states.clear();
+ }
+
+ void clearSkPaints() {
+ SkPaintHashSet::iterator end = m_paints.end();
+ for (SkPaintHashSet::iterator it = m_paints.begin(); it != end; ++it)
+ (*it)->~SkPaint();
+ m_paints.clear();
+ }
+
+ void clearCanvasStates() {
+ for (size_t i = 0; i < m_canvasStates.size(); i++)
+ m_canvasStates[i]->~CanvasState();
+ m_canvasStates.clear();
+ }
+
+ StateHashSet m_states;
+ SkPaintHashSet m_paints;
+ Vector<CanvasState*> m_canvasStates;
+};
+
+Recording::~Recording()
+{
+ delete m_recording;
+}
+
+static bool CompareRecordingDataOrder(const RecordingData* a, const RecordingData* b)
+{
+ return a->m_orderBy < b->m_orderBy;
+}
+
+static IntRect enclosedIntRect(const FloatRect& rect)
+{
+ float left = ceilf(rect.x());
+ float top = ceilf(rect.y());
+ float width = floorf(rect.maxX()) - left;
+ float height = floorf(rect.maxY()) - top;
+
+ return IntRect(clampToInteger(left), clampToInteger(top),
+ clampToInteger(width), clampToInteger(height));
+}
+
+#if USE_CLIPPING_PAINTER
+class ClippingPainter {
+public:
+ ClippingPainter(RecordingImpl* recording,
+ PlatformGraphicsContextSkia& context,
+ const SkMatrix& initialMatrix,
+ Vector<RecordingData*> &nodes)
+ : m_recording(recording)
+ , m_context(context)
+ , m_initialMatrix(initialMatrix)
+ , m_nodes(nodes)
+ , m_lastOperationId(0)
+ , m_currState(0)
+ {}
+
+ void draw(const SkIRect& bounds) {
+ drawWithClipRecursive(static_cast<int>(m_nodes.size()) - 1, bounds, 0);
+
+ while (m_currState) {
+ m_currState->exitState(&m_context);
+ m_currState = m_currState->parent();
+ }
+ }
+
+private:
+ void drawOperation(RecordingData* node, const SkRegion* uncovered)
+ {
+ GraphicsOperation::Operation* op = node->m_operation;
+ m_recording->applyState(&m_context, m_currState,
+ m_lastOperationId, op->m_canvasState, node->m_orderBy);
+ m_currState = op->m_canvasState;
+ m_lastOperationId = node->m_orderBy;
+
+ // if other opaque operations will cover the current one, clip that area out
+ // (and restore the clip immediately after drawing)
+ if (uncovered) {
+ m_context.save();
+ m_context.canvas()->clipRegion(*uncovered, SkRegion::kIntersect_Op);
+ }
+ op->apply(&(m_context));
+ if (uncovered)
+ m_context.restore();
+ }
+
+ void drawWithClipRecursive(int index, const SkIRect& bounds, const SkRegion* uncovered)
+ {
+ if (index < 0)
+ return;
+ RecordingData* recordingData = m_nodes[index];
+ GraphicsOperation::Operation* op = recordingData->m_operation;
+ if (index != 0) {
+ const IntRect* opaqueRect = op->opaqueRect();
+ if (!opaqueRect || opaqueRect->isEmpty()) {
+ drawWithClipRecursive(index - 1, bounds, uncovered);
+ } else {
+ SkRegion newUncovered;
+ if (uncovered)
+ newUncovered = *uncovered;
+ else
+ newUncovered = SkRegion(bounds);
+
+ SkRect mappedRect = *opaqueRect;
+ m_initialMatrix.mapRect(&mappedRect);
+ newUncovered.op(enclosedIntRect(mappedRect), SkRegion::kDifference_Op);
+ if (!newUncovered.isEmpty())
+ drawWithClipRecursive(index - 1, bounds, &newUncovered);
+ }
+ }
+
+ if (!uncovered || !uncovered->isEmpty())
+ drawOperation(recordingData, uncovered);
+ }
+
+ RecordingImpl* m_recording;
+ PlatformGraphicsContextSkia& m_context;
+ const SkMatrix& m_initialMatrix;
+ const Vector<RecordingData*>& m_nodes;
+ size_t m_lastOperationId;
+ CanvasState* m_currState;
+};
+#endif // USE_CLIPPING_PAINTER
+
+void Recording::draw(SkCanvas* canvas)
+{
+ if (!m_recording) {
+ ALOGW("No recording!");
+ return;
+ }
+ SkRect clip;
+ if (!canvas->getClipBounds(&clip)) {
+ ALOGW("Empty clip!");
+ return;
+ }
+ Vector<RecordingData*> nodes;
+
+ WebCore::IntRect iclip = enclosingIntRect(clip);
+ m_recording->m_tree.search(iclip, nodes);
+
+ size_t count = nodes.size();
+ ALOGV("Drawing %d nodes out of %d", count, m_recording->m_nodeCount);
+ if (count) {
+ int saveCount = canvas->getSaveCount();
+ nonCopyingSort(nodes.begin(), nodes.end(), CompareRecordingDataOrder);
+ PlatformGraphicsContextSkia context(canvas);
+#if USE_CLIPPING_PAINTER
+ if (canvas->getDevice() && canvas->getDevice()->config() != SkBitmap::kNo_Config) {
+ ClippingPainter painter(recording(), context, canvas->getTotalMatrix(), nodes);
+ painter.draw(canvas->getTotalClip().getBounds());
+ } else
+#endif
+ {
+ CanvasState* currState = 0;
+ size_t lastOperationId = 0;
+ for (size_t i = 0; i < count; i++) {
+ GraphicsOperation::Operation* op = nodes[i]->m_operation;
+ m_recording->applyState(&context, currState, lastOperationId,
+ op->m_canvasState, nodes[i]->m_orderBy);
+ currState = op->m_canvasState;
+ lastOperationId = nodes[i]->m_orderBy;
+ ALOGV("apply: %p->%s()", op, op->name());
+ op->apply(&context);
+ }
+ while (currState) {
+ currState->exitState(&context);
+ currState = currState->parent();
+ }
+ }
+ if (saveCount != canvas->getSaveCount()) {
+ ALOGW("Save/restore mismatch! %d vs. %d", saveCount, canvas->getSaveCount());
+ }
+ }
+}
+
+void Recording::setRecording(RecordingImpl* impl)
+{
+ if (m_recording == impl)
+ return;
+ if (m_recording)
+ delete m_recording;
+ m_recording = impl;
+}
+
//**************************************
// PlatformGraphicsContextRecording
//**************************************
-PlatformGraphicsContextRecording::PlatformGraphicsContextRecording(GraphicsOperationCollection* picture)
+PlatformGraphicsContextRecording::PlatformGraphicsContextRecording(Recording* recording)
: PlatformGraphicsContext()
- , mGraphicsOperationCollection(picture)
, mPicture(0)
+ , mRecording(recording)
+ , mOperationState(0)
+ , m_hasText(false)
+ , m_isEmpty(true)
+ , m_canvasProxy(this)
{
+ ALOGV("RECORDING: begin");
+ if (mRecording)
+ mRecording->setRecording(new RecordingImpl());
+ mMatrixStack.append(SkMatrix::I());
+ mCurrentMatrix = &(mMatrixStack.last());
+ pushStateOperation(new (heap()) CanvasState(0));
}
-bool PlatformGraphicsContextRecording::isPaintingDisabled()
+PlatformGraphicsContextRecording::~PlatformGraphicsContextRecording()
{
- return !mGraphicsOperationCollection;
+ ALOGV("RECORDING: end");
+ IF_ALOGV()
+ mRecording->recording()->dumpMemoryStats();
}
-SkCanvas* PlatformGraphicsContextRecording::recordingCanvas()
+bool PlatformGraphicsContextRecording::isPaintingDisabled()
{
- SkSafeUnref(mPicture);
- mPicture = new SkPicture();
- return mPicture->beginRecording(0, 0, 0);
+ return !mRecording;
}
-void PlatformGraphicsContextRecording::endRecording(int type)
+SkCanvas* PlatformGraphicsContextRecording::recordingCanvas()
{
- if (!mPicture)
- return;
- mPicture->endRecording();
- GraphicsOperation::DrawComplexText* text = new GraphicsOperation::DrawComplexText(mPicture);
- mGraphicsOperationCollection->append(text);
- mPicture = 0;
+ m_hasText = true;
+ return &m_canvasProxy;
}
-
//**************************************
// State management
//**************************************
void PlatformGraphicsContextRecording::beginTransparencyLayer(float opacity)
{
- mGraphicsOperationCollection->append(new GraphicsOperation::BeginTransparencyLayer(opacity));
+ CanvasState* parent = mRecordingStateStack.last().mCanvasState;
+ pushStateOperation(new (heap()) CanvasState(parent, opacity));
+ mRecordingStateStack.last().disableOpaqueTracking();
}
void PlatformGraphicsContextRecording::endTransparencyLayer()
{
- mGraphicsOperationCollection->append(new GraphicsOperation::EndTransparencyLayer());
+ popStateOperation();
}
void PlatformGraphicsContextRecording::save()
{
PlatformGraphicsContext::save();
- mGraphicsOperationCollection->append(new GraphicsOperation::Save());
+ CanvasState* parent = mRecordingStateStack.last().mCanvasState;
+ pushStateOperation(new (heap()) CanvasState(parent));
+ pushMatrix();
}
void PlatformGraphicsContextRecording::restore()
{
PlatformGraphicsContext::restore();
- mGraphicsOperationCollection->append(new GraphicsOperation::Restore());
+ popMatrix();
+ popStateOperation();
}
//**************************************
@@ -79,86 +559,98 @@ void PlatformGraphicsContextRecording::restore()
void PlatformGraphicsContextRecording::setAlpha(float alpha)
{
PlatformGraphicsContext::setAlpha(alpha);
- mGraphicsOperationCollection->append(new GraphicsOperation::SetAlpha(alpha));
+ mOperationState = 0;
}
void PlatformGraphicsContextRecording::setCompositeOperation(CompositeOperator op)
{
PlatformGraphicsContext::setCompositeOperation(op);
- mGraphicsOperationCollection->append(new GraphicsOperation::SetCompositeOperation(op));
+ mOperationState = 0;
}
-void PlatformGraphicsContextRecording::setFillColor(const Color& c)
+bool PlatformGraphicsContextRecording::setFillColor(const Color& c)
{
- PlatformGraphicsContext::setFillColor(c);
- mGraphicsOperationCollection->append(new GraphicsOperation::SetFillColor(c));
+ if (PlatformGraphicsContext::setFillColor(c)) {
+ mOperationState = 0;
+ return true;
+ }
+ return false;
}
-void PlatformGraphicsContextRecording::setFillShader(SkShader* fillShader)
+bool PlatformGraphicsContextRecording::setFillShader(SkShader* fillShader)
{
- PlatformGraphicsContext::setFillShader(fillShader);
- mGraphicsOperationCollection->append(new GraphicsOperation::SetFillShader(fillShader));
+ if (PlatformGraphicsContext::setFillShader(fillShader)) {
+ mOperationState = 0;
+ return true;
+ }
+ return false;
}
void PlatformGraphicsContextRecording::setLineCap(LineCap cap)
{
PlatformGraphicsContext::setLineCap(cap);
- mGraphicsOperationCollection->append(new GraphicsOperation::SetLineCap(cap));
+ mOperationState = 0;
}
void PlatformGraphicsContextRecording::setLineDash(const DashArray& dashes, float dashOffset)
{
PlatformGraphicsContext::setLineDash(dashes, dashOffset);
- mGraphicsOperationCollection->append(new GraphicsOperation::SetLineDash(dashes, dashOffset));
+ mOperationState = 0;
}
void PlatformGraphicsContextRecording::setLineJoin(LineJoin join)
{
PlatformGraphicsContext::setLineJoin(join);
- mGraphicsOperationCollection->append(new GraphicsOperation::SetLineJoin(join));
+ mOperationState = 0;
}
void PlatformGraphicsContextRecording::setMiterLimit(float limit)
{
PlatformGraphicsContext::setMiterLimit(limit);
- mGraphicsOperationCollection->append(new GraphicsOperation::SetMiterLimit(limit));
+ mOperationState = 0;
}
void PlatformGraphicsContextRecording::setShadow(int radius, int dx, int dy, SkColor c)
{
PlatformGraphicsContext::setShadow(radius, dx, dy, c);
- mGraphicsOperationCollection->append(new GraphicsOperation::SetShadow(radius, dx, dy, c));
+ mOperationState = 0;
}
void PlatformGraphicsContextRecording::setShouldAntialias(bool useAA)
{
m_state->useAA = useAA;
PlatformGraphicsContext::setShouldAntialias(useAA);
- mGraphicsOperationCollection->append(new GraphicsOperation::SetShouldAntialias(useAA));
+ mOperationState = 0;
}
-void PlatformGraphicsContextRecording::setStrokeColor(const Color& c)
+bool PlatformGraphicsContextRecording::setStrokeColor(const Color& c)
{
- PlatformGraphicsContext::setStrokeColor(c);
- mGraphicsOperationCollection->append(new GraphicsOperation::SetStrokeColor(c));
+ if (PlatformGraphicsContext::setStrokeColor(c)) {
+ mOperationState = 0;
+ return true;
+ }
+ return false;
}
-void PlatformGraphicsContextRecording::setStrokeShader(SkShader* strokeShader)
+bool PlatformGraphicsContextRecording::setStrokeShader(SkShader* strokeShader)
{
- PlatformGraphicsContext::setStrokeShader(strokeShader);
- mGraphicsOperationCollection->append(new GraphicsOperation::SetStrokeShader(strokeShader));
+ if (PlatformGraphicsContext::setStrokeShader(strokeShader)) {
+ mOperationState = 0;
+ return true;
+ }
+ return false;
}
void PlatformGraphicsContextRecording::setStrokeStyle(StrokeStyle style)
{
PlatformGraphicsContext::setStrokeStyle(style);
- mGraphicsOperationCollection->append(new GraphicsOperation::SetStrokeStyle(style));
+ mOperationState = 0;
}
void PlatformGraphicsContextRecording::setStrokeThickness(float f)
{
PlatformGraphicsContext::setStrokeThickness(f);
- mGraphicsOperationCollection->append(new GraphicsOperation::SetStrokeThickness(f));
+ mOperationState = 0;
}
//**************************************
@@ -167,32 +659,32 @@ void PlatformGraphicsContextRecording::setStrokeThickness(float f)
void PlatformGraphicsContextRecording::concatCTM(const AffineTransform& affine)
{
- mCurrentMatrix.preConcat(affine);
- mGraphicsOperationCollection->append(new GraphicsOperation::ConcatCTM(affine));
+ mCurrentMatrix->preConcat(affine);
+ appendStateOperation(NEW_OP(ConcatCTM)(affine));
}
void PlatformGraphicsContextRecording::rotate(float angleInRadians)
{
float value = angleInRadians * (180.0f / 3.14159265f);
- mCurrentMatrix.preRotate(SkFloatToScalar(value));
- mGraphicsOperationCollection->append(new GraphicsOperation::Rotate(angleInRadians));
+ mCurrentMatrix->preRotate(SkFloatToScalar(value));
+ appendStateOperation(NEW_OP(Rotate)(angleInRadians));
}
void PlatformGraphicsContextRecording::scale(const FloatSize& size)
{
- mCurrentMatrix.preScale(SkFloatToScalar(size.width()), SkFloatToScalar(size.height()));
- mGraphicsOperationCollection->append(new GraphicsOperation::Scale(size));
+ mCurrentMatrix->preScale(SkFloatToScalar(size.width()), SkFloatToScalar(size.height()));
+ appendStateOperation(NEW_OP(Scale)(size));
}
void PlatformGraphicsContextRecording::translate(float x, float y)
{
- mCurrentMatrix.preTranslate(SkFloatToScalar(x), SkFloatToScalar(y));
- mGraphicsOperationCollection->append(new GraphicsOperation::Translate(x, y));
+ mCurrentMatrix->preTranslate(SkFloatToScalar(x), SkFloatToScalar(y));
+ appendStateOperation(NEW_OP(Translate)(x, y));
}
const SkMatrix& PlatformGraphicsContextRecording::getTotalMatrix()
{
- return mCurrentMatrix;
+ return *mCurrentMatrix;
}
//**************************************
@@ -202,50 +694,65 @@ const SkMatrix& PlatformGraphicsContextRecording::getTotalMatrix()
void PlatformGraphicsContextRecording::addInnerRoundedRectClip(const IntRect& rect,
int thickness)
{
- mGraphicsOperationCollection->append(new GraphicsOperation::InnerRoundedRectClip(rect, thickness));
+ mRecordingStateStack.last().disableOpaqueTracking();
+ appendStateOperation(NEW_OP(InnerRoundedRectClip)(rect, thickness));
}
void PlatformGraphicsContextRecording::canvasClip(const Path& path)
{
+ mRecordingStateStack.last().disableOpaqueTracking();
clip(path);
}
-void PlatformGraphicsContextRecording::clip(const FloatRect& rect)
+bool PlatformGraphicsContextRecording::clip(const FloatRect& rect)
{
- mGraphicsOperationCollection->append(new GraphicsOperation::Clip(rect));
+ clipState(rect);
+ appendStateOperation(NEW_OP(Clip)(rect));
+ return true;
}
-void PlatformGraphicsContextRecording::clip(const Path& path)
+bool PlatformGraphicsContextRecording::clip(const Path& path)
{
- mGraphicsOperationCollection->append(new GraphicsOperation::ClipPath(path));
+ mRecordingStateStack.last().disableOpaqueTracking();
+ clipState(path.boundingRect());
+ appendStateOperation(NEW_OP(ClipPath)(path));
+ return true;
}
-void PlatformGraphicsContextRecording::clipConvexPolygon(size_t numPoints,
+bool PlatformGraphicsContextRecording::clipConvexPolygon(size_t numPoints,
const FloatPoint*, bool antialias)
{
// TODO
+ return true;
}
-void PlatformGraphicsContextRecording::clipOut(const IntRect& r)
+bool PlatformGraphicsContextRecording::clipOut(const IntRect& r)
{
- mGraphicsOperationCollection->append(new GraphicsOperation::ClipOut(r));
+ mRecordingStateStack.last().disableOpaqueTracking();
+ appendStateOperation(NEW_OP(ClipOut)(r));
+ return true;
}
-void PlatformGraphicsContextRecording::clipOut(const Path& path)
+bool PlatformGraphicsContextRecording::clipOut(const Path& path)
{
- mGraphicsOperationCollection->append(new GraphicsOperation::ClipPath(path, true));
+ mRecordingStateStack.last().disableOpaqueTracking();
+ appendStateOperation(NEW_OP(ClipPath)(path, true));
+ return true;
}
-void PlatformGraphicsContextRecording::clipPath(const Path& pathToClip, WindRule clipRule)
+bool PlatformGraphicsContextRecording::clipPath(const Path& pathToClip, WindRule clipRule)
{
- GraphicsOperation::ClipPath* operation = new GraphicsOperation::ClipPath(pathToClip);
+ mRecordingStateStack.last().disableOpaqueTracking();
+ clipState(pathToClip.boundingRect());
+ GraphicsOperation::ClipPath* operation = NEW_OP(ClipPath)(pathToClip);
operation->setWindRule(clipRule);
- mGraphicsOperationCollection->append(operation);
+ appendStateOperation(operation);
+ return true;
}
void PlatformGraphicsContextRecording::clearRect(const FloatRect& rect)
{
- mGraphicsOperationCollection->append(new GraphicsOperation::ClearRect(rect));
+ appendDrawingOperation(NEW_OP(ClearRect)(rect), rect);
}
//**************************************
@@ -256,33 +763,48 @@ void PlatformGraphicsContextRecording::drawBitmapPattern(
const SkBitmap& bitmap, const SkMatrix& matrix,
CompositeOperator compositeOp, const FloatRect& destRect)
{
- mGraphicsOperationCollection->append(new GraphicsOperation::DrawBitmapPattern(bitmap, matrix, compositeOp, destRect));
+ appendDrawingOperation(
+ NEW_OP(DrawBitmapPattern)(bitmap, matrix, compositeOp, destRect),
+ destRect);
}
void PlatformGraphicsContextRecording::drawBitmapRect(const SkBitmap& bitmap,
const SkIRect* src, const SkRect& dst,
CompositeOperator op)
{
- mGraphicsOperationCollection->append(new GraphicsOperation::DrawBitmapRect(bitmap, *src, dst, op));
+ appendDrawingOperation(NEW_OP(DrawBitmapRect)(bitmap, *src, dst, op), dst);
}
void PlatformGraphicsContextRecording::drawConvexPolygon(size_t numPoints,
const FloatPoint* points,
bool shouldAntialias)
{
- // TODO
+ if (numPoints < 1) return;
+ if (numPoints != 4) {
+ // TODO: Build a path and call draw on that (webkit currently never calls this)
+ ALOGW("drawConvexPolygon with numPoints != 4 is not supported!");
+ return;
+ }
+ FloatRect bounds;
+ bounds.fitToPoints(points[0], points[1], points[2], points[3]);
+ appendDrawingOperation(NEW_OP(DrawConvexPolygonQuad)(points, shouldAntialias), bounds);
}
void PlatformGraphicsContextRecording::drawEllipse(const IntRect& rect)
{
- mGraphicsOperationCollection->append(new GraphicsOperation::DrawEllipse(rect));
+ appendDrawingOperation(NEW_OP(DrawEllipse)(rect), rect);
}
void PlatformGraphicsContextRecording::drawFocusRing(const Vector<IntRect>& rects,
- int /* width */, int /* offset */,
+ int width, int offset,
const Color& color)
{
- // TODO
+ if (!rects.size())
+ return;
+ IntRect bounds = rects[0];
+ for (size_t i = 1; i < rects.size(); i++)
+ bounds.unite(rects[i]);
+ appendDrawingOperation(NEW_OP(DrawFocusRing)(rects, width, offset, color), bounds);
}
void PlatformGraphicsContextRecording::drawHighlightForText(
@@ -307,41 +829,47 @@ void PlatformGraphicsContextRecording::drawHighlightForText(
void PlatformGraphicsContextRecording::drawLine(const IntPoint& point1,
const IntPoint& point2)
{
- mGraphicsOperationCollection->append(new GraphicsOperation::DrawLine(point1, point2));
+ FloatRect bounds = FloatQuad(point1, point1, point2, point2).boundingBox();
+ float width = m_state->strokeThickness;
+ if (!width) width = 1;
+ bounds.inflate(width);
+ appendDrawingOperation(NEW_OP(DrawLine)(point1, point2), bounds);
}
void PlatformGraphicsContextRecording::drawLineForText(const FloatPoint& pt, float width)
{
- mGraphicsOperationCollection->append(new GraphicsOperation::DrawLineForText(pt, width));
+ FloatRect bounds(pt.x(), pt.y(), width, m_state->strokeThickness);
+ appendDrawingOperation(NEW_OP(DrawLineForText)(pt, width), bounds);
}
void PlatformGraphicsContextRecording::drawLineForTextChecking(const FloatPoint& pt,
float width, GraphicsContext::TextCheckingLineStyle lineStyle)
{
- mGraphicsOperationCollection->append(new GraphicsOperation::DrawLineForTextChecking(pt, width, lineStyle));
+ FloatRect bounds(pt.x(), pt.y(), width, m_state->strokeThickness);
+ appendDrawingOperation(NEW_OP(DrawLineForTextChecking)(pt, width, lineStyle), bounds);
}
void PlatformGraphicsContextRecording::drawRect(const IntRect& rect)
{
- mGraphicsOperationCollection->append(new GraphicsOperation::DrawRect(rect));
+ appendDrawingOperation(NEW_OP(DrawRect)(rect), rect);
}
void PlatformGraphicsContextRecording::fillPath(const Path& pathToFill, WindRule fillRule)
{
- mGraphicsOperationCollection->append(new GraphicsOperation::FillPath(pathToFill, fillRule));
+ appendDrawingOperation(NEW_OP(FillPath)(pathToFill, fillRule), pathToFill.boundingRect());
}
void PlatformGraphicsContextRecording::fillRect(const FloatRect& rect)
{
- mGraphicsOperationCollection->append(new GraphicsOperation::FillRect(rect));
+ appendDrawingOperation(NEW_OP(FillRect)(rect), rect);
}
void PlatformGraphicsContextRecording::fillRect(const FloatRect& rect,
const Color& color)
{
- GraphicsOperation::FillRect* operation = new GraphicsOperation::FillRect(rect);
+ GraphicsOperation::FillRect* operation = NEW_OP(FillRect)(rect);
operation->setColor(color);
- mGraphicsOperationCollection->append(operation);
+ appendDrawingOperation(operation, rect);
}
void PlatformGraphicsContextRecording::fillRoundedRect(
@@ -349,25 +877,197 @@ void PlatformGraphicsContextRecording::fillRoundedRect(
const IntSize& bottomLeft, const IntSize& bottomRight,
const Color& color)
{
- mGraphicsOperationCollection->append(new GraphicsOperation::FillRoundedRect(rect, topLeft,
- topRight, bottomLeft, bottomRight, color));
+ appendDrawingOperation(NEW_OP(FillRoundedRect)(rect, topLeft,
+ topRight, bottomLeft, bottomRight, color), rect);
}
void PlatformGraphicsContextRecording::strokeArc(const IntRect& r, int startAngle,
int angleSpan)
{
- mGraphicsOperationCollection->append(new GraphicsOperation::StrokeArc(r, startAngle, angleSpan));
+ appendDrawingOperation(NEW_OP(StrokeArc)(r, startAngle, angleSpan), r);
}
void PlatformGraphicsContextRecording::strokePath(const Path& pathToStroke)
{
- mGraphicsOperationCollection->append(new GraphicsOperation::StrokePath(pathToStroke));
+ appendDrawingOperation(NEW_OP(StrokePath)(pathToStroke), pathToStroke.boundingRect());
}
void PlatformGraphicsContextRecording::strokeRect(const FloatRect& rect, float lineWidth)
{
- mGraphicsOperationCollection->append(new GraphicsOperation::StrokeRect(rect, lineWidth));
+ FloatRect bounds = rect;
+ bounds.inflate(lineWidth);
+ appendDrawingOperation(NEW_OP(StrokeRect)(rect, lineWidth), bounds);
+}
+
+void PlatformGraphicsContextRecording::drawPosText(const void* inText, size_t byteLength,
+ const SkPoint inPos[], const SkPaint& inPaint)
+{
+ if (inPaint.getTextEncoding() != SkPaint::kGlyphID_TextEncoding) {
+ ALOGE("Unsupported text encoding! %d", inPaint.getTextEncoding());
+ return;
+ }
+ FloatRect bounds = approximateTextBounds(byteLength / sizeof(uint16_t), inPos, inPaint);
+ const SkPaint* paint = mRecording->recording()->getSkPaint(inPaint);
+ size_t posSize = sizeof(SkPoint) * paint->countText(inText, byteLength);
+ void* text = heap()->alloc(byteLength);
+ SkPoint* pos = (SkPoint*) heap()->alloc(posSize);
+ memcpy(text, inText, byteLength);
+ memcpy(pos, inPos, posSize);
+ appendDrawingOperation(NEW_OP(DrawPosText)(text, byteLength, pos, paint), bounds);
+}
+
+void PlatformGraphicsContextRecording::drawMediaButton(const IntRect& rect, RenderSkinMediaButton::MediaButton buttonType,
+ bool translucent, bool drawBackground,
+ const IntRect& thumb)
+{
+ appendDrawingOperation(NEW_OP(DrawMediaButton)(rect, buttonType,
+ translucent, drawBackground, thumb), rect);
+}
+
+void PlatformGraphicsContextRecording::clipState(const FloatRect& clip)
+{
+ if (mRecordingStateStack.size()) {
+ SkRect mapBounds;
+ mCurrentMatrix->mapRect(&mapBounds, clip);
+ mRecordingStateStack.last().clip(mapBounds);
+ }
+}
+
+void PlatformGraphicsContextRecording::pushStateOperation(CanvasState* canvasState)
+{
+ ALOGV("RECORDING: pushStateOperation: %p(isLayer=%d)", canvasState, canvasState->isTransparencyLayer());
+
+ RecordingState* parent = mRecordingStateStack.isEmpty() ? 0 : &(mRecordingStateStack.last());
+ mRecordingStateStack.append(RecordingState(canvasState, parent));
+ mRecording->recording()->addCanvasState(canvasState);
+}
+
+void PlatformGraphicsContextRecording::popStateOperation()
+{
+ RecordingState state = mRecordingStateStack.last();
+ mRecordingStateStack.removeLast();
+ mOperationState = 0;
+ if (!state.mHasDrawing) {
+ ALOGV("RECORDING: popStateOperation is deleting %p(isLayer=%d)",
+ state.mCanvasState, state.mCanvasState->isTransparencyLayer());
+ mRecording->recording()->removeCanvasState(state.mCanvasState);
+ state.mCanvasState->~CanvasState();
+ heap()->rewindIfLastAlloc(state.mCanvasState, sizeof(CanvasState));
+ } else {
+ ALOGV("RECORDING: popStateOperation: %p(isLayer=%d)",
+ state.mCanvasState, state.mCanvasState->isTransparencyLayer());
+ // Make sure we propagate drawing upwards so we don't delete our parent
+ mRecordingStateStack.last().mHasDrawing = true;
+ }
+}
+
+void PlatformGraphicsContextRecording::pushMatrix()
+{
+ mMatrixStack.append(mMatrixStack.last());
+ mCurrentMatrix = &(mMatrixStack.last());
+}
+
+void PlatformGraphicsContextRecording::popMatrix()
+{
+ mMatrixStack.removeLast();
+ mCurrentMatrix = &(mMatrixStack.last());
}
+IntRect PlatformGraphicsContextRecording::calculateFinalBounds(FloatRect bounds)
+{
+ if (bounds.isEmpty() && mRecordingStateStack.last().mHasClip) {
+ ALOGV("Empty bounds, but has clip so using that");
+ return enclosingIntRect(mRecordingStateStack.last().mBounds);
+ }
+ if (m_gc->hasShadow()) {
+ const ShadowRec& shadow = m_state->shadow;
+ if (shadow.blur > 0)
+ bounds.inflate(ceilf(shadow.blur));
+ bounds.setWidth(bounds.width() + abs(shadow.dx));
+ bounds.setHeight(bounds.height() + abs(shadow.dy));
+ if (shadow.dx < 0)
+ bounds.move(shadow.dx, 0);
+ if (shadow.dy < 0)
+ bounds.move(0, shadow.dy);
+ // Add a bit extra to deal with rounding and blurring
+ bounds.inflate(4);
+ }
+ if (m_state->strokeStyle != NoStroke)
+ bounds.inflate(std::min(1.0f, m_state->strokeThickness));
+ SkRect translated;
+ mCurrentMatrix->mapRect(&translated, bounds);
+ FloatRect ftrect = translated;
+ if (mRecordingStateStack.last().mHasClip
+ && !translated.intersect(mRecordingStateStack.last().mBounds)) {
+ ALOGV("Operation bounds=" FLOAT_RECT_FORMAT " clipped out by clip=" FLOAT_RECT_FORMAT,
+ FLOAT_RECT_ARGS(ftrect), FLOAT_RECT_ARGS(mRecordingStateStack.last().mBounds));
+ return IntRect();
+ }
+ return enclosingIntRect(translated);
+}
+
+IntRect PlatformGraphicsContextRecording::calculateCoveredBounds(FloatRect bounds)
+{
+ if (mRecordingStateStack.last().mOpaqueTrackingDisabled
+ || m_state->alpha != 1.0f
+ || (m_state->mode != SkXfermode::kSrc_Mode && m_state->mode != SkXfermode::kSrcOver_Mode)
+ || !mCurrentMatrix->rectStaysRect()) {
+ return IntRect();
+ }
+
+ SkRect translated;
+ mCurrentMatrix->mapRect(&translated, bounds);
+ FloatRect ftrect = translated;
+ if (mRecordingStateStack.last().mHasClip
+ && !translated.intersect(mRecordingStateStack.last().mBounds)) {
+ ALOGV("Operation opaque area=" FLOAT_RECT_FORMAT " clipped out by clip=" FLOAT_RECT_FORMAT,
+ FLOAT_RECT_ARGS(ftrect), FLOAT_RECT_ARGS(mRecordingStateStack.last().mBounds));
+ return IntRect();
+ }
+ return enclosedIntRect(translated);
+}
+
+void PlatformGraphicsContextRecording::appendDrawingOperation(
+ GraphicsOperation::Operation* operation, const FloatRect& untranslatedBounds)
+{
+ m_isEmpty = false;
+ RecordingState& state = mRecordingStateStack.last();
+ state.mHasDrawing = true;
+ if (!mOperationState)
+ mOperationState = mRecording->recording()->getState(m_state);
+ operation->m_state = mOperationState;
+ operation->m_canvasState = state.mCanvasState;
+
+ WebCore::IntRect ibounds = calculateFinalBounds(untranslatedBounds);
+ if (ibounds.isEmpty()) {
+ ALOGV("RECORDING: Operation %s() was clipped out", operation->name());
+ operation->~Operation();
+ return;
+ }
+#if USE_CLIPPING_PAINTER
+ if (operation->isOpaque()
+ && !untranslatedBounds.isEmpty()
+ && (untranslatedBounds.width() * untranslatedBounds.height() > MIN_TRACKED_OPAQUE_AREA)) {
+ // if the operation maps to an opaque rect, record the area it will cover
+ operation->setOpaqueRect(calculateCoveredBounds(untranslatedBounds));
+ }
+#endif
+ ALOGV("RECORDING: appendOperation %p->%s() bounds " INT_RECT_FORMAT, operation, operation->name(),
+ INT_RECT_ARGS(ibounds));
+ RecordingData* data = new (heap()) RecordingData(operation, mRecording->recording()->m_nodeCount++);
+ mRecording->recording()->m_tree.insert(ibounds, data);
+}
+
+void PlatformGraphicsContextRecording::appendStateOperation(GraphicsOperation::Operation* operation)
+{
+ ALOGV("RECORDING: appendOperation %p->%s()", operation, operation->name());
+ RecordingData* data = new (heap()) RecordingData(operation, mRecording->recording()->m_nodeCount++);
+ mRecordingStateStack.last().mCanvasState->adoptAndAppend(data);
+}
+
+LinearAllocator* PlatformGraphicsContextRecording::heap()
+{
+ return mRecording->recording()->heap();
+}
} // WebCore
diff --git a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.h b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.h
index ebb0075..061ee0e 100644
--- a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.h
+++ b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.h
@@ -28,21 +28,42 @@
#include "PlatformGraphicsContext.h"
+#include "RecordingContextCanvasProxy.h"
+#include "SkRefCnt.h"
+
namespace WebCore {
-class GraphicsOperationCollection;
+namespace GraphicsOperation {
+class Operation;
+}
+
+class CanvasState;
+class LinearAllocator;
+class RecordingImpl;
+class PlatformGraphicsContextSkia;
+class RecordingData;
+
+class Recording : public SkRefCnt {
+public:
+ Recording()
+ : m_recording(0)
+ {}
+ ~Recording();
+
+ void draw(SkCanvas* canvas);
+ void setRecording(RecordingImpl* impl);
+ RecordingImpl* recording() { return m_recording; }
+
+private:
+ RecordingImpl* m_recording;
+};
class PlatformGraphicsContextRecording : public PlatformGraphicsContext {
public:
- PlatformGraphicsContextRecording(GraphicsOperationCollection* picture);
- virtual ~PlatformGraphicsContextRecording() {}
+ PlatformGraphicsContextRecording(Recording* picture);
+ virtual ~PlatformGraphicsContextRecording();
virtual bool isPaintingDisabled();
- virtual SkCanvas* getCanvas() { return 0; }
-
- GraphicsOperationCollection* mGraphicsOperationCollection;
- SkMatrix mCurrentMatrix;
virtual SkCanvas* recordingCanvas();
- virtual void endRecording(int type = 0);
virtual ContextType type() { return RecordingContext; }
@@ -55,16 +76,16 @@ public:
// State values
virtual void setAlpha(float alpha);
virtual void setCompositeOperation(CompositeOperator op);
- virtual void setFillColor(const Color& c);
- virtual void setFillShader(SkShader* fillShader);
+ virtual bool setFillColor(const Color& c);
+ virtual bool setFillShader(SkShader* fillShader);
virtual void setLineCap(LineCap cap);
virtual void setLineDash(const DashArray& dashes, float dashOffset);
virtual void setLineJoin(LineJoin join);
virtual void setMiterLimit(float limit);
virtual void setShadow(int radius, int dx, int dy, SkColor c);
virtual void setShouldAntialias(bool useAA);
- virtual void setStrokeColor(const Color& c);
- virtual void setStrokeShader(SkShader* strokeShader);
+ virtual bool setStrokeColor(const Color& c);
+ virtual bool setStrokeShader(SkShader* strokeShader);
virtual void setStrokeStyle(StrokeStyle style);
virtual void setStrokeThickness(float f);
@@ -78,19 +99,20 @@ public:
// Clipping
virtual void addInnerRoundedRectClip(const IntRect& rect, int thickness);
virtual void canvasClip(const Path& path);
- virtual void clip(const FloatRect& rect);
- virtual void clip(const Path& path);
- virtual void clipConvexPolygon(size_t numPoints, const FloatPoint*, bool antialias);
- virtual void clipOut(const IntRect& r);
- virtual void clipOut(const Path& p);
- virtual void clipPath(const Path& pathToClip, WindRule clipRule);
+ virtual bool clip(const FloatRect& rect);
+ virtual bool clip(const Path& path);
+ virtual bool clipConvexPolygon(size_t numPoints, const FloatPoint*, bool antialias);
+ virtual bool clipOut(const IntRect& r);
+ virtual bool clipOut(const Path& p);
+ virtual bool clipPath(const Path& pathToClip, WindRule clipRule);
+ virtual SkIRect getTotalClipBounds() { return enclosingIntRect(mRecordingStateStack.last().mBounds); }
// Drawing
virtual void clearRect(const FloatRect& rect);
virtual void drawBitmapPattern(const SkBitmap& bitmap, const SkMatrix& matrix,
CompositeOperator compositeOp, const FloatRect& destRect);
virtual void drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src,
- const SkRect& dst, CompositeOperator op);
+ const SkRect& dst, CompositeOperator op = CompositeSourceOver);
virtual void drawConvexPolygon(size_t numPoints, const FloatPoint* points,
bool shouldAntialias);
virtual void drawEllipse(const IntRect& rect);
@@ -103,7 +125,7 @@ public:
virtual void drawLine(const IntPoint& point1, const IntPoint& point2);
virtual void drawLineForText(const FloatPoint& pt, float width);
virtual void drawLineForTextChecking(const FloatPoint& pt, float width,
- GraphicsContext::TextCheckingLineStyle);
+ GraphicsContext::TextCheckingLineStyle);
virtual void drawRect(const IntRect& rect);
virtual void fillPath(const Path& pathToFill, WindRule fillRule);
virtual void fillRect(const FloatRect& rect);
@@ -115,13 +137,78 @@ public:
virtual void strokePath(const Path& pathToStroke);
virtual void strokeRect(const FloatRect& rect, float lineWidth);
+ virtual void drawPosText(const void* text, size_t byteLength,
+ const SkPoint pos[], const SkPaint& paint);
+ virtual void drawMediaButton(const IntRect& rect, RenderSkinMediaButton::MediaButton buttonType,
+ bool translucent = false, bool drawBackground = true,
+ const IntRect& thumb = IntRect());
+
+ bool hasText() { return m_hasText; }
+ bool isEmpty() { return m_isEmpty; }
private:
virtual bool shadowsIgnoreTransforms() const {
return false;
}
+ void clipState(const FloatRect& clip);
+ void appendDrawingOperation(GraphicsOperation::Operation* operation, const FloatRect& bounds);
+ void appendStateOperation(GraphicsOperation::Operation* operation);
+ void pushStateOperation(CanvasState* canvasState);
+ void popStateOperation();
+ void pushMatrix();
+ void popMatrix();
+ IntRect calculateFinalBounds(FloatRect bounds);
+ IntRect calculateCoveredBounds(FloatRect bounds);
+ LinearAllocator* heap();
+
SkPicture* mPicture;
+ SkMatrix* mCurrentMatrix;
+
+ Recording* mRecording;
+ class RecordingState {
+ public:
+ RecordingState(CanvasState* state, const RecordingState* parent)
+ : mCanvasState(state)
+ , mHasDrawing(false)
+ , mHasClip(parent ? parent->mHasClip : false)
+ , mOpaqueTrackingDisabled(parent ? parent->mOpaqueTrackingDisabled : false)
+ , mBounds(parent ? parent->mBounds : FloatRect())
+ {}
+
+ RecordingState(const RecordingState& other)
+ : mCanvasState(other.mCanvasState)
+ , mHasDrawing(other.mHasDrawing)
+ , mHasClip(other.mHasClip)
+ , mOpaqueTrackingDisabled(other.mOpaqueTrackingDisabled)
+ , mBounds(other.mBounds)
+ {}
+
+ void disableOpaqueTracking() { mOpaqueTrackingDisabled = true; }
+
+ void clip(const FloatRect& rect)
+ {
+ if (mHasClip)
+ mBounds.intersect(rect);
+ else {
+ mBounds = rect;
+ mHasClip = true;
+ }
+ }
+
+ CanvasState* mCanvasState;
+ bool mHasDrawing;
+ bool mHasClip;
+ bool mOpaqueTrackingDisabled;
+ FloatRect mBounds;
+ };
+ Vector<RecordingState> mRecordingStateStack;
+ Vector<SkMatrix> mMatrixStack;
+ State* mOperationState;
+
+ bool m_hasText;
+ bool m_isEmpty;
+ RecordingContextCanvasProxy m_canvasProxy;
};
}
diff --git a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextSkia.cpp b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextSkia.cpp
index f00bb02..fcd9ade 100644
--- a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextSkia.cpp
+++ b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextSkia.cpp
@@ -174,43 +174,45 @@ void PlatformGraphicsContextSkia::canvasClip(const Path& path)
clip(path);
}
-void PlatformGraphicsContextSkia::clip(const FloatRect& rect)
+bool PlatformGraphicsContextSkia::clip(const FloatRect& rect)
{
- mCanvas->clipRect(rect);
+ return mCanvas->clipRect(rect);
}
-void PlatformGraphicsContextSkia::clip(const Path& path)
+bool PlatformGraphicsContextSkia::clip(const Path& path)
{
- mCanvas->clipPath(*path.platformPath(), SkRegion::kIntersect_Op, true);
+ return mCanvas->clipPath(*path.platformPath(), SkRegion::kIntersect_Op, true);
}
-void PlatformGraphicsContextSkia::clipConvexPolygon(size_t numPoints,
+bool PlatformGraphicsContextSkia::clipConvexPolygon(size_t numPoints,
const FloatPoint*, bool antialias)
{
if (numPoints <= 1)
- return;
+ return true;
// This is only used if HAVE_PATH_BASED_BORDER_RADIUS_DRAWING is defined
// in RenderObject.h which it isn't for us. TODO: Support that :)
+ return true;
}
-void PlatformGraphicsContextSkia::clipOut(const IntRect& r)
+bool PlatformGraphicsContextSkia::clipOut(const IntRect& r)
{
- mCanvas->clipRect(r, SkRegion::kDifference_Op);
+ return mCanvas->clipRect(r, SkRegion::kDifference_Op);
}
-void PlatformGraphicsContextSkia::clipOut(const Path& path)
+bool PlatformGraphicsContextSkia::clipOut(const Path& path)
{
- mCanvas->clipPath(*path.platformPath(), SkRegion::kDifference_Op);
+ return mCanvas->clipPath(*path.platformPath(), SkRegion::kDifference_Op);
}
-void PlatformGraphicsContextSkia::clipPath(const Path& pathToClip, WindRule clipRule)
+bool PlatformGraphicsContextSkia::clipPath(const Path& pathToClip, WindRule clipRule)
{
SkPath path = *pathToClip.platformPath();
path.setFillType(clipRule == RULE_EVENODD
? SkPath::kEvenOdd_FillType : SkPath::kWinding_FillType);
- mCanvas->clipPath(path);
+ return mCanvas->clipPath(path);
}
+
void PlatformGraphicsContextSkia::clearRect(const FloatRect& rect)
{
SkPaint paint;
@@ -605,4 +607,17 @@ void PlatformGraphicsContextSkia::strokeRect(const FloatRect& rect, float lineWi
mCanvas->drawRect(rect, paint);
}
+void PlatformGraphicsContextSkia::drawPosText(const void* text, size_t byteLength,
+ const SkPoint pos[], const SkPaint& paint)
+{
+ mCanvas->drawPosText(text, byteLength, pos, paint);
+}
+
+void PlatformGraphicsContextSkia::drawMediaButton(const IntRect& rect, RenderSkinMediaButton::MediaButton buttonType,
+ bool translucent, bool drawBackground,
+ const IntRect& thumb)
+{
+ RenderSkinMediaButton::Draw(mCanvas, rect, buttonType, translucent, drawBackground, thumb);
+}
+
} // WebCore
diff --git a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextSkia.h b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextSkia.h
index 724e20b..6bf53d7 100644
--- a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextSkia.h
+++ b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextSkia.h
@@ -35,11 +35,10 @@ public:
PlatformGraphicsContextSkia(SkCanvas* canvas, bool takeCanvasOwnership = false);
virtual ~PlatformGraphicsContextSkia();
virtual bool isPaintingDisabled();
- virtual SkCanvas* getCanvas() { return mCanvas; }
+ SkCanvas* canvas() { return mCanvas; }
virtual ContextType type() { return PaintingContext; }
virtual SkCanvas* recordingCanvas() { return mCanvas; }
- virtual void endRecording(int type = 0) {}
// FIXME: This is used by ImageBufferAndroid, which should really be
// managing the canvas lifecycle itself
@@ -62,19 +61,20 @@ public:
// Clipping
virtual void addInnerRoundedRectClip(const IntRect& rect, int thickness);
virtual void canvasClip(const Path& path);
- virtual void clip(const FloatRect& rect);
- virtual void clip(const Path& path);
- virtual void clipConvexPolygon(size_t numPoints, const FloatPoint*, bool antialias);
- virtual void clipOut(const IntRect& r);
- virtual void clipOut(const Path& p);
- virtual void clipPath(const Path& pathToClip, WindRule clipRule);
+ virtual bool clip(const FloatRect& rect);
+ virtual bool clip(const Path& path);
+ virtual bool clipConvexPolygon(size_t numPoints, const FloatPoint*, bool antialias);
+ virtual bool clipOut(const IntRect& r);
+ virtual bool clipOut(const Path& p);
+ virtual bool clipPath(const Path& pathToClip, WindRule clipRule);
+ virtual SkIRect getTotalClipBounds() { return mCanvas->getTotalClip().getBounds(); }
// Drawing
virtual void clearRect(const FloatRect& rect);
virtual void drawBitmapPattern(const SkBitmap& bitmap, const SkMatrix& matrix,
CompositeOperator compositeOp, const FloatRect& destRect);
virtual void drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src,
- const SkRect& dst, CompositeOperator op);
+ const SkRect& dst, CompositeOperator op = CompositeSourceOver);
virtual void drawConvexPolygon(size_t numPoints, const FloatPoint* points,
bool shouldAntialias);
virtual void drawEllipse(const IntRect& rect);
@@ -87,7 +87,7 @@ public:
virtual void drawLine(const IntPoint& point1, const IntPoint& point2);
virtual void drawLineForText(const FloatPoint& pt, float width);
virtual void drawLineForTextChecking(const FloatPoint& pt, float width,
- GraphicsContext::TextCheckingLineStyle);
+ GraphicsContext::TextCheckingLineStyle);
virtual void drawRect(const IntRect& rect);
virtual void fillPath(const Path& pathToFill, WindRule fillRule);
virtual void fillRect(const FloatRect& rect);
@@ -98,6 +98,11 @@ public:
virtual void strokeArc(const IntRect& r, int startAngle, int angleSpan);
virtual void strokePath(const Path& pathToStroke);
virtual void strokeRect(const FloatRect& rect, float lineWidth);
+ virtual void drawPosText(const void* text, size_t byteLength,
+ const SkPoint pos[], const SkPaint& paint);
+ virtual void drawMediaButton(const IntRect& rect, RenderSkinMediaButton::MediaButton buttonType,
+ bool translucent = false, bool drawBackground = true,
+ const IntRect& thumb = IntRect());
private:
diff --git a/Source/WebCore/platform/graphics/android/context/RTree.cpp b/Source/WebCore/platform/graphics/android/context/RTree.cpp
new file mode 100644
index 0000000..2e24c34
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/context/RTree.cpp
@@ -0,0 +1,598 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define LOG_TAG "RTree"
+#define LOG_NDEBUG 1
+
+#include "config.h"
+
+#include "RTree.h"
+
+#include "AndroidLog.h"
+#include "LinearAllocator.h"
+
+namespace WebCore {
+
+void* RecordingData::operator new(size_t size, LinearAllocator* allocator)
+{
+ return allocator->alloc(size);
+}
+
+}
+
+namespace RTree {
+
+#ifdef DEBUG
+static unsigned gID = 0;
+#endif
+
+class Element;
+
+//////////////////////////////////////////////////////////////////////
+// utility functions used by ElementList and Node
+
+static void recomputeBounds(int& minx, int& miny,
+ int& maxx, int& maxy,
+ unsigned& nbChildren,
+ Node**& children, int* area)
+{
+ // compute the bounds
+
+ if (nbChildren) {
+ minx = children[0]->m_minX;
+ miny = children[0]->m_minY;
+ maxx = children[0]->m_maxX;
+ maxy = children[0]->m_maxY;
+ }
+
+ for (unsigned int i = 1; i < nbChildren; i++)
+ {
+ minx = std::min(minx, children[i]->m_minX);
+ miny = std::min(miny, children[i]->m_minY);
+ maxx = std::max(maxx, children[i]->m_maxX);
+ maxy = std::max(maxy, children[i]->m_maxY);
+ }
+
+ if (area) {
+ int w = maxx - minx;
+ int h = maxy - miny;
+ *area = w * h;
+ }
+}
+
+int computeDeltaArea(Node* node, int& minx, int& miny,
+ int& maxx, int& maxy)
+{
+ int newMinX = std::min(minx, node->m_minX);
+ int newMinY = std::min(miny, node->m_minY);
+ int newMaxX = std::max(maxx, node->m_maxX);
+ int newMaxY = std::max(maxy, node->m_maxY);
+ int w = newMaxX - newMinX;
+ int h = newMaxY - newMinY;
+ return w * h;
+}
+
+//////////////////////////////////////////////////////////////////////
+// RTree
+//////////////////////////////////////////////////////////////////////
+//
+// This is an implementation of the R-Tree data structure
+// "R-Trees - a dynamic index structure for spatial searching", Guttman(84)
+//
+// The structure works as follow -- elements have bounds, intermediate
+// nodes will also maintain bounds (the union of their children' bounds).
+//
+// Searching is simple -- we just traverse the tree comparing the bounds
+// until we find the elements we are interested in.
+//
+// Each node can have at most M children -- the performances / memory usage
+// is strongly impacted by a choice of a good M value (RTree::m_maxChildren).
+//
+// Inserting an element
+// --------------------
+//
+// To find the leaf node N where we can insert a new element (RTree::insert(),
+// Node::insert()), we need to traverse the tree, picking the branch where
+// adding the new element will result in the least growth of its bounds,
+// until we reach a leaf node (Node::findNode()).
+//
+// If the number of children of that leaf node is under M, we simply
+// insert it. Otherwise, if we reached maximum capacity for that leaf,
+// we split the list of children (Node::split()), creating two lists,
+// where each list' elements is as far as each other as possible
+// (to decrease the likelyhood of future splits).
+//
+// We can then assign one of the list to the original leaf node N, and
+// we then create a new node NN that we try to attach to N's parent.
+//
+// If N's parent is also full, we go up in the hierachy and repeat
+// (Node::adjustTree()).
+//
+//////////////////////////////////////////////////////////////////////
+
+RTree::RTree(WebCore::LinearAllocator* allocator, int M)
+ : m_allocator(allocator)
+{
+ m_maxChildren = M;
+ m_listA = new ElementList(M);
+ m_listB = new ElementList(M);
+ m_root = Node::create(this);
+}
+
+RTree::~RTree()
+{
+ delete m_listA;
+ delete m_listB;
+ deleteNode(m_root);
+}
+
+void RTree::insert(WebCore::IntRect& bounds, WebCore::RecordingData* payload)
+{
+ Node* e = Node::create(this, bounds.x(), bounds.y(),
+ bounds.maxX(), bounds.maxY(), payload);
+ m_root->insert(e);
+}
+
+void RTree::search(WebCore::IntRect& clip, Vector<WebCore::RecordingData*>&list)
+{
+ m_root->search(clip.x(), clip.y(), clip.maxX(), clip.maxY(), list);
+}
+
+void RTree::remove(WebCore::IntRect& clip)
+{
+ m_root->remove(clip.x(), clip.y(), clip.maxX(), clip.maxY());
+}
+
+void RTree::display()
+{
+#ifdef DEBUG
+ m_root->drawTree();
+#endif
+}
+
+void* RTree::allocateNode()
+{
+ return m_allocator->alloc(sizeof(Node));
+}
+
+void RTree::deleteNode(Node* n)
+{
+ if (n)
+ n->~Node();
+}
+
+//////////////////////////////////////////////////////////////////////
+// ElementList
+
+ElementList::ElementList(int size)
+ : m_nbChildren(0)
+ , m_minX(0)
+ , m_maxX(0)
+ , m_minY(0)
+ , m_maxY(0)
+ , m_area(0)
+ , m_didTighten(false)
+{
+ m_children = new Node*[size];
+}
+
+ElementList::~ElementList()
+{
+ delete[] m_children;
+}
+
+void ElementList::add(Node* node)
+{
+ m_children[m_nbChildren] = node;
+ m_nbChildren++;
+ m_didTighten = false;
+}
+
+void ElementList::tighten()
+{
+ if (m_didTighten)
+ return;
+ recomputeBounds(m_minX, m_minY, m_maxX, m_maxY,
+ m_nbChildren, m_children, &m_area);
+ m_didTighten = true;
+}
+
+int ElementList::delta(Node* node)
+{
+ if (!m_didTighten)
+ tighten();
+ return computeDeltaArea(node, m_minX, m_minY, m_maxX, m_maxY);
+}
+
+void ElementList::removeAll()
+{
+ m_nbChildren = 0;
+ m_minX = 0;
+ m_maxX = 0;
+ m_minY = 0;
+ m_maxY = 0;
+ m_area = 0;
+ m_didTighten = false;
+}
+
+void ElementList::display() {
+#ifdef DEBUG
+ for (unsigned int i = 0; i < m_nbChildren; i++)
+ m_children[i]->display(0);
+#endif
+}
+
+//////////////////////////////////////////////////////////////////////
+// Node
+
+Node::Node(RTree* t, int minx, int miny, int maxx, int maxy, WebCore::RecordingData* payload)
+ : m_tree(t)
+ , m_parent(0)
+ , m_children(0)
+ , m_nbChildren(0)
+ , m_payload(payload)
+ , m_minX(minx)
+ , m_minY(miny)
+ , m_maxX(maxx)
+ , m_maxY(maxy)
+#ifdef DEBUG
+ , m_tid(gID++)
+#endif
+{
+#ifdef DEBUG
+ ALOGV("-> New Node %d", m_tid);
+#endif
+}
+
+Node::~Node()
+{
+ for (unsigned i = 0; i < m_nbChildren; i++)
+ m_tree->deleteNode(m_children[i]);
+ delete[] m_children;
+ if (m_payload)
+ m_payload->~RecordingData();
+}
+
+void Node::setParent(Node* node)
+{
+ m_parent = node;
+}
+
+void Node::insert(Node* node)
+{
+ Node* N = findNode(node);
+#ifdef DEBUG
+ ALOGV("-> Insert Node %d (%d, %d) in node %d",
+ node->m_tid, node->m_minX, node->m_minY, N->m_tid);
+#endif
+ N->add(node);
+}
+
+Node* Node::findNode(Node* node)
+{
+ if (m_nbChildren == 0)
+ return m_parent ? m_parent : this;
+
+ // pick the child whose bounds will be extended least
+
+ Node* pick = m_children[0];
+ int minIncrease = pick->delta(node);
+ for (unsigned int i = 1; i < m_nbChildren; i++) {
+ int increase = m_children[i]->delta(node);
+ if (increase < minIncrease) {
+ minIncrease = increase;
+ pick = m_children[i];
+ }
+ }
+
+ return pick->findNode(node);
+}
+
+void Node::tighten()
+{
+ recomputeBounds(m_minX, m_minY, m_maxX, m_maxY,
+ m_nbChildren, m_children, 0);
+}
+
+int Node::delta(Node* node)
+{
+ return computeDeltaArea(node, m_minX, m_minY, m_maxX, m_maxY);
+}
+
+void Node::simpleAdd(Node* node)
+{
+ node->setParent(this);
+ if (!m_children)
+ m_children = new Node*[m_tree->m_maxChildren + 1];
+ m_children[m_nbChildren] = node;
+ m_nbChildren++;
+}
+
+void Node::add(Node* node)
+{
+ simpleAdd(node);
+ Node* NN = 0;
+ if (m_nbChildren > m_tree->m_maxChildren)
+ NN = split();
+
+ adjustTree(this, NN);
+}
+
+void Node::remove(Node* node)
+{
+ int nodeIndex = -1;
+ for (unsigned int i = 0; i < m_nbChildren; i++) {
+ if (m_children[i] == node) {
+ nodeIndex = i;
+ break;
+ }
+ }
+ if (nodeIndex == -1)
+ return;
+
+ // compact
+ for (unsigned int i = nodeIndex; i < m_nbChildren - 1; i++)
+ m_children[i] = m_children[i + 1];
+ m_nbChildren--;
+}
+
+void Node::destroy(int index)
+{
+ delete m_children[index];
+ // compact
+ for (unsigned int i = index; i < m_nbChildren - 1; i++)
+ m_children[i] = m_children[i + 1];
+ m_nbChildren--;
+}
+
+void Node::removeAll()
+{
+ m_nbChildren = 0;
+ m_minX = 0;
+ m_maxX = 0;
+ m_minY = 0;
+ m_maxY = 0;
+}
+
+Node* Node::split()
+{
+ // First, let's get the seeds
+ // The idea is to get elements as distant as possible
+ // as we can, so that the resulting splitted lists
+ // will be more likely to not overlap.
+ Node* minElementX = m_children[0];
+ Node* maxElementX = m_children[0];
+ Node* minElementY = m_children[0];
+ Node* maxElementY = m_children[0];
+ for (unsigned int i = 1; i < m_nbChildren; i++) {
+ if (m_children[i]->m_minX < minElementX->m_minX)
+ minElementX = m_children[i];
+ if (m_children[i]->m_minY < minElementY->m_minY)
+ minElementY = m_children[i];
+ if (m_children[i]->m_maxX >= maxElementX->m_maxX)
+ maxElementX = m_children[i];
+ if (m_children[i]->m_maxY >= maxElementY->m_maxY)
+ maxElementY = m_children[i];
+ }
+
+ int dx = maxElementX->m_maxX - minElementX->m_minX;
+ int dy = maxElementY->m_maxY - minElementY->m_minY;
+
+ // assign the two seeds...
+ Node* elementA = minElementX;
+ Node* elementB = maxElementX;
+
+ if (dx < dy) {
+ elementA = minElementY;
+ elementB = maxElementY;
+ }
+
+ // If we get the same element, just get the first and
+ // last element inserted...
+ if (elementA == elementB) {
+ elementA = m_children[0];
+ elementB = m_children[m_nbChildren - 1];
+ }
+
+#ifdef DEBUG
+ ALOGV("split Node %d, dx: %d dy: %d elem A is %d, elem B is %d",
+ m_tid, dx, dy, elementA->m_tid, elementB->m_tid);
+#endif
+
+ // Let's use some temporary lists to do the split
+ ElementList* listA = m_tree->m_listA;
+ ElementList* listB = m_tree->m_listB;
+ listA->removeAll();
+ listB->removeAll();
+
+ listA->add(elementA);
+ listB->add(elementB);
+
+ remove(elementA);
+ remove(elementB);
+
+ // For any remaining elements, insert it into the list
+ // resulting in the smallest growth
+ for (unsigned int i = 0; i < m_nbChildren; i++) {
+ Node* node = m_children[i];
+ int dA = listA->delta(node);
+ int dB = listB->delta(node);
+
+ if (dA < dB && listA->m_nbChildren < m_tree->m_maxChildren)
+ listA->add(node);
+ else if (dB < dA && listB->m_nbChildren < m_tree->m_maxChildren)
+ listB->add(node);
+ else {
+ ElementList* smallestList =
+ listA->m_nbChildren > listB->m_nbChildren ? listB : listA;
+ smallestList->add(node);
+ }
+ }
+
+ // Use the list to rebuild the nodes
+ removeAll();
+ for (unsigned int i = 0; i < listA->m_nbChildren; i++)
+ simpleAdd(listA->m_children[i]);
+
+ Node* NN = Node::create(m_tree);
+ for (unsigned int i = 0; i < listB->m_nbChildren; i++)
+ NN->simpleAdd(listB->m_children[i]);
+ NN->tighten();
+
+ return NN;
+}
+
+bool Node::isRoot()
+{
+ return m_tree->m_root == this;
+}
+
+void Node::adjustTree(Node* N, Node* NN)
+{
+ bool callParent = N->updateBounds();
+
+ if (N->isRoot() && NN) {
+ // build new root
+ Node* root = Node::create(m_tree);
+#ifdef DEBUG
+ ALOGV("-> node %d created as new root", root->m_tid);
+#endif
+ root->simpleAdd(N);
+ root->simpleAdd(NN);
+ root->tighten();
+ m_tree->m_root = root;
+ return;
+ }
+
+ if (N->isRoot())
+ return;
+
+ if (N->m_parent) {
+ if (NN)
+ N->m_parent->add(NN);
+ else if (callParent)
+ adjustTree(N->m_parent, 0);
+ }
+}
+
+bool Node::updateBounds()
+{
+ int ominx = m_minX;
+ int ominy = m_minY;
+ int omaxx = m_maxX;
+ int omaxy = m_maxY;
+ tighten();
+ if ((ominx != m_minX)
+ || (ominy != m_minY)
+ || (omaxx != m_maxX)
+ || (omaxy != m_maxY))
+ return true;
+ return false;
+}
+
+#ifdef DEBUG
+static int gMaxLevel = 0;
+static int gNbNodes = 0;
+static int gNbElements = 0;
+
+void Node::drawTree(int level)
+{
+ if (level == 0) {
+ ALOGV("\n*** show tree ***\n");
+ gMaxLevel = 0;
+ gNbNodes = 0;
+ gNbElements = 0;
+ }
+
+ display(level);
+ for (unsigned int i = 0; i < m_nbChildren; i++)
+ {
+ m_children[i]->drawTree(level + 1);
+ }
+
+ if (gMaxLevel < level)
+ gMaxLevel = level;
+
+ if (!m_nbChildren)
+ gNbElements++;
+ else
+ gNbNodes++;
+
+ if (level == 0) {
+ ALOGV("********************\n");
+ ALOGV("Depth level %d, total bytes: %d, %d nodes, %d bytes (%d bytes/node), %d elements, %d bytes (%d bytes/node)",
+ gMaxLevel, gNbNodes * sizeof(Node) + gNbElements * sizeof(Element),
+ gNbNodes, gNbNodes * sizeof(Node), sizeof(Node),
+ gNbElements, gNbElements * sizeof(Element), sizeof(Element));
+ }
+}
+#endif
+
+#ifdef DEBUG
+void Node::display(int level)
+{
+ ALOGV("%*sNode %d - %d, %d, %d, %d (%d x %d)",
+ 2*level, "", m_tid, m_minX, m_minY, m_maxX, m_maxY, m_maxX - m_minX, m_maxY - m_minY);
+}
+#endif
+
+bool Node::overlap(int minx, int miny, int maxx, int maxy)
+{
+ return ! (minx > m_maxX
+ || maxx < m_minX
+ || maxy < m_minY
+ || miny > m_maxY);
+}
+
+void Node::search(int minx, int miny, int maxx, int maxy, Vector<WebCore::RecordingData*>& list)
+{
+ if (isElement() && overlap(minx, miny, maxx, maxy))
+ list.append(this->m_payload);
+
+ for (unsigned int i = 0; i < m_nbChildren; i++) {
+ if (m_children[i]->overlap(minx, miny, maxx, maxy))
+ m_children[i]->search(minx, miny, maxx, maxy, list);
+ }
+}
+
+bool Node::inside(int minx, int miny, int maxx, int maxy)
+{
+ return (minx <= m_minX
+ && maxx >= m_maxX
+ && miny <= m_minY
+ && maxy >= m_maxY);
+}
+
+void Node::remove(int minx, int miny, int maxx, int maxy)
+{
+ for (unsigned int i = 0; i < m_nbChildren; i++) {
+ if (m_children[i]->inside(minx, miny, maxx, maxy))
+ destroy(i);
+ else if (m_children[i]->overlap(minx, miny, maxx, maxy))
+ m_children[i]->remove(minx, miny, maxx, maxy);
+ }
+}
+
+} // Namespace RTree
diff --git a/Source/WebCore/platform/graphics/android/context/RTree.h b/Source/WebCore/platform/graphics/android/context/RTree.h
new file mode 100644
index 0000000..50962ef
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/context/RTree.h
@@ -0,0 +1,186 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef RTree_h
+#define RTree_h
+
+#include <Vector.h>
+#include "IntRect.h"
+#include "GraphicsOperation.h"
+
+namespace WebCore {
+
+class LinearAllocator;
+
+class RecordingData {
+public:
+ RecordingData(GraphicsOperation::Operation* ops, size_t orderBy)
+ : m_orderBy(orderBy)
+ , m_operation(ops)
+ {}
+ ~RecordingData() {
+ m_operation->~Operation();
+ }
+
+ size_t m_orderBy;
+ GraphicsOperation::Operation* m_operation;
+
+ void* operator new(size_t size, LinearAllocator* allocator);
+
+ // Purposely not implemented - use a LinearAllocator please
+ void* operator new(size_t size);
+ void operator delete(void* ptr);
+};
+
+} // namespace WebCore
+
+namespace RTree {
+
+class ElementList;
+class Node;
+
+class RTree {
+public:
+ // M -- max number of children per node
+ RTree(WebCore::LinearAllocator* allocator, int M = 10);
+ ~RTree();
+
+ void insert(WebCore::IntRect& bounds, WebCore::RecordingData* payload);
+ // Does an overlap search
+ void search(WebCore::IntRect& clip, Vector<WebCore::RecordingData*>& list);
+ // Does an inclusive remove -- all elements fully inside the clip will
+ // be removed from the tree
+ void remove(WebCore::IntRect& clip);
+ void display();
+
+ void* allocateNode();
+ void deleteNode(Node* n);
+
+private:
+
+ Node* m_root;
+ unsigned m_maxChildren;
+ ElementList* m_listA;
+ ElementList* m_listB;
+ WebCore::LinearAllocator* m_allocator;
+
+ friend class Node;
+};
+
+class ElementList {
+public:
+
+ ElementList(int size);
+ ~ElementList();
+ void add(Node* n);
+ void tighten();
+ int delta(Node* n);
+ void removeAll();
+ void display();
+
+ Node** m_children;
+ unsigned m_nbChildren;
+
+private:
+
+ int m_minX;
+ int m_maxX;
+ int m_minY;
+ int m_maxY;
+ int m_area;
+ bool m_didTighten;
+};
+
+class Node {
+public:
+ static Node* gRoot;
+
+ static Node* create(RTree* tree) {
+ return create(tree, 0, 0, 0, 0, 0);
+ }
+
+ static Node* create(RTree* tree, int minx, int miny, int maxx, int maxy,
+ WebCore::RecordingData* payload) {
+ return new (tree->allocateNode()) Node(tree, minx, miny, maxx, maxy, payload);
+ }
+
+ ~Node();
+
+ void insert(Node* n);
+ void search(int minx, int miny, int maxx, int maxy, Vector<WebCore::RecordingData*>& list);
+ void remove(int minx, int miny, int maxx, int maxy);
+
+ // Intentionally not implemented as Node* is custom allocated, we don't want to use this
+ void operator delete(void*);
+
+private:
+ Node(RTree* tree, int minx, int miny, int maxx, int maxy, WebCore::RecordingData* payload);
+
+ void setParent(Node* n);
+ Node* findNode(Node* n);
+ void simpleAdd(Node* n);
+ void add(Node* n);
+ void remove(Node* n);
+ void destroy(int index);
+ void removeAll();
+ Node* split();
+ void adjustTree(Node* N, Node* NN);
+ void tighten();
+ bool updateBounds();
+ int delta(Node* n);
+
+ bool overlap(int minx, int miny, int maxx, int maxy);
+ bool inside(int minx, int miny, int maxx, int maxy);
+
+ bool isElement() { return m_payload; }
+ bool isRoot();
+
+private:
+
+ RTree* m_tree;
+ Node* m_parent;
+
+ Node** m_children;
+ unsigned m_nbChildren;
+
+ WebCore::RecordingData* m_payload;
+
+public:
+
+ int m_minX;
+ int m_minY;
+ int m_maxX;
+ int m_maxY;
+
+#ifdef DEBUG
+ void drawTree(int level = 0);
+ void display(int level = 0);
+ unsigned m_tid;
+#endif
+};
+
+} // namespace RTree
+
+#endif // RTree_h
diff --git a/Source/WebCore/platform/graphics/android/context/RecordingContextCanvasProxy.cpp b/Source/WebCore/platform/graphics/android/context/RecordingContextCanvasProxy.cpp
new file mode 100644
index 0000000..838e450
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/context/RecordingContextCanvasProxy.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "RecordingContextCanvasProxy.h"
+
+#include "PlatformGraphicsContextRecording.h"
+
+namespace WebCore {
+
+// Return value is unused by FontAndroid
+int RecordingContextCanvasProxy::save(SaveFlags)
+{
+ m_pgc->save();
+ return -1;
+}
+
+void RecordingContextCanvasProxy::restore()
+{
+ m_pgc->restore();
+}
+
+void RecordingContextCanvasProxy::drawPosText(const void* text,
+ size_t byteLength,
+ const SkPoint pos[],
+ const SkPaint& paint)
+{
+ m_pgc->drawPosText(text, byteLength, pos, paint);
+}
+
+void RecordingContextCanvasProxy::drawBitmapRect(const SkBitmap& bitmap,
+ const SkIRect* src,
+ const SkRect& dst,
+ const SkPaint*)
+{
+ m_pgc->drawBitmapRect(bitmap, src, dst);
+}
+
+// Return value is unused by FontAndroid
+bool RecordingContextCanvasProxy::rotate(SkScalar degrees)
+{
+ m_pgc->rotate(degrees / (180.0f / 3.14159265f));
+ return true;
+}
+
+} // WebCore
diff --git a/Source/WebCore/platform/graphics/android/context/RecordingContextCanvasProxy.h b/Source/WebCore/platform/graphics/android/context/RecordingContextCanvasProxy.h
new file mode 100644
index 0000000..4daf5e7
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/context/RecordingContextCanvasProxy.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef RecordingContextCanvasProxy_h
+#define RecordingContextCanvasProxy_h
+
+#include "SkCanvas.h"
+
+namespace WebCore {
+
+class PlatformGraphicsContextRecording;
+
+class RecordingContextCanvasProxy : public SkCanvas {
+public:
+ RecordingContextCanvasProxy(PlatformGraphicsContextRecording* pgc)
+ : m_pgc(pgc)
+ {}
+
+ // Used by FontAndroid
+
+ // Return value is unused by FontAndroid
+ virtual int save(SaveFlags);
+ virtual void restore();
+ virtual void drawPosText(const void* text, size_t byteLength,
+ const SkPoint pos[], const SkPaint& paint);
+ virtual bool rotate(SkScalar degrees);
+
+ // Used by EmojiFont
+
+ virtual void drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src,
+ const SkRect& dst, const SkPaint*);
+
+ // These aren't used by anyone
+
+ virtual int saveLayer(const SkRect* bounds, const SkPaint*, SaveFlags) { /* NOT IMPLEMENTED*/ CRASH(); return -1; }
+ virtual bool translate(SkScalar dx, SkScalar dy) { /* NOT IMPLEMENTED*/ CRASH(); return -1; }
+ virtual bool scale(SkScalar sx, SkScalar sy) { /* NOT IMPLEMENTED*/ CRASH(); return -1; }
+ virtual bool skew(SkScalar sx, SkScalar sy) { /* NOT IMPLEMENTED*/ CRASH(); return -1; }
+ virtual bool concat(const SkMatrix& matrix) { /* NOT IMPLEMENTED*/ CRASH(); return -1; }
+ virtual void setMatrix(const SkMatrix& matrix) { /* NOT IMPLEMENTED*/ CRASH(); }
+ virtual bool clipRect(const SkRect&, SkRegion::Op, bool) { /* NOT IMPLEMENTED*/ CRASH(); return -1; }
+ virtual bool clipPath(const SkPath&, SkRegion::Op, bool) { /* NOT IMPLEMENTED*/ CRASH(); return -1; }
+ virtual bool clipRegion(const SkRegion& region, SkRegion::Op op) { /* NOT IMPLEMENTED*/ CRASH(); return -1; }
+ virtual void clear(SkColor) { /* NOT IMPLEMENTED*/ CRASH(); }
+ virtual void drawPaint(const SkPaint& paint) { /* NOT IMPLEMENTED*/ CRASH(); }
+ virtual void drawPoints(PointMode, size_t count, const SkPoint pts[],
+ const SkPaint&) { /* NOT IMPLEMENTED*/ CRASH(); }
+ virtual void drawRect(const SkRect& rect, const SkPaint&) { /* NOT IMPLEMENTED*/ CRASH(); }
+ virtual void drawPath(const SkPath& path, const SkPaint&) { /* NOT IMPLEMENTED*/ CRASH(); }
+ virtual void drawBitmap(const SkBitmap&, SkScalar left, SkScalar top,
+ const SkPaint*) { /* NOT IMPLEMENTED*/ CRASH(); }
+ virtual void drawBitmapMatrix(const SkBitmap&, const SkMatrix&,
+ const SkPaint*) { /* NOT IMPLEMENTED*/ CRASH(); }
+ virtual void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
+ const SkRect& dst, const SkPaint*) { /* NOT IMPLEMENTED*/ CRASH(); }
+ virtual void drawSprite(const SkBitmap&, int left, int top,
+ const SkPaint*) { /* NOT IMPLEMENTED*/ CRASH(); }
+ virtual void drawText(const void* text, size_t byteLength, SkScalar x,
+ SkScalar y, const SkPaint&) { /* NOT IMPLEMENTED*/ CRASH(); }
+ virtual void drawPosTextH(const void* text, size_t byteLength,
+ const SkScalar xpos[], SkScalar constY, const SkPaint&) { /* NOT IMPLEMENTED*/ CRASH(); }
+ virtual void drawTextOnPath(const void* text, size_t byteLength,
+ const SkPath& path, const SkMatrix* matrix,
+ const SkPaint&) { /* NOT IMPLEMENTED*/ CRASH(); }
+ virtual void drawPicture(SkPicture& picture) { /* NOT IMPLEMENTED*/ CRASH(); }
+ virtual void drawVertices(VertexMode, int vertexCount,
+ const SkPoint vertices[], const SkPoint texs[],
+ const SkColor colors[], SkXfermode*,
+ const uint16_t indices[], int indexCount,
+ const SkPaint&) { /* NOT IMPLEMENTED*/ CRASH(); }
+ virtual void drawData(const void*, size_t) { /* NOT IMPLEMENTED*/ CRASH(); }
+ virtual bool isDrawingToLayer() const { /* NOT IMPLEMENTED*/ CRASH(); return -1; }
+
+private:
+ PlatformGraphicsContextRecording* m_pgc;
+};
+
+} // namespace WebCore
+
+#endif // RecordingContextCanvasProxy_h
diff --git a/Source/WebCore/platform/graphics/android/fonts/FontAndroid.cpp b/Source/WebCore/platform/graphics/android/fonts/FontAndroid.cpp
index 7bed5bb..fcb78ed 100644
--- a/Source/WebCore/platform/graphics/android/fonts/FontAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/fonts/FontAndroid.cpp
@@ -26,8 +26,10 @@
#include "config.h"
+#define LOG_TAG "FontAndroid"
+
+#include "AndroidLog.h"
#include "EmojiFont.h"
-#include "GraphicsOperationCollection.h"
#include "GraphicsOperation.h"
#include "Font.h"
#include "FontData.h"
@@ -45,6 +47,7 @@
#include "SkTypeface.h"
#include "SkUtils.h"
#include "TextRun.h"
+#include "SkTypeface_android.h"
#ifdef SUPPORT_COMPLEX_SCRIPTS
#include "HarfbuzzSkia.h"
@@ -191,6 +194,12 @@ void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font,
// compile-time assert
SkASSERT(sizeof(GlyphBufferGlyph) == sizeof(uint16_t));
+ if (numGlyphs == 1 && glyphBuffer.glyphAt(from) == 0x3) {
+ // Webkit likes to draw end text control command for some reason
+ // Just ignore it
+ return;
+ }
+
SkPaint paint;
if (!setupForText(&paint, gc, font)) {
return;
@@ -220,10 +229,11 @@ void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font,
int localCount = 0;
for (int i = 0; i < numGlyphs; i++) {
if (EmojiFont::IsEmojiGlyph(glyphs[i])) {
- if (localCount)
+ if (localCount) {
canvas->drawPosText(&glyphs[localIndex],
- localCount * sizeof(uint16_t),
- &pos[localIndex], paint);
+ localCount * sizeof(uint16_t),
+ &pos[localIndex], paint);
+ }
EmojiFont::Draw(canvas, glyphs[i], x, y, paint);
// reset local index/count track for "real" glyphs
localCount = 0;
@@ -236,10 +246,11 @@ void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font,
y += SkFloatToScalar(adv[i].height());
}
// draw the last run of glyphs (if any)
- if (localCount)
+ if (localCount) {
canvas->drawPosText(&glyphs[localIndex],
- localCount * sizeof(uint16_t),
- &pos[localIndex], paint);
+ localCount * sizeof(uint16_t),
+ &pos[localIndex], paint);
+ }
} else {
for (int i = 0; i < numGlyphs; i++) {
pos[i].set(x, y);
@@ -255,13 +266,12 @@ void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font,
rotator.setRotate(90);
rotator.mapPoints(pos, numGlyphs);
}
-
- canvas->drawPosText(glyphs, numGlyphs * sizeof(uint16_t), pos, paint);
+ canvas->drawPosText(glyphs,
+ numGlyphs * sizeof(uint16_t), pos, paint);
if (font->platformData().orientation() == Vertical)
canvas->restore();
}
- gc->platformContext()->endRecording();
}
void Font::drawEmphasisMarksForComplexText(WebCore::GraphicsContext*, WebCore::TextRun const&, WTF::AtomicString const&, WebCore::FloatPoint const&, int, int) const
@@ -461,26 +471,8 @@ public:
}
private:
- enum CustomScript {
- Bengali,
- Devanagari,
- Hebrew,
- HebrewBold,
- Kannada,
- Malayalam,
- Naskh,
- Tamil,
- TamilBold,
- Telugu,
- Thai,
- NUM_SCRIPTS
- };
-
- static const char* paths[NUM_SCRIPTS];
-
void setupFontForScriptRun();
- const FontPlatformData* setupComplexFont(CustomScript script,
- const FontPlatformData& platformData);
+ const FontPlatformData* setupComplexFont(HB_Script script, const FontPlatformData& platformData);
HB_FontRec* allocHarfbuzzFont();
void deleteGlyphArrays();
void createGlyphArrays(int);
@@ -522,22 +514,6 @@ private:
unsigned m_letterSpacing; // pixels to be added after each glyph.
};
-
-// Indexed using enum CustomScript
-const char* TextRunWalker::paths[] = {
- "/system/fonts/Lohit-Bengali.ttf",
- "/system/fonts/DroidSansDevanagari-Regular.ttf",
- "/system/fonts/DroidSansHebrew-Regular.ttf",
- "/system/fonts/DroidSansHebrew-Bold.ttf",
- "/system/fonts/Lohit-Kannada.ttf",
- "/system/fonts/AnjaliNewLipi-light.ttf",
- "/system/fonts/DroidNaskh-Regular.ttf",
- "/system/fonts/DroidSansTamil-Regular.ttf",
- "/system/fonts/DroidSansTamil-Bold.ttf",
- "/system/fonts/Lohit-Telugu.ttf",
- "/system/fonts/DroidSansThai.ttf"
-};
-
TextRunWalker::TextRunWalker(const TextRun& run, int startingX, int startingY, const Font* font)
: m_font(font)
, m_startingX(startingX)
@@ -692,8 +668,7 @@ void TextRunWalker::setWordAndLetterSpacing(int wordSpacingAdjustment,
}
const FontPlatformData* TextRunWalker::setupComplexFont(
- CustomScript script,
- const FontPlatformData& platformData)
+ HB_Script script, const FontPlatformData& platformData)
{
static FallbackHash fallbackPlatformData;
@@ -703,15 +678,19 @@ const FontPlatformData* TextRunWalker::setupComplexFont(
// italic, then bold italic. additional fake style bits can be added.
int scriptStyleIndex = script;
if (platformData.isFakeBold())
- scriptStyleIndex += NUM_SCRIPTS;
+ scriptStyleIndex += HB_ScriptCount;
if (platformData.isFakeItalic())
- scriptStyleIndex += NUM_SCRIPTS << 1;
+ scriptStyleIndex += HB_ScriptCount << 1;
FallbackFontKey key(scriptStyleIndex, platformData.size());
FontPlatformData* newPlatformData = 0;
if (!fallbackPlatformData.contains(key)) {
- SkTypeface* typeface = SkTypeface::CreateFromFile(paths[script]);
+ SkTypeface::Style currentStyle = SkTypeface::kNormal;
+ if (platformData.typeface())
+ currentStyle = platformData.typeface()->style();
+ SkTypeface* typeface = SkCreateTypefaceForScript(script, currentStyle,
+ SkPaint::kElegant_Variant);
newPlatformData = new FontPlatformData(platformData, typeface);
SkSafeUnref(typeface);
fallbackPlatformData.set(key, newPlatformData);
@@ -729,61 +708,8 @@ void TextRunWalker::setupFontForScriptRun()
const FontData* fontData = m_font->glyphDataForCharacter(m_run[0], false).fontData;
const FontPlatformData& platformData =
fontData->fontDataForCharacter(' ')->platformData();
- const FontPlatformData* complexPlatformData = &platformData;
-
- switch (m_item.item.script) {
- case HB_Script_Bengali:
- complexPlatformData = setupComplexFont(Bengali, platformData);
- break;
- case HB_Script_Devanagari:
- complexPlatformData = setupComplexFont(Devanagari, platformData);
- break;
- case HB_Script_Hebrew:
- switch (platformData.typeface()->style()) {
- case SkTypeface::kBold:
- case SkTypeface::kBoldItalic:
- complexPlatformData = setupComplexFont(HebrewBold, platformData);
- break;
- case SkTypeface::kNormal:
- case SkTypeface::kItalic:
- default:
- complexPlatformData = setupComplexFont(Hebrew, platformData);
- break;
- }
- break;
- case HB_Script_Kannada:
- complexPlatformData = setupComplexFont(Kannada, platformData);
- break;
- case HB_Script_Malayalam:
- complexPlatformData = setupComplexFont(Malayalam, platformData);
- break;
- case HB_Script_Arabic:
- complexPlatformData = setupComplexFont(Naskh, platformData);
- break;
- case HB_Script_Tamil:
- switch (platformData.typeface()->style()) {
- case SkTypeface::kBold:
- case SkTypeface::kBoldItalic:
- complexPlatformData = setupComplexFont(TamilBold, platformData);
- break;
- case SkTypeface::kNormal:
- case SkTypeface::kItalic:
- default:
- complexPlatformData = setupComplexFont(Tamil, platformData);
- break;
- }
- break;
- case HB_Script_Telugu:
- complexPlatformData = setupComplexFont(Telugu, platformData);
- break;
- case HB_Script_Thai:
- complexPlatformData = setupComplexFont(Thai, platformData);
- break;
- default:
- // HB_Script_Common; includes Ethiopic
- complexPlatformData = &platformData;
- break;
- }
+ const FontPlatformData* complexPlatformData = setupComplexFont(m_item.item.script, platformData);
+
m_item.face = complexPlatformData->harfbuzzFace();
m_item.font->userData = const_cast<FontPlatformData*>(complexPlatformData);
@@ -1113,18 +1039,17 @@ void Font::drawComplexText(GraphicsContext* gc, TextRun const& run,
if (fill) {
walker.fontPlatformDataForScriptRun()->setupPaint(&fillPaint);
adjustTextRenderMode(&fillPaint, haveMultipleLayers);
- canvas->drawPosText(walker.glyphs(), walker.length() << 1,
- walker.positions(), fillPaint);
+ canvas->drawPosText(walker.glyphs(),
+ walker.length() << 1, walker.positions(), fillPaint);
}
if (stroke) {
walker.fontPlatformDataForScriptRun()->setupPaint(&strokePaint);
adjustTextRenderMode(&strokePaint, haveMultipleLayers);
- canvas->drawPosText(walker.glyphs(), walker.length() << 1,
- walker.positions(), strokePaint);
+ canvas->drawPosText(walker.glyphs(),
+ walker.length() << 1, walker.positions(), strokePaint);
}
}
- gc->platformContext()->endRecording();
}
float Font::floatWidthForComplexText(const TextRun& run,
diff --git a/Source/WebCore/platform/graphics/android/fonts/FontPlatformData.h b/Source/WebCore/platform/graphics/android/fonts/FontPlatformData.h
index 02a0cea..afae949 100644
--- a/Source/WebCore/platform/graphics/android/fonts/FontPlatformData.h
+++ b/Source/WebCore/platform/graphics/android/fonts/FontPlatformData.h
@@ -33,12 +33,13 @@
#include "FontOrientation.h"
#include "TextOrientation.h"
#include <wtf/text/StringImpl.h>
+#include "SkLanguage.h"
+#include "SkPaint.h"
#ifndef NDEBUG
#include "PlatformString.h"
#endif
-class SkPaint;
class SkTypeface;
struct HB_FaceRec_;
@@ -62,13 +63,13 @@ public:
~FontPlatformData();
FontPlatformData(WTF::HashTableDeletedValueType)
- : mTypeface(hashTableDeletedFontValue()) { }
+ : m_typeface(hashTableDeletedFontValue()) { }
bool isHashTableDeletedValue() const {
- return mTypeface == hashTableDeletedFontValue();
+ return m_typeface == hashTableDeletedFontValue();
}
- FontOrientation orientation() const { return mOrientation; }
- void setOrientation(FontOrientation orientation) { mOrientation = orientation; }
+ FontOrientation orientation() const { return m_orientation; }
+ void setOrientation(FontOrientation orientation) { m_orientation = orientation; }
FontPlatformData& operator=(const FontPlatformData&);
bool operator==(const FontPlatformData& a) const;
@@ -80,7 +81,7 @@ public:
// -------------------------------------------------------------------------
uint32_t uniqueID() const;
- float size() const { return mTextSize; }
+ float size() const { return m_textSize; }
unsigned hash() const;
int emSizeInFontUnits() const;
bool isFixedPitch() const;
@@ -90,10 +91,12 @@ public:
#endif
HB_FaceRec_* harfbuzzFace() const;
- SkTypeface* typeface() const { return mTypeface; }
+ SkTypeface* typeface() const { return m_typeface; }
- bool isFakeBold() const { return mFakeBold; }
- bool isFakeItalic() const { return mFakeItalic; }
+ bool isFakeBold() const { return m_fakeBold; }
+ bool isFakeItalic() const { return m_fakeItalic; }
+
+ static void setDefaultLanguage(const char* language);
private:
class RefCountedHarfbuzzFace : public RefCounted<RefCountedHarfbuzzFace> {
@@ -115,14 +118,15 @@ private:
HB_FaceRec_* m_harfbuzzFace;
};
- SkTypeface* mTypeface;
- float mTextSize;
- mutable int mEmSizeInFontUnits;
- bool mFakeBold;
- bool mFakeItalic;
- FontOrientation mOrientation;
- TextOrientation mTextOrientation;
+ SkTypeface* m_typeface;
+ float m_textSize;
+ mutable int m_emSizeInFontUnits;
+ bool m_fakeBold;
+ bool m_fakeItalic;
+ FontOrientation m_orientation;
+ TextOrientation m_textOrientation;
mutable RefPtr<RefCountedHarfbuzzFace> m_harfbuzzFace;
+ static SkLanguage s_defaultLanguage;
static SkTypeface* hashTableDeletedFontValue() {
return reinterpret_cast<SkTypeface*>(-1);
diff --git a/Source/WebCore/platform/graphics/android/fonts/FontPlatformDataAndroid.cpp b/Source/WebCore/platform/graphics/android/fonts/FontPlatformDataAndroid.cpp
index fc254c0..f3e4227 100644
--- a/Source/WebCore/platform/graphics/android/fonts/FontPlatformDataAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/fonts/FontPlatformDataAndroid.cpp
@@ -41,26 +41,26 @@
//#define COUNT_FONTPLATFORMDATA_LIFE
#ifdef COUNT_FONTPLATFORMDATA_LIFE
-static int gCount;
-static int gMaxCount;
+static int g_count;
+static int g_maxCount;
static void inc_count()
{
- if (++gCount > gMaxCount)
+ if (++g_count > g_maxCount)
{
- gMaxCount = gCount;
- SkDebugf("---------- FontPlatformData %d\n", gMaxCount);
+ g_maxCount = g_count;
+ SkDebugf("---------- FontPlatformData %d\n", g_maxCount);
}
}
-static void dec_count() { --gCount; }
+static void dec_count() { --g_count; }
#else
#define inc_count()
#define dec_count()
#endif
#ifdef TRACE_FONTPLATFORMDATA_LIFE
- #define trace(num) SkDebugf("FontPlatformData%d %p %g %d %d\n", num, mTypeface, mTextSize, mFakeBold, mFakeItalic)
+ #define trace(num) SkDebugf("FontPlatformData%d %p %g %d %d\n", num, m_typeface, m_textSize, m_fakeBold, m_fakeItalic)
#else
#define trace(num)
#endif
@@ -75,8 +75,8 @@ FontPlatformData::RefCountedHarfbuzzFace::~RefCountedHarfbuzzFace()
}
FontPlatformData::FontPlatformData()
- : mTypeface(NULL), mTextSize(0), mEmSizeInFontUnits(0), mFakeBold(false), mFakeItalic(false),
- mOrientation(Horizontal), mTextOrientation(TextOrientationVerticalRight)
+ : m_typeface(NULL), m_textSize(0), m_emSizeInFontUnits(0), m_fakeBold(false), m_fakeItalic(false),
+ m_orientation(Horizontal), m_textOrientation(TextOrientationVerticalRight)
{
inc_count();
trace(1);
@@ -84,30 +84,29 @@ FontPlatformData::FontPlatformData()
FontPlatformData::FontPlatformData(const FontPlatformData& src)
{
- if (hashTableDeletedFontValue() != src.mTypeface) {
- SkSafeRef(src.mTypeface);
+ if (hashTableDeletedFontValue() != src.m_typeface) {
+ SkSafeRef(src.m_typeface);
}
- mTypeface = src.mTypeface;
- mTextSize = src.mTextSize;
- mEmSizeInFontUnits = src.mEmSizeInFontUnits;
- mFakeBold = src.mFakeBold;
- mFakeItalic = src.mFakeItalic;
+ m_typeface = src.m_typeface;
+ m_textSize = src.m_textSize;
+ m_emSizeInFontUnits = src.m_emSizeInFontUnits;
+ m_fakeBold = src.m_fakeBold;
+ m_fakeItalic = src.m_fakeItalic;
m_harfbuzzFace = src.m_harfbuzzFace;
- mOrientation = src.mOrientation;
- mTextOrientation = src.mTextOrientation;
-
+ m_orientation = src.m_orientation;
+ m_textOrientation = src.m_textOrientation;
inc_count();
trace(2);
}
FontPlatformData::FontPlatformData(SkTypeface* tf, float textSize, bool fakeBold, bool fakeItalic,
FontOrientation orientation, TextOrientation textOrientation)
- : mTypeface(tf), mTextSize(textSize), mEmSizeInFontUnits(0), mFakeBold(fakeBold), mFakeItalic(fakeItalic),
- mOrientation(orientation), mTextOrientation(textOrientation)
+ : m_typeface(tf), m_textSize(textSize), m_emSizeInFontUnits(0), m_fakeBold(fakeBold), m_fakeItalic(fakeItalic),
+ m_orientation(orientation), m_textOrientation(textOrientation)
{
- if (hashTableDeletedFontValue() != mTypeface) {
- SkSafeRef(mTypeface);
+ if (hashTableDeletedFontValue() != m_typeface) {
+ SkSafeRef(m_typeface);
}
inc_count();
@@ -115,11 +114,11 @@ FontPlatformData::FontPlatformData(SkTypeface* tf, float textSize, bool fakeBold
}
FontPlatformData::FontPlatformData(const FontPlatformData& src, float textSize)
- : mTypeface(src.mTypeface), mTextSize(textSize), mEmSizeInFontUnits(src.mEmSizeInFontUnits), mFakeBold(src.mFakeBold), mFakeItalic(src.mFakeItalic),
- mOrientation(src.mOrientation), mTextOrientation(src.mTextOrientation), m_harfbuzzFace(src.m_harfbuzzFace)
+ : m_typeface(src.m_typeface), m_textSize(textSize), m_emSizeInFontUnits(src.m_emSizeInFontUnits), m_fakeBold(src.m_fakeBold), m_fakeItalic(src.m_fakeItalic),
+ m_orientation(src.m_orientation), m_textOrientation(src.m_textOrientation), m_harfbuzzFace(src.m_harfbuzzFace)
{
- if (hashTableDeletedFontValue() != mTypeface) {
- SkSafeRef(mTypeface);
+ if (hashTableDeletedFontValue() != m_typeface) {
+ SkSafeRef(m_typeface);
}
inc_count();
@@ -127,20 +126,20 @@ FontPlatformData::FontPlatformData(const FontPlatformData& src, float textSize)
}
FontPlatformData::FontPlatformData(float size, bool bold, bool oblique)
- : mTypeface(NULL), mTextSize(size), mEmSizeInFontUnits(0), mFakeBold(bold), mFakeItalic(oblique),
- mOrientation(Horizontal), mTextOrientation(TextOrientationVerticalRight)
+ : m_typeface(NULL), m_textSize(size), m_emSizeInFontUnits(0), m_fakeBold(bold), m_fakeItalic(oblique),
+ m_orientation(Horizontal), m_textOrientation(TextOrientationVerticalRight)
{
inc_count();
trace(5);
}
FontPlatformData::FontPlatformData(const FontPlatformData& src, SkTypeface* tf)
- : mTypeface(tf), mTextSize(src.mTextSize), mEmSizeInFontUnits(0), mFakeBold(src.mFakeBold),
- mFakeItalic(src.mFakeItalic), mOrientation(src.mOrientation),
- mTextOrientation(src.mTextOrientation)
+ : m_typeface(tf), m_textSize(src.m_textSize), m_emSizeInFontUnits(0), m_fakeBold(src.m_fakeBold),
+ m_fakeItalic(src.m_fakeItalic), m_orientation(src.m_orientation),
+ m_textOrientation(src.m_textOrientation)
{
- if (hashTableDeletedFontValue() != mTypeface) {
- SkSafeRef(mTypeface);
+ if (hashTableDeletedFontValue() != m_typeface) {
+ SkSafeRef(m_typeface);
}
inc_count();
@@ -154,61 +153,67 @@ FontPlatformData::~FontPlatformData()
SkDebugf("----------- ~FontPlatformData\n");
#endif
- if (hashTableDeletedFontValue() != mTypeface) {
- SkSafeUnref(mTypeface);
+ if (hashTableDeletedFontValue() != m_typeface) {
+ SkSafeUnref(m_typeface);
}
}
int FontPlatformData::emSizeInFontUnits() const
{
- if (mEmSizeInFontUnits)
- return mEmSizeInFontUnits;
+ if (m_emSizeInFontUnits)
+ return m_emSizeInFontUnits;
SkAdvancedTypefaceMetrics* metrics = 0;
- if (mTypeface)
- metrics = mTypeface->getAdvancedTypefaceMetrics(SkAdvancedTypefaceMetrics::kNo_PerGlyphInfo);
+ if (m_typeface)
+ metrics = m_typeface->getAdvancedTypefaceMetrics(SkAdvancedTypefaceMetrics::kNo_PerGlyphInfo);
if (metrics) {
- mEmSizeInFontUnits = metrics->fEmSize;
+ m_emSizeInFontUnits = metrics->fEmSize;
metrics->unref();
} else
- mEmSizeInFontUnits = 1000; // default value copied from Skia.
- return mEmSizeInFontUnits;
+ m_emSizeInFontUnits = 1000; // default value copied from Skia.
+ return m_emSizeInFontUnits;
}
FontPlatformData& FontPlatformData::operator=(const FontPlatformData& src)
{
- if (hashTableDeletedFontValue() != src.mTypeface) {
- SkSafeRef(src.mTypeface);
+ if (hashTableDeletedFontValue() != src.m_typeface) {
+ SkSafeRef(src.m_typeface);
}
- if (hashTableDeletedFontValue() != mTypeface) {
- SkSafeUnref(mTypeface);
+ if (hashTableDeletedFontValue() != m_typeface) {
+ SkSafeUnref(m_typeface);
}
- mTypeface = src.mTypeface;
- mEmSizeInFontUnits = src.mEmSizeInFontUnits;
- mTextSize = src.mTextSize;
- mFakeBold = src.mFakeBold;
- mFakeItalic = src.mFakeItalic;
+ m_typeface = src.m_typeface;
+ m_emSizeInFontUnits = src.m_emSizeInFontUnits;
+ m_textSize = src.m_textSize;
+ m_fakeBold = src.m_fakeBold;
+ m_fakeItalic = src.m_fakeItalic;
m_harfbuzzFace = src.m_harfbuzzFace;
- mOrientation = src.mOrientation;
- mTextOrientation = src.mTextOrientation;
+ m_orientation = src.m_orientation;
+ m_textOrientation = src.m_textOrientation;
return *this;
}
+SkLanguage FontPlatformData::s_defaultLanguage;
+void FontPlatformData::setDefaultLanguage(const char* language) {
+ s_defaultLanguage = SkLanguage(language);
+}
+
void FontPlatformData::setupPaint(SkPaint* paint) const
{
- if (hashTableDeletedFontValue() == mTypeface)
+ if (hashTableDeletedFontValue() == m_typeface)
paint->setTypeface(0);
else
- paint->setTypeface(mTypeface);
+ paint->setTypeface(m_typeface);
paint->setAntiAlias(true);
paint->setSubpixelText(true);
paint->setHinting(SkPaint::kSlight_Hinting);
- paint->setTextSize(SkFloatToScalar(mTextSize));
- paint->setFakeBoldText(mFakeBold);
- paint->setTextSkewX(mFakeItalic ? -SK_Scalar1/4 : 0);
+ paint->setTextSize(SkFloatToScalar(m_textSize));
+ paint->setFakeBoldText(m_fakeBold);
+ paint->setTextSkewX(m_fakeItalic ? -SK_Scalar1/4 : 0);
+ paint->setLanguage(s_defaultLanguage);
#ifndef SUPPORT_COMPLEX_SCRIPTS
paint->setTextEncoding(SkPaint::kUTF16_TextEncoding);
#endif
@@ -216,44 +221,44 @@ void FontPlatformData::setupPaint(SkPaint* paint) const
uint32_t FontPlatformData::uniqueID() const
{
- if (hashTableDeletedFontValue() == mTypeface)
+ if (hashTableDeletedFontValue() == m_typeface)
return SkTypeface::UniqueID(0);
else
- return SkTypeface::UniqueID(mTypeface);
+ return SkTypeface::UniqueID(m_typeface);
}
bool FontPlatformData::operator==(const FontPlatformData& a) const
{
- return mTypeface == a.mTypeface &&
- mTextSize == a.mTextSize &&
- mFakeBold == a.mFakeBold &&
- mFakeItalic == a.mFakeItalic &&
- mOrientation == a.mOrientation &&
- mTextOrientation == a.mTextOrientation;
+ return m_typeface == a.m_typeface &&
+ m_textSize == a.m_textSize &&
+ m_fakeBold == a.m_fakeBold &&
+ m_fakeItalic == a.m_fakeItalic &&
+ m_orientation == a.m_orientation &&
+ m_textOrientation == a.m_textOrientation;
}
unsigned FontPlatformData::hash() const
{
unsigned h;
- if (hashTableDeletedFontValue() == mTypeface) {
- h = reinterpret_cast<unsigned>(mTypeface);
+ if (hashTableDeletedFontValue() == m_typeface) {
+ h = reinterpret_cast<unsigned>(m_typeface);
} else {
- h = SkTypeface::UniqueID(mTypeface);
+ h = SkTypeface::UniqueID(m_typeface);
}
- uint32_t sizeAsInt = *reinterpret_cast<const uint32_t*>(&mTextSize);
+ uint32_t sizeAsInt = *reinterpret_cast<const uint32_t*>(&m_textSize);
- h ^= 0x01010101 * ((static_cast<int>(mTextOrientation) << 3) | (static_cast<int>(mOrientation) << 2) |
- ((int)mFakeBold << 1) | (int)mFakeItalic);
+ h ^= 0x01010101 * ((static_cast<int>(m_textOrientation) << 3) | (static_cast<int>(m_orientation) << 2) |
+ ((int)m_fakeBold << 1) | (int)m_fakeItalic);
h ^= sizeAsInt;
return h;
}
bool FontPlatformData::isFixedPitch() const
{
- if (mTypeface && (mTypeface != hashTableDeletedFontValue()))
- return mTypeface->isFixedWidth();
+ if (m_typeface && (m_typeface != hashTableDeletedFontValue()))
+ return m_typeface->isFixedWidth();
else
return false;
}
diff --git a/Source/WebCore/platform/graphics/android/layers/CanvasTexture.cpp b/Source/WebCore/platform/graphics/android/layers/CanvasTexture.cpp
index e4b2bc6..aacb0bc 100644
--- a/Source/WebCore/platform/graphics/android/layers/CanvasTexture.cpp
+++ b/Source/WebCore/platform/graphics/android/layers/CanvasTexture.cpp
@@ -31,7 +31,6 @@
#if USE(ACCELERATED_COMPOSITING)
-#include "android_graphics.h"
#include "AndroidLog.h"
#include "GLUtils.h"
#include "Image.h"
@@ -134,10 +133,10 @@ bool CanvasTexture::uploadImageBuffer(ImageBuffer* imageBuffer)
// Size mismatch, early abort (will fall back to software)
if (imageBuffer->size() != m_size)
return false;
- GraphicsContext* gc = imageBuffer ? imageBuffer->context() : 0;
- if (!gc)
+ SkCanvas* canvas = imageBufferCanvas(imageBuffer);
+ if (!canvas)
return false;
- const SkBitmap& bitmap = android_gc2canvas(gc)->getDevice()->accessBitmap(false);
+ const SkBitmap& bitmap = canvas->getDevice()->accessBitmap(false);
if (!GLUtils::updateSharedSurfaceTextureWithBitmap(anw, bitmap))
return false;
m_hasValidTexture = true;
diff --git a/Source/WebCore/platform/graphics/android/layers/DumpLayer.cpp b/Source/WebCore/platform/graphics/android/layers/DumpLayer.cpp
index 5551965..d827c44 100644
--- a/Source/WebCore/platform/graphics/android/layers/DumpLayer.cpp
+++ b/Source/WebCore/platform/graphics/android/layers/DumpLayer.cpp
@@ -3,79 +3,87 @@
#if USE(ACCELERATED_COMPOSITING)
+#define WRITE_VAL(format, ...) (snprintf(m_valueBuffer, BUF_SIZE, format, __VA_ARGS__), writeEntry(label, m_valueBuffer))
+
namespace WebCore {
-void lwrite(FILE* file, const char* str)
+void LayerDumper::writeIntVal(const char* label, int value)
{
- fwrite(str, sizeof(char), strlen(str), file);
+ WRITE_VAL("%d", value);
}
-void writeIndent(FILE* file, int indentLevel)
+void LayerDumper::writeHexVal(const char* label, int value)
{
- if (indentLevel)
- fprintf(file, "%*s", indentLevel*2, " ");
+ WRITE_VAL("%x", value);
}
-void writeln(FILE* file, int indentLevel, const char* str)
+void LayerDumper::writeFloatVal(const char* label, float value)
{
- writeIndent(file, indentLevel);
- lwrite(file, str);
- lwrite(file, "\n");
+ WRITE_VAL("%.3f", value);
}
-void writeIntVal(FILE* file, int indentLevel, const char* str, int value)
+void LayerDumper::writePoint(const char* label, SkPoint point)
{
- writeIndent(file, indentLevel);
- fprintf(file, "%s = %d;\n", str, value);
+ WRITE_VAL("{ x = %.3f; y = %.3f; }", point.fX, point.fY);
}
-void writeHexVal(FILE* file, int indentLevel, const char* str, int value)
+void LayerDumper::writeIntPoint(const char* label, IntPoint point)
{
- writeIndent(file, indentLevel);
- fprintf(file, "%s = %x;\n", str, value);
+ WRITE_VAL("{ x = %d; y = %d; }", point.x(), point.y());
}
-void writeFloatVal(FILE* file, int indentLevel, const char* str, float value)
+void LayerDumper::writeSize(const char* label, SkSize size)
{
- writeIndent(file, indentLevel);
- fprintf(file, "%s = %.3f;\n", str, value);
+ WRITE_VAL("{ w = %.3f; h = %.3f; }", size.width(), size.height());
}
-void writePoint(FILE* file, int indentLevel, const char* str, SkPoint point)
+void LayerDumper::writeRect(const char* label, SkRect rect)
{
- writeIndent(file, indentLevel);
- fprintf(file, "%s = { x = %.3f; y = %.3f; };\n", str, point.fX, point.fY);
+ WRITE_VAL("{ x = %.3f; y = %.3f; w = %.3f; h = %.3f; }",
+ rect.fLeft, rect.fTop, rect.width(), rect.height());
}
-void writeIntPoint(FILE* file, int indentLevel, const char* str, IntPoint point)
+void LayerDumper::writeMatrix(const char* label, const TransformationMatrix& matrix)
{
- writeIndent(file, indentLevel);
- fprintf(file, "%s = { x = %d; y = %d; };\n", str, point.x(), point.y());
+ WRITE_VAL("{ (%.2f,%.2f,%.2f,%.2f),(%.2f,%.2f,%.2f,%.2f),"
+ "(%.2f,%.2f,%.2f,%.2f),(%.2f,%.2f,%.2f,%.2f) }",
+ matrix.m11(), matrix.m12(), matrix.m13(), matrix.m14(),
+ matrix.m21(), matrix.m22(), matrix.m23(), matrix.m24(),
+ matrix.m31(), matrix.m32(), matrix.m33(), matrix.m34(),
+ matrix.m41(), matrix.m42(), matrix.m43(), matrix.m44());
}
-void writeSize(FILE* file, int indentLevel, const char* str, SkSize size)
+void LayerDumper::writeLength(const char* label, SkLength value)
{
- writeIndent(file, indentLevel);
- fprintf(file, "%s = { w = %.3f; h = %.3f; };\n", str, size.width(), size.height());
+ if (value.defined())
+ WRITE_VAL("{ type = %d; value = %.2f; }", value.type, value.value);
+ else
+ writeEntry(label, "<undefined>");
}
-void writeRect(FILE* file, int indentLevel, const char* str, SkRect rect)
+void FileLayerDumper::beginLayer(const char* className, const LayerAndroid* layerPtr)
{
- writeIndent(file, indentLevel);
- fprintf(file, "%s = { x = %.3f; y = %.3f; w = %.3f; h = %.3f; };\n",
- str, rect.fLeft, rect.fTop, rect.width(), rect.height());
+ LayerDumper::beginLayer(className, layerPtr);
+ writeLine("{");
+ writeHexVal("layer", (int)layerPtr);
}
-void writeMatrix(FILE* file, int indentLevel, const char* str, const TransformationMatrix& matrix)
+void FileLayerDumper::endLayer()
{
- writeIndent(file, indentLevel);
- fprintf(file, "%s = { (%.2f,%.2f,%.2f,%.2f),(%.2f,%.2f,%.2f,%.2f),"
- "(%.2f,%.2f,%.2f,%.2f),(%.2f,%.2f,%.2f,%.2f) };\n",
- str,
- matrix.m11(), matrix.m12(), matrix.m13(), matrix.m14(),
- matrix.m21(), matrix.m22(), matrix.m23(), matrix.m24(),
- matrix.m31(), matrix.m32(), matrix.m33(), matrix.m34(),
- matrix.m41(), matrix.m42(), matrix.m43(), matrix.m44());
+ writeLine("}");
+ LayerDumper::endLayer();
+}
+
+void FileLayerDumper::writeEntry(const char* label, const char* value)
+{
+ fprintf(m_file, "%*s%s = %s\n", (m_indentLevel + 1) * 2, " ", label, value);
+}
+
+void FileLayerDumper::writeLine(const char* str)
+{
+ if (m_indentLevel)
+ fprintf(m_file, "%*s", m_indentLevel * 2, " ");
+ fprintf(m_file, "%s\n", str);
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/layers/DumpLayer.h b/Source/WebCore/platform/graphics/android/layers/DumpLayer.h
index 5b30952..9fd3365 100644
--- a/Source/WebCore/platform/graphics/android/layers/DumpLayer.h
+++ b/Source/WebCore/platform/graphics/android/layers/DumpLayer.h
@@ -17,7 +17,9 @@
#ifndef DumpLayer_h
#define DumpLayer_h
+#include "FixedPositioning.h"
#include "IntPoint.h"
+#include "LayerAndroid.h"
#include "SkPoint.h"
#include "SkRect.h"
#include "SkSize.h"
@@ -50,17 +52,59 @@
namespace WebCore {
-void lwrite(FILE* file, const char* str);
-void writeIndent(FILE* file, int indentLevel);
-void writeln(FILE* file, int indentLevel, const char* str);
-void writeIntVal(FILE* file, int indentLevel, const char* str, int value);
-void writeHexVal(FILE* file, int indentLevel, const char* str, int value);
-void writeFloatVal(FILE* file, int indentLevel, const char* str, float value);
-void writePoint(FILE* file, int indentLevel, const char* str, SkPoint point);
-void writeIntPoint(FILE* file, int indentLevel, const char* str, IntPoint point);
-void writeSize(FILE* file, int indentLevel, const char* str, SkSize size);
-void writeRect(FILE* file, int indentLevel, const char* str, SkRect rect);
-void writeMatrix(FILE* file, int indentLevel, const char* str, const TransformationMatrix& matrix);
+class LayerDumper {
+public:
+ LayerDumper(int initialIndentLevel = 0)
+ : m_indentLevel(initialIndentLevel)
+ {}
+ virtual ~LayerDumper() {}
+
+ virtual void beginLayer(const char* className, const LayerAndroid* layerPtr) {}
+
+ virtual void endLayer() {}
+
+ virtual void beginChildren(int childCount) {
+ m_indentLevel++;
+ }
+ virtual void endChildren() {
+ m_indentLevel--;
+ }
+
+ void writeIntVal(const char* label, int value);
+ void writeHexVal(const char* label, int value);
+ void writeFloatVal(const char* label, float value);
+ void writePoint(const char* label, SkPoint value);
+ void writeIntPoint(const char* label, IntPoint value);
+ void writeSize(const char* label, SkSize value);
+ void writeRect(const char* label, SkRect value);
+ void writeMatrix(const char* label, const TransformationMatrix& value);
+ void writeLength(const char* label, SkLength value);
+
+protected:
+ virtual void writeEntry(const char* label, const char* value) = 0;
+
+ int m_indentLevel;
+
+private:
+ static const int BUF_SIZE = 4096;
+ char m_valueBuffer[BUF_SIZE];
+};
+
+class FileLayerDumper : public LayerDumper {
+public:
+ FileLayerDumper(FILE* file)
+ : m_file(file)
+ {}
+
+ virtual void beginLayer(const char* className, const LayerAndroid* layerPtr);
+ virtual void endLayer();
+protected:
+ virtual void writeEntry(const char* label, const char* value);
+
+private:
+ void writeLine(const char* str);
+ FILE* m_file;
+};
}
diff --git a/Source/WebCore/platform/graphics/android/layers/FixedPositioning.cpp b/Source/WebCore/platform/graphics/android/layers/FixedPositioning.cpp
index 82afe8f..aa204f8 100644
--- a/Source/WebCore/platform/graphics/android/layers/FixedPositioning.cpp
+++ b/Source/WebCore/platform/graphics/android/layers/FixedPositioning.cpp
@@ -86,25 +86,17 @@ void FixedPositioning::contentDraw(SkCanvas* canvas, Layer::PaintStyle style)
}
}
-void writeLength(FILE* file, int indentLevel, const char* str, SkLength length)
+void FixedPositioning::dumpLayer(LayerDumper* dumper) const
{
- if (!length.defined())
- return;
- writeIndent(file, indentLevel);
- fprintf(file, "%s = { type = %d; value = %.2f; };\n", str, length.type, length.value);
-}
-
-void FixedPositioning::dumpLayer(FILE* file, int indentLevel) const
-{
- writeLength(file, indentLevel + 1, "fixedLeft", m_fixedLeft);
- writeLength(file, indentLevel + 1, "fixedTop", m_fixedTop);
- writeLength(file, indentLevel + 1, "fixedRight", m_fixedRight);
- writeLength(file, indentLevel + 1, "fixedBottom", m_fixedBottom);
- writeLength(file, indentLevel + 1, "fixedMarginLeft", m_fixedMarginLeft);
- writeLength(file, indentLevel + 1, "fixedMarginTop", m_fixedMarginTop);
- writeLength(file, indentLevel + 1, "fixedMarginRight", m_fixedMarginRight);
- writeLength(file, indentLevel + 1, "fixedMarginBottom", m_fixedMarginBottom);
- writeRect(file, indentLevel + 1, "fixedRect", m_fixedRect);
+ dumper->writeLength("fixedLeft", m_fixedLeft);
+ dumper->writeLength("fixedTop", m_fixedTop);
+ dumper->writeLength("fixedRight", m_fixedRight);
+ dumper->writeLength("fixedBottom", m_fixedBottom);
+ dumper->writeLength("fixedMarginLeft", m_fixedMarginLeft);
+ dumper->writeLength("fixedMarginTop", m_fixedMarginTop);
+ dumper->writeLength("fixedMarginRight", m_fixedMarginRight);
+ dumper->writeLength("fixedMarginBottom", m_fixedMarginBottom);
+ dumper->writeRect("fixedRect", m_fixedRect);
}
BackgroundImagePositioning::BackgroundImagePositioning(LayerAndroid* layer, const BackgroundImagePositioning& position)
diff --git a/Source/WebCore/platform/graphics/android/layers/FixedPositioning.h b/Source/WebCore/platform/graphics/android/layers/FixedPositioning.h
index e273a25..ac838c8 100644
--- a/Source/WebCore/platform/graphics/android/layers/FixedPositioning.h
+++ b/Source/WebCore/platform/graphics/android/layers/FixedPositioning.h
@@ -130,7 +130,7 @@ public:
void contentDraw(SkCanvas* canvas, Layer::PaintStyle style);
- void dumpLayer(FILE*, int indentLevel) const;
+ void dumpLayer(LayerDumper*) const;
// ViewStateSerializer friends
friend void android::serializeLayer(LayerAndroid* layer, SkWStream* stream);
diff --git a/Source/WebCore/platform/graphics/android/layers/IFrameLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/layers/IFrameLayerAndroid.cpp
index 3532542..4481f55 100644
--- a/Source/WebCore/platform/graphics/android/layers/IFrameLayerAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/layers/IFrameLayerAndroid.cpp
@@ -29,10 +29,10 @@ IFrameLayerAndroid* IFrameLayerAndroid::updatePosition(SkRect viewport,
return this;
}
-void IFrameLayerAndroid::dumpLayer(FILE* file, int indentLevel) const
+void IFrameLayerAndroid::dumpLayer(LayerDumper* dumper) const
{
- writeIntVal(file, indentLevel + 1, "m_isIframe", true);
- writeIntPoint(file, indentLevel + 1, "m_iframeOffset", m_iframeOffset);
+ LayerAndroid::dumpLayer(dumper);
+ dumper->writeIntPoint("m_iframeOffset", m_iframeOffset);
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/layers/IFrameLayerAndroid.h b/Source/WebCore/platform/graphics/android/layers/IFrameLayerAndroid.h
index f2fbf49..08e7212 100644
--- a/Source/WebCore/platform/graphics/android/layers/IFrameLayerAndroid.h
+++ b/Source/WebCore/platform/graphics/android/layers/IFrameLayerAndroid.h
@@ -53,7 +53,7 @@ public:
virtual IFrameLayerAndroid* updatePosition(SkRect viewport,
IFrameLayerAndroid* parentIframeLayer);
- virtual void dumpLayer(FILE*, int indentLevel) const;
+ virtual void dumpLayer(LayerDumper*) const;
const IntPoint& iframeOffset() const { return m_iframeOffset; }
diff --git a/Source/WebCore/platform/graphics/android/layers/LayerAndroid.cpp b/Source/WebCore/platform/graphics/android/layers/LayerAndroid.cpp
index 228a30e..84ce910 100644
--- a/Source/WebCore/platform/graphics/android/layers/LayerAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/layers/LayerAndroid.cpp
@@ -398,22 +398,27 @@ void LayerAndroid::updateLocalTransformAndClip(const TransformationMatrix& paren
{
FloatPoint position(getPosition().x() + m_replicatedLayerPosition.x() - getScrollOffset().x(),
getPosition().y() + m_replicatedLayerPosition.y() - getScrollOffset().y());
- float originX = getAnchorPoint().x() * getWidth();
- float originY = getAnchorPoint().y() * getHeight();
-
- TransformationMatrix localMatrix;
if (isPositionFixed())
m_drawTransform.makeIdentity();
else
m_drawTransform = parentMatrix;
- m_drawTransform.translate3d(originX + position.x(),
- originY + position.y(),
- anchorPointZ());
- m_drawTransform.multiply(m_transform);
- m_drawTransform.translate3d(-originX,
- -originY,
- -anchorPointZ());
+
+ if (m_transform.isIdentity()) {
+ m_drawTransform.translate3d(position.x(),
+ position.y(),
+ 0);
+ } else {
+ float originX = getAnchorPoint().x() * getWidth();
+ float originY = getAnchorPoint().y() * getHeight();
+ m_drawTransform.translate3d(originX + position.x(),
+ originY + position.y(),
+ anchorPointZ());
+ m_drawTransform.multiply(m_transform);
+ m_drawTransform.translate3d(-originX,
+ -originY,
+ -anchorPointZ());
+ }
m_drawTransformUnfudged = m_drawTransform;
if (m_drawTransform.isIdentityOrTranslation()
@@ -473,23 +478,19 @@ void LayerAndroid::updateGLPositionsAndScale(const TransformationMatrix& parentM
if (!countChildren() || !m_visible)
return;
- TransformationMatrix localMatrix = m_drawTransformUnfudged;
-
+ TransformationMatrix childMatrix = m_drawTransformUnfudged;
// Flatten to 2D if the layer doesn't preserve 3D.
if (!preserves3D()) {
- localMatrix.setM13(0);
- localMatrix.setM23(0);
- localMatrix.setM31(0);
- localMatrix.setM32(0);
- localMatrix.setM33(1);
- localMatrix.setM34(0);
- localMatrix.setM43(0);
+ childMatrix.setM13(0);
+ childMatrix.setM23(0);
+ childMatrix.setM31(0);
+ childMatrix.setM32(0);
+ childMatrix.setM33(1);
+ childMatrix.setM34(0);
+ childMatrix.setM43(0);
}
// now apply it to our children
-
- TransformationMatrix childMatrix;
- childMatrix = localMatrix;
childMatrix.translate3d(getScrollOffset().x(), getScrollOffset().y(), 0);
if (!m_childrenTransform.isIdentity()) {
childMatrix.translate(getSize().width() * 0.5f, getSize().height() * 0.5f);
@@ -601,7 +602,7 @@ void LayerAndroid::showLayer(int indent)
m_clippingRect.width(), m_clippingRect.height());
ALOGD("%s s:%x %s %s (%d) [%d:%x - 0x%x] - %s %s - area (%d, %d, %d, %d) - visible (%d, %d, %d, %d) "
"clip (%d, %d, %d, %d) %s %s m_content(%x), pic w: %d h: %d originalLayer: %x %d",
- spaces, m_surface, m_haveClip ? "CLIP LAYER" : "", subclassName().ascii().data(),
+ spaces, m_surface, m_haveClip ? "CLIP LAYER" : "", subclassName(),
subclassType(), uniqueId(), this, m_owningLayer,
needsTexture() ? "needsTexture" : "",
m_imageCRC ? "hasImage" : "",
@@ -802,13 +803,14 @@ bool LayerAndroid::drawCanvas(SkCanvas* canvas, bool drawChildren, PaintStyle st
r.set(m_clippingRect.x(), m_clippingRect.y(),
m_clippingRect.x() + m_clippingRect.width(),
m_clippingRect.y() + m_clippingRect.height());
- canvas->clipRect(r);
- SkMatrix matrix;
- GLUtils::toSkMatrix(matrix, m_drawTransform);
- SkMatrix canvasMatrix = canvas->getTotalMatrix();
- matrix.postConcat(canvasMatrix);
- canvas->setMatrix(matrix);
- onDraw(canvas, m_drawOpacity, 0, style);
+ if (canvas->clipRect(r)) {
+ SkMatrix matrix;
+ GLUtils::toSkMatrix(matrix, m_drawTransform);
+ SkMatrix canvasMatrix = canvas->getTotalMatrix();
+ matrix.postConcat(canvasMatrix);
+ canvas->setMatrix(matrix);
+ onDraw(canvas, m_drawOpacity, 0, style);
+ }
}
if (!drawChildren)
@@ -819,6 +821,55 @@ bool LayerAndroid::drawCanvas(SkCanvas* canvas, bool drawChildren, PaintStyle st
return askScreenUpdate;
}
+void LayerAndroid::collect3dRenderingContext(Vector<LayerAndroid*>& layersInContext)
+{
+ layersInContext.append(this);
+ if (preserves3D()) {
+ int count = countChildren();
+ for (int i = 0; i < count; i++)
+ getChild(i)->collect3dRenderingContext(layersInContext);
+ }
+}
+
+bool LayerAndroid::drawSurfaceAndChildrenGL()
+{
+ bool askScreenUpdate = false;
+ if (surface()->getFirstLayer() == this)
+ askScreenUpdate |= surface()->drawGL(false);
+
+ // return early, since children will be painted directly by drawTreeSurfacesGL
+ if (preserves3D())
+ return askScreenUpdate;
+
+ int count = countChildren();
+ Vector <LayerAndroid*> sublayers;
+ for (int i = 0; i < count; i++)
+ sublayers.append(getChild(i));
+
+ std::stable_sort(sublayers.begin(), sublayers.end(), compareLayerZ);
+ for (int i = 0; i < count; i++)
+ askScreenUpdate |= sublayers[i]->drawTreeSurfacesGL();
+
+ return askScreenUpdate;
+}
+
+bool LayerAndroid::drawTreeSurfacesGL()
+{
+ bool askScreenUpdate = false;
+ if (preserves3D()) {
+ // hit a preserve-3d layer, so render the entire 3D rendering context in z order
+ Vector<LayerAndroid*> contextLayers;
+ collect3dRenderingContext(contextLayers);
+ std::stable_sort(contextLayers.begin(), contextLayers.end(), compareLayerZ);
+
+ for (unsigned int i = 0; i < contextLayers.size(); i++)
+ askScreenUpdate |= contextLayers[i]->drawSurfaceAndChildrenGL();
+ } else
+ askScreenUpdate |= drawSurfaceAndChildrenGL();
+
+ return askScreenUpdate;
+}
+
bool LayerAndroid::drawGL(bool layerTilesDisabled)
{
if (!layerTilesDisabled && m_imageCRC) {
@@ -954,60 +1005,42 @@ void LayerAndroid::setFixedPosition(FixedPositioning* position) {
m_fixedPosition = position;
}
-void LayerAndroid::dumpLayer(FILE* file, int indentLevel) const
+void LayerAndroid::dumpLayer(LayerDumper* dumper) const
{
- writeHexVal(file, indentLevel + 1, "layer", (int)this);
- writeIntVal(file, indentLevel + 1, "layerId", m_uniqueId);
- writeIntVal(file, indentLevel + 1, "haveClip", m_haveClip);
- writeIntVal(file, indentLevel + 1, "isFixed", isPositionFixed());
+ dumper->writeIntVal("layerId", m_uniqueId);
+ dumper->writeIntVal("haveClip", m_haveClip);
+ dumper->writeIntVal("isFixed", isPositionFixed());
- writeFloatVal(file, indentLevel + 1, "opacity", getOpacity());
- writeSize(file, indentLevel + 1, "size", getSize());
- writePoint(file, indentLevel + 1, "position", getPosition());
- writePoint(file, indentLevel + 1, "anchor", getAnchorPoint());
+ dumper->writeFloatVal("opacity", getOpacity());
+ dumper->writeSize("size", getSize());
+ dumper->writePoint("position", getPosition());
+ dumper->writePoint("anchor", getAnchorPoint());
- writeMatrix(file, indentLevel + 1, "drawMatrix", m_drawTransform);
- writeMatrix(file, indentLevel + 1, "transformMatrix", m_transform);
- writeRect(file, indentLevel + 1, "clippingRect", SkRect(m_clippingRect));
+ dumper->writeMatrix("drawMatrix", m_drawTransform);
+ dumper->writeMatrix("transformMatrix", m_transform);
+ dumper->writeRect("clippingRect", SkRect(m_clippingRect));
if (m_content) {
- writeIntVal(file, indentLevel + 1, "m_content.width", m_content->width());
- writeIntVal(file, indentLevel + 1, "m_content.height", m_content->height());
+ dumper->writeIntVal("m_content.width", m_content->width());
+ dumper->writeIntVal("m_content.height", m_content->height());
}
if (m_fixedPosition)
- return m_fixedPosition->dumpLayer(file, indentLevel);
+ m_fixedPosition->dumpLayer(dumper);
}
-void LayerAndroid::dumpLayers(FILE* file, int indentLevel) const
+void LayerAndroid::dumpLayers(LayerDumper* dumper) const
{
- writeln(file, indentLevel, "{");
-
- dumpLayer(file, indentLevel);
+ dumper->beginLayer(subclassName(), this);
+ dumpLayer(dumper);
+ dumper->beginChildren(countChildren());
if (countChildren()) {
- writeln(file, indentLevel + 1, "children = [");
- for (int i = 0; i < countChildren(); i++) {
- if (i > 0)
- writeln(file, indentLevel + 1, ", ");
- getChild(i)->dumpLayers(file, indentLevel + 1);
- }
- writeln(file, indentLevel + 1, "];");
+ for (int i = 0; i < countChildren(); i++)
+ getChild(i)->dumpLayers(dumper);
}
- writeln(file, indentLevel, "}");
-}
-
-void LayerAndroid::dumpToLog() const
-{
- FILE* file = fopen("/data/data/com.android.browser/layertmp", "w");
- dumpLayers(file, 0);
- fclose(file);
- file = fopen("/data/data/com.android.browser/layertmp", "r");
- char buffer[512];
- bzero(buffer, sizeof(buffer));
- while (fgets(buffer, sizeof(buffer), file))
- SkDebugf("%s", buffer);
- fclose(file);
+ dumper->endChildren();
+ dumper->endLayer();
}
LayerAndroid* LayerAndroid::findById(int match)
diff --git a/Source/WebCore/platform/graphics/android/layers/LayerAndroid.h b/Source/WebCore/platform/graphics/android/layers/LayerAndroid.h
index 41f6420..5a1ef57 100644
--- a/Source/WebCore/platform/graphics/android/layers/LayerAndroid.h
+++ b/Source/WebCore/platform/graphics/android/layers/LayerAndroid.h
@@ -73,6 +73,7 @@ class IFrameLayerAndroid;
class LayerMergeState;
class RenderLayer;
class PaintedSurface;
+class LayerDumper;
class TexturesResult {
public:
@@ -100,7 +101,7 @@ public:
CanvasLayer, BaseLayer } SubclassType;
typedef enum { InvalidateNone = 0, InvalidateLayers } InvalidateFlags;
- String subclassName()
+ const char* subclassName() const
{
switch (subclassType()) {
case LayerAndroid::StandardLayer:
@@ -150,6 +151,9 @@ public:
float getScale() { return m_scale; }
+ // draw the layer tree recursively in draw order, grouping and sorting 3d rendering contexts
+ bool drawTreeSurfacesGL();
+
virtual bool drawGL(bool layerTilesDisabled);
virtual bool drawCanvas(SkCanvas* canvas, bool drawChildren, PaintStyle style);
bool drawChildrenCanvas(SkCanvas* canvas, PaintStyle style);
@@ -195,9 +199,7 @@ public:
bool hasAnimations() const;
void addDirtyArea();
- virtual void dumpLayer(FILE*, int indentLevel) const;
- void dumpLayers(FILE*, int indentLevel) const;
- void dumpToLog() const;
+ void dumpLayers(LayerDumper*) const;
virtual IFrameLayerAndroid* updatePosition(SkRect viewport,
IFrameLayerAndroid* parentIframeLayer);
@@ -292,6 +294,7 @@ public:
}
protected:
+ virtual void dumpLayer(LayerDumper*) const;
/** Call this with the current viewport (scrolling, zoom) to update
the position of the fixed layers.
@@ -312,13 +315,14 @@ private:
return contentIsScrollable() || isPositionFixed() || (m_animations.size() != 0);
}
+ // recurse through the current 3d rendering context, adding layers in the context to the vector
+ void collect3dRenderingContext(Vector<LayerAndroid*>& layersInContext);
+ bool drawSurfaceAndChildrenGL();
+
#if DUMP_NAV_CACHE
friend class CachedLayer::Debug; // debugging access only
#endif
- void copyAnimationStartTimes(LayerAndroid* oldLayer);
- bool prepareContext(bool force = false);
-
// -------------------------------------------------------------------
// Fields to be serialized
// -------------------------------------------------------------------
diff --git a/Source/WebCore/platform/graphics/android/layers/LayerContent.h b/Source/WebCore/platform/graphics/android/layers/LayerContent.h
index 10b6507..a18e4c8 100644
--- a/Source/WebCore/platform/graphics/android/layers/LayerContent.h
+++ b/Source/WebCore/platform/graphics/android/layers/LayerContent.h
@@ -42,7 +42,7 @@ class LayerContent : public SkRefCnt {
public:
virtual int width() = 0;
virtual int height() = 0;
- virtual bool isEmpty() { return !width() || !height(); }
+ bool isEmpty() { return !width() || !height(); }
virtual void setCheckForOptimisations(bool check) = 0;
virtual void checkForOptimisations() = 0;
virtual bool hasText() = 0;
diff --git a/Source/WebCore/platform/graphics/android/layers/MediaPlayerPrivateAndroid.h b/Source/WebCore/platform/graphics/android/layers/MediaPlayerPrivateAndroid.h
index 17fd4d8..3b4f630 100644
--- a/Source/WebCore/platform/graphics/android/layers/MediaPlayerPrivateAndroid.h
+++ b/Source/WebCore/platform/graphics/android/layers/MediaPlayerPrivateAndroid.h
@@ -104,8 +104,8 @@ public:
{
return m_videoLayer;
}
- void onStopFullscreen();
-
+ void onStopFullscreen(bool stillPlaying);
+ virtual void enterFullscreenMode() { }
protected:
// Android-specific methods and fields.
static MediaPlayerPrivateInterface* create(MediaPlayer* player);
diff --git a/Source/WebCore/platform/graphics/android/layers/PictureLayerContent.cpp b/Source/WebCore/platform/graphics/android/layers/PictureLayerContent.cpp
index 4398146..e40c9b6 100644
--- a/Source/WebCore/platform/graphics/android/layers/PictureLayerContent.cpp
+++ b/Source/WebCore/platform/graphics/android/layers/PictureLayerContent.cpp
@@ -1,6 +1,10 @@
+#define LOG_TAG "PictureLayerContent"
+#define LOG_NDEBUG 1
+
#include "config.h"
#include "PictureLayerContent.h"
+#include "AndroidLog.h"
#include "InspectorCanvas.h"
#include "SkPicture.h"
@@ -41,16 +45,6 @@ int PictureLayerContent::height()
return m_picture->height();
}
-bool PictureLayerContent::isEmpty()
-{
- if (!m_picture)
- return true;
- if (m_picture->width() == 0
- || m_picture->height() == 0)
- return true;
- return false;
-}
-
void PictureLayerContent::checkForOptimisations()
{
if (!m_checkedContent)
@@ -90,6 +84,7 @@ void PictureLayerContent::draw(SkCanvas* canvas)
if (!m_picture)
return;
+ TRACE_METHOD();
android::Mutex::Autolock lock(m_drawLock);
SkRect r = SkRect::MakeWH(width(), height());
canvas->clipRect(r);
diff --git a/Source/WebCore/platform/graphics/android/layers/PictureLayerContent.h b/Source/WebCore/platform/graphics/android/layers/PictureLayerContent.h
index 1567f44..cf633cb 100644
--- a/Source/WebCore/platform/graphics/android/layers/PictureLayerContent.h
+++ b/Source/WebCore/platform/graphics/android/layers/PictureLayerContent.h
@@ -38,7 +38,6 @@ public:
virtual int width();
virtual int height();
- virtual bool isEmpty();
virtual void setCheckForOptimisations(bool check) { m_checkedContent = !check; }
virtual void checkForOptimisations();
virtual bool hasText();
diff --git a/Source/WebCore/platform/graphics/android/layers/PicturePileLayerContent.cpp b/Source/WebCore/platform/graphics/android/layers/PicturePileLayerContent.cpp
index b648e72..1167bda 100644
--- a/Source/WebCore/platform/graphics/android/layers/PicturePileLayerContent.cpp
+++ b/Source/WebCore/platform/graphics/android/layers/PicturePileLayerContent.cpp
@@ -1,6 +1,10 @@
+#define LOG_TAG "PicturePileLayerContent"
+#define LOG_NDEBUG 1
+
#include "config.h"
#include "PicturePileLayerContent.h"
+#include "AndroidLog.h"
#include "SkCanvas.h"
#include "SkPicture.h"
@@ -8,13 +12,19 @@ namespace WebCore {
PicturePileLayerContent::PicturePileLayerContent(const PicturePile& picturePile)
: m_picturePile(picturePile)
+ , m_hasText(picturePile.hasText())
+ , m_hasContent(!picturePile.isEmpty())
{
}
void PicturePileLayerContent::draw(SkCanvas* canvas)
{
+ TRACE_METHOD();
android::Mutex::Autolock lock(m_drawLock);
m_picturePile.draw(canvas);
+
+ if (CC_UNLIKELY(!m_hasContent))
+ ALOGW("Warning: painting PicturePile without content!");
}
void PicturePileLayerContent::serialize(SkWStream* stream)
diff --git a/Source/WebCore/platform/graphics/android/layers/PicturePileLayerContent.h b/Source/WebCore/platform/graphics/android/layers/PicturePileLayerContent.h
index 4fc123e..9f3a263 100644
--- a/Source/WebCore/platform/graphics/android/layers/PicturePileLayerContent.h
+++ b/Source/WebCore/platform/graphics/android/layers/PicturePileLayerContent.h
@@ -35,18 +35,23 @@ class PicturePileLayerContent : public LayerContent {
public:
PicturePileLayerContent(const PicturePile& picturePile);
- virtual int width() { return m_picturePile.size().width(); }
- virtual int height() { return m_picturePile.size().height(); }
+ // return 0 when no content, so don't have to paint
+ virtual int width() { return m_hasContent ? m_picturePile.size().width() : 0; }
+ virtual int height() { return m_hasContent ? m_picturePile.size().height() : 0; }
+
virtual void setCheckForOptimisations(bool check) {}
- virtual void checkForOptimisations() {}
- virtual bool hasText() { return true; }
+ virtual void checkForOptimisations() {} // already performed, stored in m_hasText/m_hasContent
+ virtual bool hasText() { return m_hasText; }
virtual void draw(SkCanvas* canvas);
virtual void serialize(SkWStream* stream);
virtual PrerenderedInval* prerenderForRect(const IntRect& dirty);
virtual void clearPrerenders();
+ PicturePile* picturePile() { return &m_picturePile; }
private:
PicturePile m_picturePile;
+ bool m_hasText;
+ bool m_hasContent;
};
} // WebCore
diff --git a/Source/WebCore/platform/graphics/android/layers/VideoLayerAndroid.h b/Source/WebCore/platform/graphics/android/layers/VideoLayerAndroid.h
index 5ebf615..07c241f 100644
--- a/Source/WebCore/platform/graphics/android/layers/VideoLayerAndroid.h
+++ b/Source/WebCore/platform/graphics/android/layers/VideoLayerAndroid.h
@@ -44,7 +44,7 @@ namespace WebCore {
// Otherwise will draw a static image.
// NOTE: These values are matching the ones in HTML5VideoView.java
// Please keep them in sync when changed here.
-typedef enum {INITIALIZED, PREPARING, PREPARED, PLAYING, RELEASED} PlayerState;
+typedef enum {INITIALIZED, PREPARING, PREPARED, PLAYING, RESETTED, RELEASED} PlayerState;
class VideoLayerAndroid : public LayerAndroid {
diff --git a/Source/WebCore/platform/graphics/android/layers/VideoLayerManager.cpp b/Source/WebCore/platform/graphics/android/layers/VideoLayerManager.cpp
index a7b3184..1f28cdf 100644
--- a/Source/WebCore/platform/graphics/android/layers/VideoLayerManager.cpp
+++ b/Source/WebCore/platform/graphics/android/layers/VideoLayerManager.cpp
@@ -73,7 +73,7 @@ int VideoLayerManager::getButtonSize()
return VIDEO_BUTTON_SIZE;
}
-GLuint VideoLayerManager::createTextureFromImage(int buttonType)
+GLuint VideoLayerManager::createTextureFromImage(RenderSkinMediaButton::MediaButton buttonType)
{
SkRect rect = SkRect(m_buttonRect);
SkBitmap bitmap;
@@ -83,8 +83,7 @@ GLuint VideoLayerManager::createTextureFromImage(int buttonType)
SkCanvas canvas(bitmap);
canvas.drawARGB(0, 0, 0, 0, SkXfermode::kClear_Mode);
- RenderSkinMediaButton::Draw(&canvas, m_buttonRect, buttonType, true, 0,
- false);
+ RenderSkinMediaButton::Draw(&canvas, m_buttonRect, buttonType, true, false);
GLuint texture;
glGenTextures(1, &texture);
diff --git a/Source/WebCore/platform/graphics/android/layers/VideoLayerManager.h b/Source/WebCore/platform/graphics/android/layers/VideoLayerManager.h
index adce0f4..346afe4 100644
--- a/Source/WebCore/platform/graphics/android/layers/VideoLayerManager.h
+++ b/Source/WebCore/platform/graphics/android/layers/VideoLayerManager.h
@@ -28,6 +28,7 @@
#include "GLUtils.h"
#include "IntRect.h"
+#include "RenderSkinMediaButton.h"
#include <wtf/HashMap.h>
#include <wtf/Vector.h>
#include <utils/threads.h>
@@ -122,7 +123,7 @@ private:
Vector<GLuint> m_retiredTextures;
android::Mutex m_retiredTexturesLock;
- GLuint createTextureFromImage(int buttonType);
+ GLuint createTextureFromImage(RenderSkinMediaButton::MediaButton buttonType);
// Texture for showing the static image will be created at native side.
bool m_createdTexture;
diff --git a/Source/WebCore/platform/graphics/android/rendering/BaseRenderer.cpp b/Source/WebCore/platform/graphics/android/rendering/BaseRenderer.cpp
index 6f679da..0ab72b7 100644
--- a/Source/WebCore/platform/graphics/android/rendering/BaseRenderer.cpp
+++ b/Source/WebCore/platform/graphics/android/rendering/BaseRenderer.cpp
@@ -34,6 +34,7 @@
#include "AndroidLog.h"
#include "GaneshRenderer.h"
#include "GLUtils.h"
+#include "InstrumentedPlatformCanvas.h"
#include "RasterRenderer.h"
#include "SkBitmap.h"
#include "SkBitmapRef.h"
@@ -94,7 +95,10 @@ void BaseRenderer::renderTiledContent(TileRenderInfo& renderInfo)
const bool visualIndicator = TilesManager::instance()->getShowVisualIndicator();
const SkSize& tileSize = renderInfo.tileSize;
- SkCanvas canvas;
+ Color *background = renderInfo.tilePainter->background();
+ InstrumentedPlatformCanvas canvas(TilesManager::instance()->tileWidth(),
+ TilesManager::instance()->tileHeight(),
+ background ? *background : Color::transparent);
setupCanvas(renderInfo, &canvas);
if (!canvas.getDevice()) {
@@ -112,10 +116,8 @@ void BaseRenderer::renderTiledContent(TileRenderInfo& renderInfo)
canvas.translate(-renderInfo.x * tileSize.width(), -renderInfo.y * tileSize.height());
canvas.scale(renderInfo.scale, renderInfo.scale);
renderInfo.tilePainter->paint(&canvas);
- if (renderInfo.baseTile && renderInfo.baseTile->backTexture())
- checkForPureColor(renderInfo, &canvas);
- else
- renderInfo.isPureColor = false;
+
+ checkForPureColor(renderInfo, canvas);
if (visualIndicator) {
double after = currentTimeMS();
@@ -144,6 +146,13 @@ void BaseRenderer::renderTiledContent(TileRenderInfo& renderInfo)
renderingComplete(renderInfo, &canvas);
}
+void BaseRenderer::checkForPureColor(TileRenderInfo& renderInfo, InstrumentedPlatformCanvas& canvas)
+{
+ renderInfo.isPureColor = canvas.isSolidColor();
+ renderInfo.pureColor = canvas.solidColor();
+ deviceCheckForPureColor(renderInfo, &canvas);
+}
+
} // namespace WebCore
#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/android/rendering/BaseRenderer.h b/Source/WebCore/platform/graphics/android/rendering/BaseRenderer.h
index b25a50e..dc8831a 100644
--- a/Source/WebCore/platform/graphics/android/rendering/BaseRenderer.h
+++ b/Source/WebCore/platform/graphics/android/rendering/BaseRenderer.h
@@ -37,6 +37,7 @@ class SkDevice;
namespace WebCore {
+class InstrumentedPlatformCanvas;
class TextureInfo;
class TilePainter;
class Tile;
@@ -87,7 +88,10 @@ protected:
virtual void setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* canvas) = 0;
virtual void renderingComplete(const TileRenderInfo& renderInfo, SkCanvas* canvas) = 0;
- virtual void checkForPureColor(TileRenderInfo& renderInfo, SkCanvas* canvas) = 0;
+ void checkForPureColor(TileRenderInfo& renderInfo, InstrumentedPlatformCanvas& canvas);
+
+ // performs additional pure color check, renderInfo.isPureColor may already be set to true
+ virtual void deviceCheckForPureColor(TileRenderInfo& renderInfo, SkCanvas* canvas) = 0;
void drawTileInfo(SkCanvas* canvas, const TileRenderInfo& renderInfo,
int updateCount, double renderDuration);
diff --git a/Source/WebCore/platform/graphics/android/rendering/GLExtras.cpp b/Source/WebCore/platform/graphics/android/rendering/GLExtras.cpp
index 2c114d6..175c552 100644
--- a/Source/WebCore/platform/graphics/android/rendering/GLExtras.cpp
+++ b/Source/WebCore/platform/graphics/android/rendering/GLExtras.cpp
@@ -35,7 +35,6 @@
#include "IntRect.h"
#include "SkPath.h"
#include "TilesManager.h"
-#include "android_graphics.h"
// Touch ring border width. This is doubled if the ring is not pressed
#define RING_BORDER_WIDTH 1
diff --git a/Source/WebCore/platform/graphics/android/rendering/GLUtils.cpp b/Source/WebCore/platform/graphics/android/rendering/GLUtils.cpp
index 4a0b77b..1a54cb7 100644
--- a/Source/WebCore/platform/graphics/android/rendering/GLUtils.cpp
+++ b/Source/WebCore/platform/graphics/android/rendering/GLUtils.cpp
@@ -384,6 +384,7 @@ bool GLUtils::isPureColorBitmap(const SkBitmap& bitmap, Color& pureColor)
// If the bitmap is the pure color, skip the transfer step, and update the Tile Info.
// This check is taking < 1ms if we do full bitmap check per tile.
// TODO: use the SkPicture to determine whether or not a tile is single color.
+ TRACE_METHOD();
pureColor = Color(Color::transparent);
bitmap.lockPixels();
bool sameColor = true;
@@ -445,7 +446,7 @@ bool GLUtils::skipTransferForPureColor(const TileRenderInfo* renderInfo,
}
void GLUtils::paintTextureWithBitmap(const TileRenderInfo* renderInfo,
- const SkBitmap& bitmap)
+ SkBitmap& bitmap)
{
if (!renderInfo)
return;
@@ -471,7 +472,7 @@ void GLUtils::paintTextureWithBitmap(const TileRenderInfo* renderInfo,
}
}
-void GLUtils::updateQueueWithBitmap(const TileRenderInfo* renderInfo, const SkBitmap& bitmap)
+void GLUtils::updateQueueWithBitmap(const TileRenderInfo* renderInfo, SkBitmap& bitmap)
{
if (!renderInfo
|| !renderInfo->textureInfo
@@ -483,6 +484,7 @@ void GLUtils::updateQueueWithBitmap(const TileRenderInfo* renderInfo, const SkBi
bool GLUtils::updateSharedSurfaceTextureWithBitmap(ANativeWindow* anw, const SkBitmap& bitmap)
{
+ TRACE_METHOD();
SkAutoLockPixels alp(bitmap);
if (!bitmap.getPixels())
return false;
diff --git a/Source/WebCore/platform/graphics/android/rendering/GLUtils.h b/Source/WebCore/platform/graphics/android/rendering/GLUtils.h
index c2dec7d..3b093d1 100644
--- a/Source/WebCore/platform/graphics/android/rendering/GLUtils.h
+++ b/Source/WebCore/platform/graphics/android/rendering/GLUtils.h
@@ -80,8 +80,8 @@ public:
static void createEGLImageFromTexture(GLuint texture, EGLImageKHR* image);
static void createTextureFromEGLImage(GLuint texture, EGLImageKHR image, GLint filter = GL_LINEAR);
- static void paintTextureWithBitmap(const TileRenderInfo* renderInfo, const SkBitmap& bitmap);
- static void updateQueueWithBitmap(const TileRenderInfo* , const SkBitmap& bitmap);
+ static void paintTextureWithBitmap(const TileRenderInfo* renderInfo, SkBitmap& bitmap);
+ static void updateQueueWithBitmap(const TileRenderInfo* , SkBitmap& bitmap);
static bool updateSharedSurfaceTextureWithBitmap(ANativeWindow* anw, const SkBitmap& bitmap);
static void convertToTransformationMatrix(const float* matrix, TransformationMatrix& transformMatrix);
diff --git a/Source/WebCore/platform/graphics/android/rendering/GaneshRenderer.cpp b/Source/WebCore/platform/graphics/android/rendering/GaneshRenderer.cpp
index d779af4..8b5e30a 100644
--- a/Source/WebCore/platform/graphics/android/rendering/GaneshRenderer.cpp
+++ b/Source/WebCore/platform/graphics/android/rendering/GaneshRenderer.cpp
@@ -94,7 +94,8 @@ void GaneshRenderer::renderingComplete(const TileRenderInfo& renderInfo, SkCanva
// tile's ANativeWindow (i.e. SurfaceTexture) buffer
TransferQueue* tileQueue = TilesManager::instance()->transferQueue();
eglSwapBuffers(eglGetCurrentDisplay(), tileQueue->m_eglSurface);
- tileQueue->addItemInTransferQueue(&renderInfo, GpuUpload, 0);
+ SkBitmap dummyBitmap;
+ tileQueue->addItemInTransferQueue(&renderInfo, GpuUpload, dummyBitmap);
tileQueue->unlockQueue();
}
diff --git a/Source/WebCore/platform/graphics/android/rendering/GaneshRenderer.h b/Source/WebCore/platform/graphics/android/rendering/GaneshRenderer.h
index cdd9f3e..77982e8 100644
--- a/Source/WebCore/platform/graphics/android/rendering/GaneshRenderer.h
+++ b/Source/WebCore/platform/graphics/android/rendering/GaneshRenderer.h
@@ -48,9 +48,7 @@ protected:
virtual void setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* canvas);
virtual void renderingComplete(const TileRenderInfo& renderInfo, SkCanvas* canvas);
- virtual void checkForPureColor(TileRenderInfo& renderInfo, SkCanvas* canvas) {
- renderInfo.isPureColor = false;
- }
+ virtual void deviceCheckForPureColor(TileRenderInfo& renderInfo, SkCanvas* canvas) {}
};
diff --git a/Source/WebCore/platform/graphics/android/rendering/ImageTexture.cpp b/Source/WebCore/platform/graphics/android/rendering/ImageTexture.cpp
index aa84427..db03753 100644
--- a/Source/WebCore/platform/graphics/android/rendering/ImageTexture.cpp
+++ b/Source/WebCore/platform/graphics/android/rendering/ImageTexture.cpp
@@ -101,6 +101,7 @@ ImageTexture::~ImageTexture()
delete m_image;
delete m_tileGrid;
SkSafeUnref(m_picture);
+ ImagesManager::instance()->onImageTextureDestroy(m_crc);
}
SkBitmap* ImageTexture::convertBitmap(SkBitmap* bitmap)
diff --git a/Source/WebCore/platform/graphics/android/rendering/ImagesManager.cpp b/Source/WebCore/platform/graphics/android/rendering/ImagesManager.cpp
index 82ea3fa..d2bd8a0 100644
--- a/Source/WebCore/platform/graphics/android/rendering/ImagesManager.cpp
+++ b/Source/WebCore/platform/graphics/android/rendering/ImagesManager.cpp
@@ -102,12 +102,20 @@ void ImagesManager::releaseImage(unsigned imgCRC)
android::Mutex::Autolock lock(m_imagesLock);
if (m_images.contains(imgCRC)) {
ImageTexture* image = m_images.get(imgCRC);
- if (image->getRefCnt() == 1)
- m_images.remove(imgCRC);
+ // don't need to remove image from the HashMap, it will unregister
+ // itself by calling onImageTextureDestroy().
+
SkSafeUnref(image);
}
}
+void ImagesManager::onImageTextureDestroy(unsigned imgCRC)
+{
+ // NOTE: all unrefs must go through releaseImage, to ensure that
+ // onImageTextureDestroy is called under the m_imagesLock
+ m_images.remove(imgCRC);
+}
+
int ImagesManager::nbTextures()
{
android::Mutex::Autolock lock(m_imagesLock);
diff --git a/Source/WebCore/platform/graphics/android/rendering/ImagesManager.h b/Source/WebCore/platform/graphics/android/rendering/ImagesManager.h
index b915a46..718cfdd 100644
--- a/Source/WebCore/platform/graphics/android/rendering/ImagesManager.h
+++ b/Source/WebCore/platform/graphics/android/rendering/ImagesManager.h
@@ -47,6 +47,9 @@ public:
ImageTexture* retainImage(unsigned imgCRC);
void releaseImage(unsigned imgCRC);
+ // should be called only by ~ImageTexture()
+ void onImageTextureDestroy(unsigned imgCRC);
+
bool prepareTextures(GLWebViewState*);
int nbTextures();
diff --git a/Source/WebCore/platform/graphics/android/rendering/InstrumentedPlatformCanvas.h b/Source/WebCore/platform/graphics/android/rendering/InstrumentedPlatformCanvas.h
new file mode 100644
index 0000000..cc3ef55
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/rendering/InstrumentedPlatformCanvas.h
@@ -0,0 +1,314 @@
+/*
+ * Copyright (C) 2011 Research In Motion Limited. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef InstrumentedPlatformCanvas_h
+#define InstrumentedPlatformCanvas_h
+
+#include "SkCanvas.h"
+
+#define DEBUG_SKIA_DRAWING 0
+#if DEBUG_SKIA_DRAWING
+#include "AndroidLog.h" // NOTE: AndroidLog.h normally shouldn't be included in a header
+#include "FloatRect.h"
+#define WRAPCANVAS_LOG_ENTRY(...) {ALOGD("non-rect %s, m_isSolidColor %d", __FUNCTION__, m_isSolidColor);}
+#else
+#define WRAPCANVAS_LOG_ENTRY(...) ((void)0)
+#endif
+
+namespace WebCore {
+
+class InstrumentedPlatformCanvas : public SkCanvas {
+public:
+ InstrumentedPlatformCanvas(int width, int height, Color initialColor)
+ : m_size(width, height)
+ , m_isSolidColor(true)
+ , m_solidColor(initialColor)
+ {
+ }
+
+ virtual ~InstrumentedPlatformCanvas() { }
+
+ bool isSolidColor() const { return m_isSolidColor; }
+ Color solidColor() const { return m_solidColor; }
+
+ // overrides from SkCanvas
+ virtual int save(SaveFlags flags = kMatrixClip_SaveFlag)
+ {
+ WRAPCANVAS_LOG_ENTRY("");
+ return SkCanvas::save(flags);
+ }
+
+ virtual int saveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags flags)
+ {
+ WRAPCANVAS_LOG_ENTRY("");
+ m_isSolidColor = false;
+ return SkCanvas::saveLayer(bounds, paint, flags);
+ }
+
+ virtual void restore()
+ {
+ WRAPCANVAS_LOG_ENTRY("");
+ SkCanvas::restore();
+ }
+
+ virtual bool translate(SkScalar dx, SkScalar dy)
+ {
+ WRAPCANVAS_LOG_ENTRY("");
+ return SkCanvas::translate(dx, dy);
+ }
+
+ virtual bool scale(SkScalar sx, SkScalar sy)
+ {
+ WRAPCANVAS_LOG_ENTRY("");
+ return SkCanvas::scale(sx, sy);
+ }
+
+ virtual bool rotate(SkScalar degrees)
+ {
+ WRAPCANVAS_LOG_ENTRY("");
+ return SkCanvas::rotate(degrees);
+ }
+
+ virtual bool skew(SkScalar sx, SkScalar sy)
+ {
+ WRAPCANVAS_LOG_ENTRY("");
+ return SkCanvas::skew(sx, sy);
+ }
+
+ virtual bool concat(const SkMatrix& matrix)
+ {
+ WRAPCANVAS_LOG_ENTRY("");
+ return SkCanvas::concat(matrix);
+ }
+
+ virtual void setMatrix(const SkMatrix& matrix)
+ {
+ WRAPCANVAS_LOG_ENTRY("");
+ SkCanvas::setMatrix(matrix);
+ }
+
+ virtual bool clipRect(const SkRect& rect, SkRegion::Op op)
+ {
+ WRAPCANVAS_LOG_ENTRY("");
+ return SkCanvas::clipRect(rect, op);
+ }
+
+ virtual bool clipPath(const SkPath& path, SkRegion::Op op)
+ {
+ WRAPCANVAS_LOG_ENTRY("");
+ m_isSolidColor = false;
+ return SkCanvas::clipPath(path, op);
+ }
+
+ virtual bool clipRegion(const SkRegion& region, SkRegion::Op op)
+ {
+ WRAPCANVAS_LOG_ENTRY("");
+ if (!region.isRect())
+ m_isSolidColor = false;
+ return SkCanvas::clipRegion(region, op);
+ }
+
+ virtual void clear(SkColor color)
+ {
+ WRAPCANVAS_LOG_ENTRY("");
+ m_isSolidColor = true;
+ m_solidColor = Color(color);
+ SkCanvas::clear(color);
+ }
+
+ virtual void drawPaint(const SkPaint& paint)
+ {
+ WRAPCANVAS_LOG_ENTRY("");
+ m_isSolidColor = false;
+ SkCanvas::drawPaint(paint);
+ }
+
+ virtual void drawPoints(PointMode mode, size_t count, const SkPoint pts[],
+ const SkPaint& paint)
+ {
+ WRAPCANVAS_LOG_ENTRY("");
+ m_isSolidColor = false;
+ SkCanvas::drawPoints(mode, count, pts, paint);
+ }
+
+ bool rectFullyOverlaps(const SkRect& rect)
+ {
+ IntRect canvasRect(IntPoint(), m_size);
+ if (getTotalMatrix().rectStaysRect()
+ && getTotalClip().contains(canvasRect)) {
+ const SkMatrix& matrix = getTotalMatrix();
+ SkRect mapped;
+ matrix.mapRect(&mapped, rect);
+ return mapped.contains(canvasRect);
+ }
+ return false;
+ }
+
+ virtual void drawRect(const SkRect& rect, const SkPaint& paint)
+ {
+
+#if DEBUG_SKIA_DRAWING
+ FloatRect rectToDraw = rect;
+ ALOGD("drawrect " FLOAT_RECT_FORMAT ", is solid %d", FLOAT_RECT_ARGS(rectToDraw), m_isSolidColor);
+#endif
+
+ if (m_isSolidColor) {
+ Color color = solidColor(paint);
+ if (color != m_solidColor) {
+ if (color.isValid() && rectFullyOverlaps(rect))
+ m_solidColor = color;
+ else
+ m_isSolidColor = false;
+ }
+ }
+
+ SkCanvas::drawRect(rect, paint);
+ }
+
+ virtual void drawPath(const SkPath& path, const SkPaint& paint)
+ {
+ WRAPCANVAS_LOG_ENTRY("");
+ m_isSolidColor = false;
+ SkCanvas::drawPath(path, paint);
+ }
+
+ virtual void drawBitmap(const SkBitmap& bitmap, SkScalar left,
+ SkScalar top, const SkPaint* paint)
+ {
+ WRAPCANVAS_LOG_ENTRY("");
+ m_isSolidColor = false;
+ SkCanvas::drawBitmap(bitmap, left, top, paint);
+ }
+
+ virtual void drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src,
+ const SkRect& dst, const SkPaint* paint)
+ {
+ WRAPCANVAS_LOG_ENTRY("");
+ m_isSolidColor = false;
+ SkCanvas::drawBitmapRect(bitmap, src, dst, paint);
+ }
+
+ virtual void drawBitmapMatrix(const SkBitmap& bitmap,
+ const SkMatrix& matrix, const SkPaint* paint)
+ {
+ WRAPCANVAS_LOG_ENTRY("");
+ m_isSolidColor = false;
+ SkCanvas::drawBitmapMatrix(bitmap, matrix, paint);
+ }
+
+ virtual void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
+ const SkRect& dst, const SkPaint* paint = 0)
+ {
+ WRAPCANVAS_LOG_ENTRY("");
+ m_isSolidColor = false;
+ SkCanvas::drawBitmapNine(bitmap, center, dst, paint);
+ }
+
+ virtual void drawSprite(const SkBitmap& bitmap, int left, int top,
+ const SkPaint* paint)
+ {
+ WRAPCANVAS_LOG_ENTRY("");
+ m_isSolidColor = false;
+ SkCanvas::drawSprite(bitmap, left, top, paint);
+ }
+
+ virtual void drawText(const void* text, size_t byteLength, SkScalar x,
+ SkScalar y, const SkPaint& paint)
+ {
+ WRAPCANVAS_LOG_ENTRY("");
+ m_isSolidColor = false;
+ SkCanvas::drawText(text, byteLength, x, y, paint);
+ }
+
+ virtual void drawPosText(const void* text, size_t byteLength,
+ const SkPoint pos[], const SkPaint& paint)
+ {
+ WRAPCANVAS_LOG_ENTRY("");
+ m_isSolidColor = false;
+ SkCanvas::drawPosText(text, byteLength, pos, paint);
+ }
+
+ virtual void drawPosTextH(const void* text, size_t byteLength,
+ const SkScalar xpos[], SkScalar constY, const SkPaint& paint)
+ {
+ WRAPCANVAS_LOG_ENTRY("");
+ m_isSolidColor = false;
+ SkCanvas::drawPosTextH(text, byteLength, xpos, constY, paint);
+ }
+
+ virtual void drawTextOnPath(const void* text, size_t byteLength,
+ const SkPath& path, const SkMatrix* matrix, const SkPaint& paint)
+ {
+ WRAPCANVAS_LOG_ENTRY("");
+ m_isSolidColor = false;
+ SkCanvas::drawTextOnPath(text, byteLength, path, matrix, paint);
+ }
+
+ virtual void drawPicture(SkPicture& picture)
+ {
+ WRAPCANVAS_LOG_ENTRY("");
+ m_isSolidColor = false;
+ SkCanvas::drawPicture(picture);
+ }
+
+ virtual void drawVertices(VertexMode mode, int vertexCount,
+ const SkPoint vertices[], const SkPoint texs[],
+ const SkColor colors[], SkXfermode* xfermode,
+ const uint16_t indices[], int indexCount, const SkPaint& paint)
+ {
+ WRAPCANVAS_LOG_ENTRY("");
+ m_isSolidColor = false;
+ SkCanvas::drawVertices(mode, vertexCount, vertices, texs,
+ colors, xfermode, indices, indexCount, paint);
+ }
+
+ virtual void drawData(const void* data, size_t size)
+ {
+ WRAPCANVAS_LOG_ENTRY("");
+ m_isSolidColor = false;
+ SkCanvas::drawData(data, size);
+ }
+
+private:
+ Color solidColor(const SkPaint& paint)
+ {
+ if (paint.getStyle() != SkPaint::kFill_Style)
+ return Color();
+ if (paint.getLooper() || paint.getShader())
+ return Color();
+
+ SkXfermode::Mode mode;
+ SkXfermode::AsMode(paint.getXfermode(), &mode);
+ if (mode == SkXfermode::kClear_Mode)
+ return Color(0, 0, 0, 0);
+
+ if ((mode == SkXfermode::kSrcOver_Mode && paint.getAlpha() == 255)
+ || mode == SkXfermode::kSrc_Mode)
+ return Color(paint.getColor());
+ return Color();
+ }
+
+ IntSize m_size;
+ bool m_isSolidColor;
+ Color m_solidColor;
+ SkPaint m_solidPaint;
+};
+
+} // namespace WebCore
+
+#endif // InstrumentedPlatformCanvas_h
diff --git a/Source/WebCore/platform/graphics/android/rendering/PaintTileOperation.cpp b/Source/WebCore/platform/graphics/android/rendering/PaintTileOperation.cpp
index 3fcbdb2..c1b91a3 100644
--- a/Source/WebCore/platform/graphics/android/rendering/PaintTileOperation.cpp
+++ b/Source/WebCore/platform/graphics/android/rendering/PaintTileOperation.cpp
@@ -79,12 +79,12 @@ bool PaintTileOperation::operator==(const QueuedOperation* operation)
return op->m_tile == m_tile;
}
-void PaintTileOperation::run()
+void PaintTileOperation::run(BaseRenderer* renderer)
{
TRACE_METHOD();
if (m_tile) {
- m_tile->paintBitmap(m_painter);
+ m_tile->paintBitmap(m_painter, renderer);
m_tile->setRepaintPending(false);
m_tile = 0;
}
diff --git a/Source/WebCore/platform/graphics/android/rendering/PaintTileOperation.h b/Source/WebCore/platform/graphics/android/rendering/PaintTileOperation.h
index c82cdcd..ecd3ce9 100644
--- a/Source/WebCore/platform/graphics/android/rendering/PaintTileOperation.h
+++ b/Source/WebCore/platform/graphics/android/rendering/PaintTileOperation.h
@@ -42,7 +42,7 @@ public:
GLWebViewState* state, bool isLowResPrefetch);
virtual ~PaintTileOperation();
virtual bool operator==(const QueuedOperation* operation);
- virtual void run();
+ virtual void run(BaseRenderer* renderer);
virtual void* uniquePtr() { return m_tile; }
// returns a rendering priority for m_tile, lower values are processed faster
virtual int priority();
diff --git a/Source/WebCore/platform/graphics/android/rendering/QueuedOperation.h b/Source/WebCore/platform/graphics/android/rendering/QueuedOperation.h
index 7625528..fe6f8a3 100644
--- a/Source/WebCore/platform/graphics/android/rendering/QueuedOperation.h
+++ b/Source/WebCore/platform/graphics/android/rendering/QueuedOperation.h
@@ -28,10 +28,12 @@
namespace WebCore {
+class BaseRenderer;
+
class QueuedOperation {
public:
virtual ~QueuedOperation() {}
- virtual void run() = 0;
+ virtual void run(BaseRenderer* renderer) = 0;
virtual bool operator==(const QueuedOperation* operation) = 0;
virtual void* uniquePtr() = 0;
virtual int priority() = 0;
diff --git a/Source/WebCore/platform/graphics/android/rendering/RasterRenderer.cpp b/Source/WebCore/platform/graphics/android/rendering/RasterRenderer.cpp
index 47e5c17..fd26380 100644
--- a/Source/WebCore/platform/graphics/android/rendering/RasterRenderer.cpp
+++ b/Source/WebCore/platform/graphics/android/rendering/RasterRenderer.cpp
@@ -42,20 +42,17 @@
namespace WebCore {
-SkBitmap* RasterRenderer::g_bitmap = 0;
-
-RasterRenderer::RasterRenderer() : BaseRenderer(BaseRenderer::Raster)
+RasterRenderer::RasterRenderer()
+ : BaseRenderer(BaseRenderer::Raster)
+ , m_bitmapIsPureColor(false)
{
+ m_bitmap.setConfig(SkBitmap::kARGB_8888_Config,
+ TilesManager::instance()->tileWidth(),
+ TilesManager::instance()->tileHeight());
+ m_bitmap.allocPixels();
#ifdef DEBUG_COUNT
ClassTracker::instance()->increment("RasterRenderer");
#endif
- if (!g_bitmap) {
- g_bitmap = new SkBitmap();
- g_bitmap->setConfig(SkBitmap::kARGB_8888_Config,
- TilesManager::instance()->tileWidth(),
- TilesManager::instance()->tileHeight());
- g_bitmap->allocPixels();
- }
}
RasterRenderer::~RasterRenderer()
@@ -67,9 +64,14 @@ RasterRenderer::~RasterRenderer()
void RasterRenderer::setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* canvas)
{
+ TRACE_METHOD();
+
if (renderInfo.baseTile->isLayerTile()) {
- g_bitmap->setIsOpaque(false);
- g_bitmap->eraseARGB(0, 0, 0, 0);
+ m_bitmap.setIsOpaque(false);
+
+ // clear bitmap if necessary
+ if (!m_bitmapIsPureColor || m_bitmapPureColor != Color::transparent)
+ m_bitmap.eraseARGB(0, 0, 0, 0);
} else {
Color defaultBackground = Color::white;
Color* background = renderInfo.tilePainter->background();
@@ -78,12 +80,15 @@ void RasterRenderer::setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* can
background = &defaultBackground;
}
ALOGV("setupCanvas use background on Base Layer %x", background->rgb());
- g_bitmap->setIsOpaque(!background->hasAlpha());
- g_bitmap->eraseARGB(background->alpha(), background->red(),
- background->green(), background->blue());
+ m_bitmap.setIsOpaque(!background->hasAlpha());
+
+ // fill background color if necessary
+ if (!m_bitmapIsPureColor || m_bitmapPureColor != *background)
+ m_bitmap.eraseARGB(background->alpha(), background->red(),
+ background->green(), background->blue());
}
- SkDevice* device = new SkDevice(*g_bitmap);
+ SkDevice* device = new SkDevice(m_bitmap);
canvas->setDevice(device);
@@ -92,14 +97,20 @@ void RasterRenderer::setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* can
void RasterRenderer::renderingComplete(const TileRenderInfo& renderInfo, SkCanvas* canvas)
{
- const SkBitmap& bitmap = canvas->getDevice()->accessBitmap(false);
- GLUtils::paintTextureWithBitmap(&renderInfo, bitmap);
+ // We may swap the content of m_bitmap with the bitmap in the transfer queue.
+ GLUtils::paintTextureWithBitmap(&renderInfo, m_bitmap);
}
-void RasterRenderer::checkForPureColor(TileRenderInfo& renderInfo, SkCanvas* canvas)
+void RasterRenderer::deviceCheckForPureColor(TileRenderInfo& renderInfo, SkCanvas* canvas)
{
- const SkBitmap& bitmap = canvas->getDevice()->accessBitmap(false);
- renderInfo.isPureColor = GLUtils::isPureColorBitmap(bitmap, renderInfo.pureColor);
+ if (!renderInfo.isPureColor) {
+ // base renderer may have already determined isPureColor, so only do the
+ // brute force check if needed
+ renderInfo.isPureColor = GLUtils::isPureColorBitmap(m_bitmap, renderInfo.pureColor);
+ }
+
+ m_bitmapIsPureColor = renderInfo.isPureColor;
+ m_bitmapPureColor = renderInfo.pureColor;
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/rendering/RasterRenderer.h b/Source/WebCore/platform/graphics/android/rendering/RasterRenderer.h
index 39e00f2..791c6b6 100644
--- a/Source/WebCore/platform/graphics/android/rendering/RasterRenderer.h
+++ b/Source/WebCore/platform/graphics/android/rendering/RasterRenderer.h
@@ -46,14 +46,14 @@ public:
~RasterRenderer();
protected:
-
virtual void setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* canvas);
virtual void renderingComplete(const TileRenderInfo& renderInfo, SkCanvas* canvas);
- virtual void checkForPureColor(TileRenderInfo& renderInfo, SkCanvas* canvas);
+ virtual void deviceCheckForPureColor(TileRenderInfo& renderInfo, SkCanvas* canvas);
private:
- static SkBitmap* g_bitmap;
-
+ SkBitmap m_bitmap;
+ bool m_bitmapIsPureColor;
+ Color m_bitmapPureColor;
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/rendering/ShaderProgram.cpp b/Source/WebCore/platform/graphics/android/rendering/ShaderProgram.cpp
index d7266a3..5920007 100644
--- a/Source/WebCore/platform/graphics/android/rendering/ShaderProgram.cpp
+++ b/Source/WebCore/platform/graphics/android/rendering/ShaderProgram.cpp
@@ -257,6 +257,16 @@ GLint ShaderProgram::createProgram(const char* pVertexSource, const char* pFragm
return program;
}
+void ShaderProgram::initProgram(ShaderType type)
+{
+ // initialize shader's static texSampler and position values
+ glUseProgram(m_handleArray[type].programHandle);
+
+ if (m_handleArray[type].texSamplerHandle != -1)
+ glUniform1i(m_handleArray[type].texSamplerHandle, 0);
+ glEnableVertexAttribArray(m_handleArray[type].positionHandle);
+}
+
ShaderProgram::ShaderProgram()
: m_blendingEnabled(false)
, m_contrast(1)
@@ -264,6 +274,11 @@ ShaderProgram::ShaderProgram()
, m_currentScale(1.0f)
, m_needsInit(true)
{
+ // initialize the matrix to calculate z values correctly, since it can be
+ // used for that before setupDrawing is called.
+ GLUtils::setOrthographicMatrix(m_visibleContentRectProjectionMatrix,
+ 0,0,1,1,
+ -1000, 1000);
}
void ShaderProgram::cleanupGLResources()
@@ -321,6 +336,7 @@ void ShaderProgram::initGLResources()
GLint pureColorValue = glGetUniformLocation(pureColorProgram, "inputColor");
m_handleArray[PureColor].init(-1, -1, pureColorPosition, pureColorProgram,
pureColorProjMtx, pureColorValue, -1, -1, -1, -1);
+ initProgram(PureColor);
GLint tex2DAlpha = glGetUniformLocation(tex2DProgram, "alpha");
GLint tex2DPosition = glGetAttribLocation(tex2DProgram, "vPosition");
@@ -329,6 +345,7 @@ void ShaderProgram::initGLResources()
GLint tex2DFillPortion = glGetUniformLocation(tex2DProgram, "fillPortion");
m_handleArray[Tex2D].init(tex2DAlpha, -1, tex2DPosition, tex2DProgram,
tex2DProjMtx, -1, tex2DTexSampler, -1, tex2DFillPortion, -1);
+ initProgram(Tex2D);
GLint tex2DInvAlpha = glGetUniformLocation(tex2DInvProgram, "alpha");
GLint tex2DInvContrast = glGetUniformLocation(tex2DInvProgram, "contrast");
@@ -340,6 +357,7 @@ void ShaderProgram::initGLResources()
tex2DInvPosition, tex2DInvProgram,
tex2DInvProjMtx, -1,
tex2DInvTexSampler, -1, tex2DInvFillPortion, -1);
+ initProgram(Tex2DInv);
GLint repeatTexAlpha = glGetUniformLocation(repeatTexProgram, "alpha");
GLint repeatTexPosition = glGetAttribLocation(repeatTexProgram, "vPosition");
@@ -351,6 +369,7 @@ void ShaderProgram::initGLResources()
repeatTexProgram,repeatTexProjMtx, -1,
repeatTexTexSampler, -1, repeatTexFillPortion,
repeatTexScale);
+ initProgram(RepeatTex);
GLint repeatTexInvAlpha = glGetUniformLocation(repeatTexInvProgram, "alpha");
GLint repeatTexInvContrast = glGetUniformLocation(tex2DInvProgram, "contrast");
@@ -364,6 +383,7 @@ void ShaderProgram::initGLResources()
repeatTexInvProjMtx, -1,
repeatTexInvTexSampler, -1,
repeatTexInvFillPortion, repeatTexInvScale);
+ initProgram(RepeatTexInv);
GLint texOESAlpha = glGetUniformLocation(texOESProgram, "alpha");
GLint texOESPosition = glGetAttribLocation(texOESProgram, "vPosition");
@@ -372,6 +392,7 @@ void ShaderProgram::initGLResources()
GLint texOESFillPortion = glGetUniformLocation(texOESProgram, "fillPortion");
m_handleArray[TexOES].init(texOESAlpha, -1, texOESPosition, texOESProgram,
texOESProjMtx, -1, texOESTexSampler, -1, texOESFillPortion, -1);
+ initProgram(TexOES);
GLint texOESInvAlpha = glGetUniformLocation(texOESInvProgram, "alpha");
GLint texOESInvContrast = glGetUniformLocation(texOESInvProgram, "contrast");
@@ -383,6 +404,7 @@ void ShaderProgram::initGLResources()
texOESInvPosition, texOESInvProgram,
texOESInvProjMtx, -1,
texOESInvTexSampler, -1, texOESInvFillPortion, -1);
+ initProgram(TexOESInv);
GLint videoPosition = glGetAttribLocation(videoProgram, "vPosition");
GLint videoProjMtx = glGetUniformLocation(videoProgram, "projectionMatrix");
@@ -391,6 +413,7 @@ void ShaderProgram::initGLResources()
m_handleArray[Video].init(-1, -1, videoPosition, videoProgram,
videoProjMtx, -1, videoTexSampler,
videoTexMtx, -1, -1);
+ initProgram(Video);
const GLfloat coord[] = {
0.0f, 0.0f, // C
@@ -539,6 +562,16 @@ void ShaderProgram::setupDrawing(const IntRect& invScreenRect,
// Set up m_clipProjectionMatrix, m_currentScale and m_webViewMatrix before
// calling this function.
setupSurfaceProjectionMatrix();
+
+ //// initialize frame-constant values ////
+ glActiveTexture(GL_TEXTURE0);
+ glBindBuffer(GL_ARRAY_BUFFER, m_textureBuffer[0]);
+
+ //// initialize GL cache ////
+ m_cachedProgramType = UndefinedShader;
+ m_cachedOpacity = -1;
+ m_cachedFillPortion = FloatRect();
+ m_cachedPureColor = Color();
}
// Calculate the right color value sent into the shader considering the (0,1)
@@ -695,23 +728,34 @@ void ShaderProgram::drawQuadInternal(ShaderType type, const GLfloat* matrix,
const Color& pureColor, const FloatRect& fillPortion,
const FloatSize& repeatScale)
{
- glUseProgram(m_handleArray[type].programHandle);
+ if (m_cachedProgramType != type) {
+ glUseProgram(m_handleArray[type].programHandle);
+ glVertexAttribPointer(m_handleArray[type].positionHandle,
+ 2, GL_FLOAT, GL_FALSE, 0, 0);
+ m_cachedProgramType = type;
+ m_cachedOpacity = -1; // reset cache for variable shared by multiple programs
+ }
glUniformMatrix4fv(m_handleArray[type].projMtxHandle, 1, GL_FALSE, matrix);
if (type != PureColor) {
- glActiveTexture(GL_TEXTURE0);
- glUniform1i(m_handleArray[type].texSamplerHandle, 0);
glBindTexture(textureTarget, textureId);
glTexParameteri(textureTarget, GL_TEXTURE_MIN_FILTER, filter);
glTexParameteri(textureTarget, GL_TEXTURE_MAG_FILTER, filter);
- glUniform1f(m_handleArray[type].alphaHandle, opacity);
+
+ if (m_cachedOpacity != opacity) {
+ glUniform1f(m_handleArray[type].alphaHandle, opacity);
+ m_cachedOpacity = opacity;
+ }
GLint contrastHandle = m_handleArray[type].contrastHandle;
if (contrastHandle != -1)
glUniform1f(contrastHandle, m_contrast);
- glUniform4f(m_handleArray[type].fillPortionHandle, fillPortion.x(), fillPortion.y(),
- fillPortion.width(), fillPortion.height());
+ if (m_cachedFillPortion != fillPortion) {
+ glUniform4f(m_handleArray[type].fillPortionHandle, fillPortion.x(), fillPortion.y(),
+ fillPortion.width(), fillPortion.height());
+ m_cachedFillPortion = fillPortion;
+ }
// Only when we have repeat scale, this handle can be >= 0;
if (m_handleArray[type].scaleHandle != -1) {
@@ -719,16 +763,14 @@ void ShaderProgram::drawQuadInternal(ShaderType type, const GLfloat* matrix,
repeatScale.width(), repeatScale.height());
}
} else {
- glUniform4f(m_handleArray[type].pureColorHandle,
- pureColor.red() / 255.0, pureColor.green() / 255.0,
- pureColor.blue() / 255.0, pureColor.alpha() / 255.0);
+ if (m_cachedPureColor != pureColor) {
+ glUniform4f(m_handleArray[type].pureColorHandle,
+ pureColor.red() / 255.0, pureColor.green() / 255.0,
+ pureColor.blue() / 255.0, pureColor.alpha() / 255.0);
+ m_cachedPureColor = pureColor;
+ }
}
- GLint positionHandle = m_handleArray[type].positionHandle;
- glBindBuffer(GL_ARRAY_BUFFER, m_textureBuffer[0]);
- glEnableVertexAttribArray(positionHandle);
- glVertexAttribPointer(positionHandle, 2, GL_FLOAT, GL_FALSE, 0, 0);
-
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
@@ -819,7 +861,13 @@ void ShaderProgram::drawVideoLayerQuad(const TransformationMatrix& drawMatrix,
int textureId)
{
// switch to our custom yuv video rendering program
- glUseProgram(m_handleArray[Video].programHandle);
+ if (m_cachedProgramType != Video) {
+ glUseProgram(m_handleArray[Video].programHandle);
+ glVertexAttribPointer(m_handleArray[Video].positionHandle,
+ 2, GL_FLOAT, GL_FALSE, 0, 0);
+ m_cachedProgramType = Video;
+ }
+
// TODO: Merge drawVideoLayerQuad into drawQuad.
TransformationMatrix modifiedDrawMatrix;
modifiedDrawMatrix.scale3d(m_currentScale, m_currentScale, 1);
@@ -835,15 +883,8 @@ void ShaderProgram::drawVideoLayerQuad(const TransformationMatrix& drawMatrix,
projectionMatrix);
glUniformMatrix4fv(m_handleArray[Video].videoMtxHandle, 1, GL_FALSE,
textureMatrix);
- glActiveTexture(GL_TEXTURE0);
- glUniform1i(m_handleArray[Video].texSamplerHandle, 0);
glBindTexture(GL_TEXTURE_EXTERNAL_OES, textureId);
- GLint videoPosition = m_handleArray[Video].positionHandle;
- glBindBuffer(GL_ARRAY_BUFFER, m_textureBuffer[0]);
- glEnableVertexAttribArray(videoPosition);
- glVertexAttribPointer(videoPosition, 2, GL_FLOAT, GL_FALSE, 0, 0);
-
setBlendingState(false);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
diff --git a/Source/WebCore/platform/graphics/android/rendering/ShaderProgram.h b/Source/WebCore/platform/graphics/android/rendering/ShaderProgram.h
index 27eb737..9c5dc17 100644
--- a/Source/WebCore/platform/graphics/android/rendering/ShaderProgram.h
+++ b/Source/WebCore/platform/graphics/android/rendering/ShaderProgram.h
@@ -168,6 +168,7 @@ public:
private:
GLuint loadShader(GLenum shaderType, const char* pSource);
GLint createProgram(const char* vertexSource, const char* fragmentSource);
+ void initProgram(ShaderType type);
GLfloat* getTileProjectionMatrix(const DrawQuadData* data);
void setBlendingState(bool enableBlending);
void drawQuadInternal(ShaderType type, const GLfloat* matrix, int textureId,
@@ -231,6 +232,11 @@ private:
GLfloat m_tileProjMatrix[16];
Vector<ShaderResource> m_resources;
+
+ ShaderType m_cachedProgramType;
+ GLfloat m_cachedOpacity;
+ FloatRect m_cachedFillPortion;
+ Color m_cachedPureColor;
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/rendering/Surface.cpp b/Source/WebCore/platform/graphics/android/rendering/Surface.cpp
index 1898910..96a4a16 100644
--- a/Source/WebCore/platform/graphics/android/rendering/Surface.cpp
+++ b/Source/WebCore/platform/graphics/android/rendering/Surface.cpp
@@ -218,7 +218,7 @@ void Surface::prepareGL(bool layerTilesDisabled, bool updateWithBlit)
ALOGV("prepareGL on Surf %p with SurfBack %p, %d layers, first layer %s (%d) "
"prepareArea(%d, %d - %d x %d) fullArea(%d, %d - %d x %d)",
this, m_surfaceBacking, m_layers.size(),
- getFirstLayer()->subclassName().ascii().data(),
+ getFirstLayer()->subclassName(),
getFirstLayer()->uniqueId(),
prepareArea.x(), prepareArea.y(), prepareArea.width(), prepareArea.height(),
fullArea.x(), fullArea.y(), fullArea.width(), fullArea.height());
@@ -253,7 +253,7 @@ bool Surface::drawGL(bool layerTilesDisabled)
bool askRedraw = false;
if (m_surfaceBacking && !tilesDisabled) {
ALOGV("drawGL on Surf %p with SurfBack %p, first layer %s (%d)", this, m_surfaceBacking,
- getFirstLayer()->subclassName().ascii().data(), getFirstLayer()->uniqueId());
+ getFirstLayer()->subclassName(), getFirstLayer()->uniqueId());
bool force3dContentVisible = true;
IntRect drawArea = visibleContentArea(force3dContentVisible);
diff --git a/Source/WebCore/platform/graphics/android/rendering/SurfaceBacking.cpp b/Source/WebCore/platform/graphics/android/rendering/SurfaceBacking.cpp
index d7f6535..5b11df6 100644
--- a/Source/WebCore/platform/graphics/android/rendering/SurfaceBacking.cpp
+++ b/Source/WebCore/platform/graphics/android/rendering/SurfaceBacking.cpp
@@ -40,13 +40,15 @@
namespace WebCore {
SurfaceBacking::SurfaceBacking(bool isBaseSurface)
+ : m_frontTileGrid(new TileGrid(isBaseSurface))
+ , m_backTileGrid(new TileGrid(isBaseSurface))
+ , m_lowResTileGrid(new TileGrid(isBaseSurface))
+ , m_scale(-1)
+ , m_futureScale(-1)
+ , m_zooming(false)
+ , m_hasAllowedZoom(false)
+
{
- m_frontTileGrid = new TileGrid(isBaseSurface);
- m_backTileGrid = new TileGrid(isBaseSurface);
- m_lowResTileGrid = new TileGrid(isBaseSurface);
- m_scale = -1;
- m_futureScale = -1;
- m_zooming = false;
#ifdef DEBUG_COUNT
ClassTracker::instance()->increment("SurfaceBacking");
#endif
@@ -67,9 +69,16 @@ void SurfaceBacking::prepareGL(GLWebViewState* state, bool allowZoom,
TilePainter* painter, bool aggressiveRendering,
bool updateWithBlit)
{
+ // If the surface backing has ever zoomed beyond 1.0 scale, it's always
+ // allowed to (so repaints aren't necessary when allowZoom toggles). If not,
+ // and allowZoom is false, don't allow scale greater than 1.0
+ m_hasAllowedZoom |= allowZoom;
float scale = state->scale();
- if (scale > 1 && !allowZoom)
+ bool scaleOverridden = false;
+ if (scale > 1 && !m_hasAllowedZoom) {
scale = 1;
+ scaleOverridden = true;
+ }
if (m_scale == -1) {
m_scale = scale;
@@ -78,7 +87,10 @@ void SurfaceBacking::prepareGL(GLWebViewState* state, bool allowZoom,
if (m_futureScale != scale) {
m_futureScale = scale;
- m_zoomUpdateTime = WTF::currentTime() + SurfaceBacking::s_zoomUpdateDelay;
+ if (scaleOverridden)
+ m_zoomUpdateTime = 0; // start rendering immediately
+ else
+ m_zoomUpdateTime = WTF::currentTime() + SurfaceBacking::s_zoomUpdateDelay;
m_zooming = true;
// release back TileGrid's TileTextures, so they can be reused immediately
diff --git a/Source/WebCore/platform/graphics/android/rendering/SurfaceBacking.h b/Source/WebCore/platform/graphics/android/rendering/SurfaceBacking.h
index 5709f2a..80c6545 100644
--- a/Source/WebCore/platform/graphics/android/rendering/SurfaceBacking.h
+++ b/Source/WebCore/platform/graphics/android/rendering/SurfaceBacking.h
@@ -85,7 +85,7 @@ private:
void swapTileGrids();
// Delay before we schedule a new tile at the new scale factor
- static const double s_zoomUpdateDelay = 0.2; // 200 ms
+ static const double s_zoomUpdateDelay = 0.1; // 100 ms
TileGrid* m_frontTileGrid;
TileGrid* m_backTileGrid;
@@ -95,6 +95,7 @@ private:
float m_futureScale;
double m_zoomUpdateTime;
bool m_zooming;
+ bool m_hasAllowedZoom;
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/rendering/SurfaceCollection.cpp b/Source/WebCore/platform/graphics/android/rendering/SurfaceCollection.cpp
index 1c769bf..b675f7d 100644
--- a/Source/WebCore/platform/graphics/android/rendering/SurfaceCollection.cpp
+++ b/Source/WebCore/platform/graphics/android/rendering/SurfaceCollection.cpp
@@ -95,15 +95,6 @@ void SurfaceCollection::prepareGL(const SkRect& visibleContentRect, bool tryToFa
m_surfaces[i]->prepareGL(layerTilesDisabled, tryToFastBlit);
}
-static inline bool compareSurfaceZ(const Surface* a, const Surface* b)
-{
- const LayerAndroid* la = a->getFirstLayer();
- const LayerAndroid* lb = b->getFirstLayer();
-
- // swap drawing order if zValue suggests it AND the layers are in the same stacking context
- return (la->zValue() > lb->zValue()) && (la->getParent() == lb->getParent());
-}
-
bool SurfaceCollection::drawGL(const SkRect& visibleContentRect)
{
TRACE_METHOD();
@@ -111,21 +102,10 @@ bool SurfaceCollection::drawGL(const SkRect& visibleContentRect)
ClassTracker::instance()->show();
#endif
- bool needsRedraw = false;
updateLayerPositions(visibleContentRect);
bool layerTilesDisabled = m_compositedRoot->state()->isSingleSurfaceRenderingMode();
- // create a duplicate vector of surfaces, sorted by z value
- Vector <Surface*> surfaces;
- for (unsigned int i = 0; i < m_surfaces.size(); i++)
- surfaces.append(m_surfaces[i]);
- std::stable_sort(surfaces.begin()+1, surfaces.end(), compareSurfaceZ);
-
- // draw the sorted vector
- for (unsigned int i = 0; i < m_surfaces.size(); i++)
- needsRedraw |= surfaces[i]->drawGL(layerTilesDisabled);
-
- return needsRedraw;
+ return m_compositedRoot->drawTreeSurfacesGL();
}
Color SurfaceCollection::getBackgroundColor()
diff --git a/Source/WebCore/platform/graphics/android/rendering/SurfaceCollectionManager.cpp b/Source/WebCore/platform/graphics/android/rendering/SurfaceCollectionManager.cpp
index 174720f..9914176 100644
--- a/Source/WebCore/platform/graphics/android/rendering/SurfaceCollectionManager.cpp
+++ b/Source/WebCore/platform/graphics/android/rendering/SurfaceCollectionManager.cpp
@@ -38,6 +38,10 @@ namespace WebCore {
using namespace android::uirenderer;
+// Tag used to display current number of SurfaceCollections.
+// Note: this will only work if one webview is actively drawing at a time.
+static const char* COLLECTION_COUNT_TAG = "CollectionCount";
+
SurfaceCollectionManager::SurfaceCollectionManager()
: m_drawingCollection(0)
, m_paintingCollection(0)
@@ -87,6 +91,12 @@ void SurfaceCollectionManager::swap()
m_paintingCollection = m_queuedCollection;
m_queuedCollection = 0;
+ if (ATRACE_ENABLED()) {
+ ATRACE_INT(COLLECTION_COUNT_TAG,
+ (m_drawingCollection ? 1 : 0)
+ + (m_paintingCollection ? 1 : 0));
+ }
+
ALOGV("SWAPPING COMPLETE, D %p, P %p, Q %p",
m_drawingCollection, m_paintingCollection, m_queuedCollection);
}
@@ -106,6 +116,8 @@ void SurfaceCollectionManager::clearCollections()
m_paintingCollection = 0;
SkSafeUnref(m_queuedCollection);
m_queuedCollection = 0;
+
+ ATRACE_INT(COLLECTION_COUNT_TAG, 0);
}
void SurfaceCollectionManager::updatePaintingCollection(SurfaceCollection* newCollection)
@@ -126,8 +138,10 @@ bool SurfaceCollectionManager::updateWithSurfaceCollection(SurfaceCollection* ne
if (!newCollection || brandNew) {
clearCollections();
- if (brandNew)
+ if (brandNew) {
updatePaintingCollection(newCollection);
+ ATRACE_INT(COLLECTION_COUNT_TAG, 1);
+ }
return false;
}
@@ -157,6 +171,13 @@ bool SurfaceCollectionManager::updateWithSurfaceCollection(SurfaceCollection* ne
// don't have painting collection, paint this one!
updatePaintingCollection(newCollection);
}
+
+ if (ATRACE_ENABLED()) {
+ ATRACE_INT(COLLECTION_COUNT_TAG,
+ (m_drawingCollection ? 1 : 0)
+ + (m_paintingCollection ? 1 : 0)
+ + (m_queuedCollection ? 1 : 0));
+ }
return m_drawingCollection && TilesManager::instance()->useDoubleBuffering();
}
@@ -225,18 +246,19 @@ int SurfaceCollectionManager::drawGL(double currentTime, IntRect& viewRect,
int returnFlags = 0;
bool didCollectionSwap = false;
+ bool tryFastBlit = !m_fastSwapMode;
if (m_paintingCollection) {
ALOGV("preparing painting collection %p", m_paintingCollection);
m_paintingCollection->evaluateAnimations(currentTime);
- bool tryFastBlit = !m_fastSwapMode;
m_paintingCollection->prepareGL(visibleContentRect, tryFastBlit);
m_paintingCollection->computeTexturesAmount(texturesResultPtr);
if (!TilesManager::instance()->useDoubleBuffering() || m_paintingCollection->isReady()) {
ALOGV("have painting collection %p ready, swapping!", m_paintingCollection);
didCollectionSwap = true;
+ m_fastSwapMode = false;
TilesManager::instance()->incContentUpdates();
if (collectionsSwappedPtr)
*collectionsSwappedPtr = true;
@@ -261,6 +283,9 @@ int SurfaceCollectionManager::drawGL(double currentTime, IntRect& viewRect,
&& m_drawingCollection->isReady())) {
// either a swap just occurred, or there is no more work to be done: do a full draw
m_drawingCollection->swapTiles();
+
+ if (didCollectionSwap && m_paintingCollection)
+ m_paintingCollection->prepareGL(visibleContentRect, tryFastBlit);
returnFlags |= DrawGlInfo::kStatusDraw;
} else {
// current collection not ready - invoke functor in process mode
@@ -286,6 +311,9 @@ int SurfaceCollectionManager::drawGL(double currentTime, IntRect& viewRect,
if (didCollectionSwap || m_fastSwapMode || (drawingReady && !m_paintingCollection))
m_drawingCollection->swapTiles();
+ if (didCollectionSwap && m_paintingCollection)
+ m_paintingCollection->prepareGL(visibleContentRect, tryFastBlit);
+
if (drawingReady) {
// exit fast swap mode, as content is up to date
m_fastSwapMode = false;
diff --git a/Source/WebCore/platform/graphics/android/rendering/TexturesGenerator.cpp b/Source/WebCore/platform/graphics/android/rendering/TexturesGenerator.cpp
index cc94c9c..74e663a 100644
--- a/Source/WebCore/platform/graphics/android/rendering/TexturesGenerator.cpp
+++ b/Source/WebCore/platform/graphics/android/rendering/TexturesGenerator.cpp
@@ -32,6 +32,7 @@
#if USE(ACCELERATED_COMPOSITING)
#include "AndroidLog.h"
+#include "BaseRenderer.h"
#include "GLUtils.h"
#include "PaintTileOperation.h"
#include "TilesManager.h"
@@ -39,6 +40,19 @@
namespace WebCore {
+TexturesGenerator::TexturesGenerator(TilesManager* instance)
+ : Thread(false)
+ , m_tilesManager(instance)
+ , m_deferredMode(false)
+ , m_renderer(0)
+{
+}
+
+TexturesGenerator::~TexturesGenerator()
+{
+ delete m_renderer;
+}
+
bool TexturesGenerator::tryUpdateOperationWithPainter(Tile* tile, TilePainter* painter)
{
android::Mutex::Autolock lock(mRequestedOperationsLock);
@@ -83,12 +97,11 @@ void TexturesGenerator::removeOperationsForFilter(OperationFilter* filter)
i++;
}
}
- delete filter;
}
status_t TexturesGenerator::readyToRun()
{
- ALOGV("Thread ready to run");
+ m_renderer = BaseRenderer::createRenderer();
return NO_ERROR;
}
@@ -165,7 +178,9 @@ bool TexturesGenerator::threadLoop()
if (currentOperation) {
ALOGV("threadLoop, painting the request with priority %d",
currentOperation->priority());
- currentOperation->run();
+ // swap out the renderer if necessary
+ BaseRenderer::swapRendererIfNeeded(m_renderer);
+ currentOperation->run(m_renderer);
}
mRequestedOperationsLock.lock();
diff --git a/Source/WebCore/platform/graphics/android/rendering/TexturesGenerator.h b/Source/WebCore/platform/graphics/android/rendering/TexturesGenerator.h
index 290ad08..e487edb 100644
--- a/Source/WebCore/platform/graphics/android/rendering/TexturesGenerator.h
+++ b/Source/WebCore/platform/graphics/android/rendering/TexturesGenerator.h
@@ -29,7 +29,7 @@
#if USE(ACCELERATED_COMPOSITING)
#include "QueuedOperation.h"
-#include "TilePainter.h"
+#include "TransferQueue.h"
#include <wtf/HashMap.h>
#include <wtf/Vector.h>
@@ -43,10 +43,9 @@ class TilesManager;
class TexturesGenerator : public Thread {
public:
- TexturesGenerator(TilesManager* instance) : Thread(false)
- , m_tilesManager(instance)
- , m_deferredMode(false) { }
- virtual ~TexturesGenerator() { }
+ TexturesGenerator(TilesManager* instance);
+ virtual ~TexturesGenerator();
+
virtual status_t readyToRun();
bool tryUpdateOperationWithPainter(Tile* tile, TilePainter* painter);
@@ -69,6 +68,7 @@ private:
TilesManager* m_tilesManager;
bool m_deferredMode;
+ BaseRenderer* m_renderer;
// defer painting for one second if best in queue has priority
// QueuedOperation::gDeferPriorityCutoff or higher
diff --git a/Source/WebCore/platform/graphics/android/rendering/Tile.cpp b/Source/WebCore/platform/graphics/android/rendering/Tile.cpp
index 96b189a..76be981 100644
--- a/Source/WebCore/platform/graphics/android/rendering/Tile.cpp
+++ b/Source/WebCore/platform/graphics/android/rendering/Tile.cpp
@@ -33,7 +33,7 @@
#include "AndroidLog.h"
#include "GLUtils.h"
-#include "RasterRenderer.h"
+#include "BaseRenderer.h"
#include "TextureInfo.h"
#include "TileTexture.h"
#include "TilesManager.h"
@@ -64,7 +64,6 @@ Tile::Tile(bool isLayerTile)
#ifdef DEBUG_COUNT
ClassTracker::instance()->increment("Tile");
#endif
- m_renderer = BaseRenderer::createRenderer();
}
Tile::~Tile()
@@ -74,8 +73,6 @@ Tile::~Tile()
if (m_frontTexture)
m_frontTexture->release(this);
- delete m_renderer;
-
#ifdef DEBUG_COUNT
ClassTracker::instance()->decrement("Tile");
#endif
@@ -297,7 +294,7 @@ bool Tile::isTileVisible(const IntRect& viewTileBounds)
}
// This is called from the texture generation thread
-void Tile::paintBitmap(TilePainter* painter)
+void Tile::paintBitmap(TilePainter* painter, BaseRenderer* renderer)
{
// We acquire the values below atomically. This ensures that we are reading
// values correctly across cores. Further, once we have these values they
@@ -328,8 +325,6 @@ void Tile::paintBitmap(TilePainter* painter)
return;
}
- // swap out the renderer if necessary
- BaseRenderer::swapRendererIfNeeded(m_renderer);
// setup the common renderInfo fields;
TileRenderInfo renderInfo;
renderInfo.x = x;
@@ -343,7 +338,7 @@ void Tile::paintBitmap(TilePainter* painter)
const float tileWidth = renderInfo.tileSize.width();
const float tileHeight = renderInfo.tileSize.height();
- m_renderer->renderTiledContent(renderInfo);
+ renderer->renderTiledContent(renderInfo);
m_atomicSync.lock();
diff --git a/Source/WebCore/platform/graphics/android/rendering/Tile.h b/Source/WebCore/platform/graphics/android/rendering/Tile.h
index b045f1f..f467bb0 100644
--- a/Source/WebCore/platform/graphics/android/rendering/Tile.h
+++ b/Source/WebCore/platform/graphics/android/rendering/Tile.h
@@ -28,7 +28,6 @@
#if USE(ACCELERATED_COMPOSITING)
-#include "BaseRenderer.h"
#include "FloatPoint.h"
#include "SkRect.h"
#include "SkRegion.h"
@@ -39,9 +38,10 @@
namespace WebCore {
+class BaseRenderer;
+class GLWebViewState;
class TextureInfo;
class TileTexture;
-class GLWebViewState;
/**
* An individual tile that is used to construct part of a webpage's BaseLayer of
@@ -107,7 +107,7 @@ public:
const FloatRect& fillPortion);
// the only thread-safe function called by the background thread
- void paintBitmap(TilePainter* painter);
+ void paintBitmap(TilePainter* painter, BaseRenderer* renderer);
bool intersectWithRect(int x, int y, int tileWidth, int tileHeight,
float scale, const SkRect& dirtyRect,
@@ -171,8 +171,6 @@ private:
// across all threads and cores.
android::Mutex m_atomicSync;
- BaseRenderer* m_renderer;
-
bool m_isLayerTile;
// the most recent GL draw before this tile was prepared. used for
diff --git a/Source/WebCore/platform/graphics/android/rendering/TilesManager.cpp b/Source/WebCore/platform/graphics/android/rendering/TilesManager.cpp
index 0b4ba7b..aa18898 100644
--- a/Source/WebCore/platform/graphics/android/rendering/TilesManager.cpp
+++ b/Source/WebCore/platform/graphics/android/rendering/TilesManager.cpp
@@ -57,7 +57,7 @@
// number to cap the layer tile texturs, it worked on both phones and tablets.
// TODO: after merge the pool of base tiles and layer tiles, we should revisit
// the logic of allocation management.
-#define MAX_TEXTURE_ALLOCATION ((6+TILE_PREFETCH_DISTANCE*2)*(5+TILE_PREFETCH_DISTANCE*2)*4)
+#define MAX_TEXTURE_ALLOCATION ((10+TILE_PREFETCH_DISTANCE*2)*(7+TILE_PREFETCH_DISTANCE*2)*4)
#define TILE_WIDTH 256
#define TILE_HEIGHT 256
@@ -65,6 +65,10 @@
#define LAYER_TEXTURES_DESTROY_TIMEOUT 60 // If we do not need layers for 60 seconds, free the textures
+// Eventually this should be dynamically be determined, and smart scheduling
+// between the generators should be implemented
+#define NUM_TEXTURES_GENERATORS 1
+
namespace WebCore {
int TilesManager::getMaxTextureAllocation()
@@ -101,14 +105,25 @@ TilesManager::TilesManager()
, m_eglContext(EGL_NO_CONTEXT)
{
ALOGV("TilesManager ctor");
- m_textures.reserveCapacity(MAX_TEXTURE_ALLOCATION);
- m_availableTextures.reserveCapacity(MAX_TEXTURE_ALLOCATION);
- m_tilesTextures.reserveCapacity(MAX_TEXTURE_ALLOCATION);
- m_availableTilesTextures.reserveCapacity(MAX_TEXTURE_ALLOCATION);
- m_pixmapsGenerationThread = new TexturesGenerator(this);
- m_pixmapsGenerationThread->run("TexturesGenerator");
+ m_textures.reserveCapacity(MAX_TEXTURE_ALLOCATION / 2);
+ m_availableTextures.reserveCapacity(MAX_TEXTURE_ALLOCATION / 2);
+ m_tilesTextures.reserveCapacity(MAX_TEXTURE_ALLOCATION / 2);
+ m_availableTilesTextures.reserveCapacity(MAX_TEXTURE_ALLOCATION / 2);
+
+ m_textureGenerators = new sp<TexturesGenerator>[NUM_TEXTURES_GENERATORS];
+ for (int i = 0; i < NUM_TEXTURES_GENERATORS; i++) {
+ m_textureGenerators[i] = new TexturesGenerator(this);
+ ALOGD("Starting TG #%d, %p", i, m_textureGenerators[i].get());
+ m_textureGenerators[i]->run("TexturesGenerator");
+ }
+}
+
+TilesManager::~TilesManager()
+{
+ delete[] m_textureGenerators;
}
+
void TilesManager::allocateTextures()
{
int nbTexturesToAllocate = m_currentTextureCount - m_textures.size();
@@ -488,6 +503,29 @@ void TilesManager::updateTilesIfContextVerified()
return;
}
+void TilesManager::removeOperationsForFilter(OperationFilter* filter)
+{
+ for (int i = 0; i < NUM_TEXTURES_GENERATORS; i++)
+ m_textureGenerators[i]->removeOperationsForFilter(filter);
+ delete filter;
+}
+
+bool TilesManager::tryUpdateOperationWithPainter(Tile* tile, TilePainter* painter)
+{
+ for (int i = 0; i < NUM_TEXTURES_GENERATORS; i++) {
+ if (m_textureGenerators[i]->tryUpdateOperationWithPainter(tile, painter))
+ return true;
+ }
+ return false;
+}
+
+void TilesManager::scheduleOperation(QueuedOperation* operation)
+{
+ // TODO: painter awareness, store prefer awareness, store preferred thread into painter
+ m_scheduleThread = (m_scheduleThread + 1) % NUM_TEXTURES_GENERATORS;
+ m_textureGenerators[m_scheduleThread]->scheduleOperation(operation);
+}
+
int TilesManager::tileWidth()
{
return TILE_WIDTH;
diff --git a/Source/WebCore/platform/graphics/android/rendering/TilesManager.h b/Source/WebCore/platform/graphics/android/rendering/TilesManager.h
index f0d2eac..0781ef6 100644
--- a/Source/WebCore/platform/graphics/android/rendering/TilesManager.h
+++ b/Source/WebCore/platform/graphics/android/rendering/TilesManager.h
@@ -53,23 +53,9 @@ public:
return gInstance != 0;
}
- void removeOperationsForFilter(OperationFilter* filter)
- {
- m_pixmapsGenerationThread->removeOperationsForFilter(filter);
- }
-
- bool tryUpdateOperationWithPainter(Tile* tile, TilePainter* painter)
- {
- return m_pixmapsGenerationThread->tryUpdateOperationWithPainter(tile, painter);
- }
-
- void scheduleOperation(QueuedOperation* operation)
- {
- m_pixmapsGenerationThread->scheduleOperation(operation);
- }
-
ShaderProgram* shader() { return &m_shader; }
TransferQueue* transferQueue();
+
VideoLayerManager* videoLayerManager() { return &m_videoLayerManager; }
void updateTilesIfContextVerified();
@@ -165,8 +151,15 @@ public:
return m_drawGLCount;
}
+ // operations on/for texture generator threads
+ void removeOperationsForFilter(OperationFilter* filter);
+ bool tryUpdateOperationWithPainter(Tile* tile, TilePainter* painter);
+ void scheduleOperation(QueuedOperation* operation);
+
private:
TilesManager();
+ ~TilesManager();
+ int m_scheduleThread;
void discardTexturesVector(unsigned long long sparedDrawCount,
WTF::Vector<TileTexture*>& textures,
@@ -198,7 +191,7 @@ private:
unsigned int m_contentUpdates; // nr of successful tiled paints
unsigned int m_webkitContentUpdates; // nr of paints from webkit
- sp<TexturesGenerator> m_pixmapsGenerationThread;
+ sp<TexturesGenerator>* m_textureGenerators;
android::Mutex m_texturesLock;
diff --git a/Source/WebCore/platform/graphics/android/rendering/TransferQueue.cpp b/Source/WebCore/platform/graphics/android/rendering/TransferQueue.cpp
index f37afa4..b15fa6d 100644
--- a/Source/WebCore/platform/graphics/android/rendering/TransferQueue.cpp
+++ b/Source/WebCore/platform/graphics/android/rendering/TransferQueue.cpp
@@ -32,6 +32,7 @@
#if USE(ACCELERATED_COMPOSITING)
#include "AndroidLog.h"
+#include "BaseRenderer.h"
#include "DrawQuadData.h"
#include "GLUtils.h"
#include "Tile.h"
@@ -389,8 +390,9 @@ void TransferQueue::updateDirtyTiles()
}
void TransferQueue::updateQueueWithBitmap(const TileRenderInfo* renderInfo,
- const SkBitmap& bitmap)
+ SkBitmap& bitmap)
{
+ TRACE_METHOD();
if (!tryUpdateQueueWithBitmap(renderInfo, bitmap)) {
// failed placing bitmap in queue, discard tile's texture so it will be
// re-enqueued (and repainted)
@@ -401,7 +403,7 @@ void TransferQueue::updateQueueWithBitmap(const TileRenderInfo* renderInfo,
}
bool TransferQueue::tryUpdateQueueWithBitmap(const TileRenderInfo* renderInfo,
- const SkBitmap& bitmap)
+ SkBitmap& bitmap)
{
// This lock need to cover the full update since it is possible that queue
// will be cleaned up in the middle of this update without the lock.
@@ -427,7 +429,7 @@ bool TransferQueue::tryUpdateQueueWithBitmap(const TileRenderInfo* renderInfo,
}
// b) After update the Surface Texture, now udpate the transfer queue info.
- addItemInTransferQueue(renderInfo, currentUploadType, &bitmap);
+ addItemInTransferQueue(renderInfo, currentUploadType, bitmap);
ALOGV("Bitmap updated x, y %d %d, baseTile %p",
renderInfo->x, renderInfo->y, renderInfo->baseTile);
@@ -473,7 +475,7 @@ void TransferQueue::addItemCommon(const TileRenderInfo* renderInfo,
// Currently only called by GLUtils::updateSharedSurfaceTextureWithBitmap.
void TransferQueue::addItemInTransferQueue(const TileRenderInfo* renderInfo,
TextureUploadType type,
- const SkBitmap* bitmap)
+ SkBitmap& bitmap)
{
m_transferQueueIndex = (m_transferQueueIndex + 1) % m_transferQueueSize;
@@ -485,15 +487,18 @@ void TransferQueue::addItemInTransferQueue(const TileRenderInfo* renderInfo,
TileTransferData* data = &m_transferQueue[index];
addItemCommon(renderInfo, type, data);
- if (type == CpuUpload && bitmap) {
+ if (type == CpuUpload) {
// Lazily create the bitmap
if (!m_transferQueue[index].bitmap) {
m_transferQueue[index].bitmap = new SkBitmap();
- int w = bitmap->width();
- int h = bitmap->height();
- m_transferQueue[index].bitmap->setConfig(bitmap->config(), w, h);
+ int w = bitmap.width();
+ int h = bitmap.height();
+ m_transferQueue[index].bitmap->setConfig(bitmap.config(), w, h);
+ m_transferQueue[index].bitmap->allocPixels();
}
- bitmap->copyTo(m_transferQueue[index].bitmap, bitmap->config());
+ SkBitmap temp = (*m_transferQueue[index].bitmap);
+ (*m_transferQueue[index].bitmap) = bitmap;
+ bitmap = temp;
}
m_emptyItemCount--;
diff --git a/Source/WebCore/platform/graphics/android/rendering/TransferQueue.h b/Source/WebCore/platform/graphics/android/rendering/TransferQueue.h
index c0835d7..55011b0 100644
--- a/Source/WebCore/platform/graphics/android/rendering/TransferQueue.h
+++ b/Source/WebCore/platform/graphics/android/rendering/TransferQueue.h
@@ -115,11 +115,11 @@ public:
// insert the bitmap into the queue, mark the tile dirty if failing
void updateQueueWithBitmap(const TileRenderInfo* renderInfo,
- const SkBitmap& bitmap);
+ SkBitmap& bitmap);
void addItemInTransferQueue(const TileRenderInfo* info,
TextureUploadType type,
- const SkBitmap* bitmap);
+ SkBitmap& bitmap);
// Check if the item @ index is ready for update.
// The lock will be done when returning true.
bool readyForUpdate();
@@ -145,7 +145,7 @@ public:
private:
// return true if successfully inserted into queue
bool tryUpdateQueueWithBitmap(const TileRenderInfo* renderInfo,
- const SkBitmap& bitmap);
+ SkBitmap& bitmap);
bool getHasGLContext();
void setHasGLContext(bool hasContext);
void emptyAndAbandonQueue();
diff --git a/Source/WebCore/platform/graphics/android/utils/LinearAllocator.cpp b/Source/WebCore/platform/graphics/android/utils/LinearAllocator.cpp
new file mode 100644
index 0000000..b945944
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/utils/LinearAllocator.cpp
@@ -0,0 +1,225 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define LOG_TAG "LinearAllocator"
+#define LOG_NDEBUG 1
+
+#include "config.h"
+#include "LinearAllocator.h"
+
+#include "AndroidLog.h"
+
+namespace WebCore {
+
+// The ideal size of a page allocation (these need to be multiples of 4)
+#define INITIAL_PAGE_SIZE ((size_t)4096) // 4kb
+#define MAX_PAGE_SIZE ((size_t)131072) // 128kb
+
+// The maximum amount of wasted space we can have per page
+// Allocations exceeding this will have their own dedicated page
+// If this is too low, we will malloc too much
+// Too high, and we may waste too much space
+// Must be smaller than INITIAL_PAGE_SIZE
+#define MAX_WASTE_SIZE ((size_t)1024)
+
+#define ALIGN(x) (x + (x % sizeof(int)))
+
+#if LOG_NDEBUG
+#define ADD_ALLOCATION(size)
+#define RM_ALLOCATION(size)
+#else
+#include <utils/Thread.h>
+static size_t s_totalAllocations = 0;
+static double s_lastLogged = 0;
+static android::Mutex s_mutex;
+
+static void _logUsageLocked() {
+ double now = currentTimeMS();
+ if (now - s_lastLogged > 5) {
+ s_lastLogged = now;
+ ALOGV("Total memory usage: %d kb", s_totalAllocations / 1024);
+ }
+}
+
+static void _addAllocation(size_t size) {
+ android::AutoMutex lock(s_mutex);
+ s_totalAllocations += size;
+ _logUsageLocked();
+}
+
+#define ADD_ALLOCATION(size) _addAllocation(size);
+#define RM_ALLOCATION(size) _addAllocation(-size);
+#endif
+
+class LinearAllocator::Page {
+public:
+ Page* next() { return m_nextPage; }
+ void setNext(Page* next) { m_nextPage = next; }
+
+ Page()
+ : m_nextPage(0)
+ {}
+
+ void* start()
+ {
+ return (void*) (((unsigned)this) + sizeof(LinearAllocator::Page));
+ }
+
+ void* end(int pageSize)
+ {
+ return (void*) (((unsigned)start()) + pageSize);
+ }
+
+private:
+ Page(const Page& other) {}
+ Page* m_nextPage;
+};
+
+LinearAllocator::LinearAllocator()
+ : m_pageSize(INITIAL_PAGE_SIZE)
+ , m_maxAllocSize(MAX_WASTE_SIZE)
+ , m_next(0)
+ , m_currentPage(0)
+ , m_pages(0)
+ , m_totalAllocated(0)
+ , m_wastedSpace(0)
+ , m_pageCount(0)
+ , m_dedicatedPageCount(0)
+{
+}
+
+LinearAllocator::~LinearAllocator(void)
+{
+ Page* p = m_pages;
+ while (p) {
+ Page* next = p->next();
+ delete p;
+ RM_ALLOCATION(m_pageSize);
+ p = next;
+ }
+}
+
+void* LinearAllocator::start(Page* p)
+{
+ return ((char*)p) + sizeof(Page);
+}
+
+void* LinearAllocator::end(Page* p)
+{
+ return ((char*)p) + m_pageSize;
+}
+
+bool LinearAllocator::fitsInCurrentPage(size_t size)
+{
+ return m_next && ((char*)m_next + size) <= end(m_currentPage);
+}
+
+void LinearAllocator::ensureNext(size_t size)
+{
+ if (fitsInCurrentPage(size))
+ return;
+ if (m_currentPage && m_pageSize < MAX_PAGE_SIZE) {
+ m_pageSize = std::min(MAX_PAGE_SIZE, m_pageSize * 2);
+ m_pageSize = ALIGN(m_pageSize);
+ }
+ m_wastedSpace += m_pageSize;
+ Page* p = newPage(m_pageSize);
+ if (m_currentPage)
+ m_currentPage->setNext(p);
+ m_currentPage = p;
+ if (!m_pages)
+ m_pages = m_currentPage;
+ m_next = start(m_currentPage);
+}
+
+void* LinearAllocator::alloc(size_t size)
+{
+ size = ALIGN(size);
+ if (size > m_maxAllocSize && !fitsInCurrentPage(size)) {
+ ALOGV("Exceeded max size %d > %d", size, m_maxAllocSize);
+ // Allocation is too large, create a dedicated page for the allocation
+ Page* page = newPage(size);
+ m_dedicatedPageCount++;
+ page->setNext(m_pages);
+ m_pages = page;
+ if (!m_currentPage)
+ m_currentPage = m_pages;
+ return start(page);
+ }
+ ensureNext(size);
+ void* ptr = m_next;
+ m_next = ((char*)m_next) + size;
+ m_wastedSpace -= size;
+ return ptr;
+}
+
+void LinearAllocator::rewindIfLastAlloc(void* ptr, size_t allocSize)
+{
+ // Don't bother rewinding across pages
+ if (ptr >= start(m_currentPage) && ptr < end(m_currentPage)
+ && ptr == ((char*)m_next - allocSize)) {
+ m_totalAllocated -= allocSize;
+ m_wastedSpace += allocSize;
+ m_next = ptr;
+ }
+}
+
+LinearAllocator::Page* LinearAllocator::newPage(size_t pageSize)
+{
+ pageSize += sizeof(LinearAllocator::Page);
+ ADD_ALLOCATION(pageSize);
+ m_totalAllocated += pageSize;
+ m_pageCount++;
+ void* buf = malloc(pageSize);
+ return new (buf) Page();
+}
+
+static const char* toSize(size_t value, float& result)
+{
+ if (value < 2000) {
+ result = value;
+ return "B";
+ }
+ if (value < 2000000) {
+ result = value / 1024.0f;
+ return "KB";
+ }
+ result = value / 1048576.0f;
+ return "MB";
+}
+
+void LinearAllocator::dumpMemoryStats(const char* prefix)
+{
+ float prettySize;
+ const char* prettySuffix;
+ prettySuffix = toSize(m_totalAllocated, prettySize);
+ ALOGD("%sTotal allocated: %.2f%s", prefix, prettySize, prettySuffix);
+ prettySuffix = toSize(m_wastedSpace, prettySize);
+ ALOGD("%sWasted space: %.2f%s (%.1f%%)", prefix, prettySize, prettySuffix,
+ (float) m_wastedSpace / (float) m_totalAllocated * 100.0f);
+ ALOGD("%sPages %d (dedicated %d)", prefix, m_pageCount, m_dedicatedPageCount);
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/context/GraphicsOperationCollection.h b/Source/WebCore/platform/graphics/android/utils/LinearAllocator.h
index 9d7b530..8cabf7c 100644
--- a/Source/WebCore/platform/graphics/android/context/GraphicsOperationCollection.h
+++ b/Source/WebCore/platform/graphics/android/utils/LinearAllocator.h
@@ -23,50 +23,46 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef GraphicsOperationCollection_h
-#define GraphicsOperationCollection_h
-
-#if USE(ACCELERATED_COMPOSITING)
-
-#include "Color.h"
-#include "GraphicsOperation.h"
-#include "IntRect.h"
-#include "SkRefCnt.h"
+#ifndef LinearAllocator_h
+#define LinearAllocator_h
namespace WebCore {
-class PlatformGraphicsContext;
-
-class GraphicsOperationCollection : public SkRefCnt {
+class LinearAllocator
+{
public:
- GraphicsOperationCollection(const IntRect& drawArea);
- ~GraphicsOperationCollection();
+ LinearAllocator();
+ ~LinearAllocator();
- void apply(PlatformGraphicsContext* context);
- void append(GraphicsOperation::Operation* operation);
+ void* alloc(size_t size);
+ void rewindIfLastAlloc(void* ptr, size_t allocSize);
- bool isEmpty();
+ void dumpMemoryStats(const char* prefix = "");
private:
- IntRect m_drawArea;
- Vector<GraphicsOperation::Operation*> m_operations;
-};
+ LinearAllocator(const LinearAllocator& other);
-class AutoGraphicsOperationCollection {
-public:
- AutoGraphicsOperationCollection(const IntRect& area);
- ~AutoGraphicsOperationCollection();
- GraphicsContext* context() { return m_graphicsContext; }
- GraphicsOperationCollection* picture() { return m_graphicsOperationCollection; }
+ class Page;
-private:
- GraphicsOperationCollection* m_graphicsOperationCollection;
- PlatformGraphicsContext* m_platformGraphicsContext;
- GraphicsContext* m_graphicsContext;
-};
+ Page* newPage(size_t pageSize);
+ bool fitsInCurrentPage(size_t size);
+ void ensureNext(size_t size);
+ void* start(Page *p);
+ void* end(Page* p);
-}
+ size_t m_pageSize;
+ size_t m_maxAllocSize;
+ void* m_next;
+ Page* m_currentPage;
+ Page* m_pages;
+
+ // Memory usage tracking
+ size_t m_totalAllocated;
+ size_t m_wastedSpace;
+ size_t m_pageCount;
+ size_t m_dedicatedPageCount;
+};
-#endif // USE(ACCELERATED_COMPOSITING)
+} // namespace WebCore
-#endif // GraphicsOperationCollection_h
+#endif // LinearAllocator_h
diff --git a/Source/WebCore/platform/mock/GeolocationServiceMock.cpp b/Source/WebCore/platform/mock/GeolocationServiceMock.cpp
index c3ba7b4..b254cb8 100644
--- a/Source/WebCore/platform/mock/GeolocationServiceMock.cpp
+++ b/Source/WebCore/platform/mock/GeolocationServiceMock.cpp
@@ -80,12 +80,7 @@ void GeolocationServiceMock::setError(PassRefPtr<PositionError> error)
makeGeolocationCallbackFromAllInstances();
}
-#if PLATFORM(ANDROID)
-// TODO: Upstream to webkit.org. See https://bugs.webkit.org/show_bug.cgi?id=34082
-bool GeolocationServiceMock::startUpdating(PositionOptions*, bool /* suspend */)
-#else
bool GeolocationServiceMock::startUpdating(PositionOptions*)
-#endif
{
m_isActive = true;
m_timer.startOneShot(0);
diff --git a/Source/WebCore/platform/mock/GeolocationServiceMock.h b/Source/WebCore/platform/mock/GeolocationServiceMock.h
index 1b4db93..7d02797 100755
--- a/Source/WebCore/platform/mock/GeolocationServiceMock.h
+++ b/Source/WebCore/platform/mock/GeolocationServiceMock.h
@@ -46,12 +46,7 @@ class GeolocationServiceMock : public GeolocationService {
GeolocationServiceMock(GeolocationServiceClient*);
virtual ~GeolocationServiceMock();
-#if PLATFORM(ANDROID)
- // TODO: Upstream to webkit.org. See https://bugs.webkit.org/show_bug.cgi?id=34082
- virtual bool startUpdating(PositionOptions*, bool suspend);
-#else
virtual bool startUpdating(PositionOptions*);
-#endif
virtual void stopUpdating();
static void setPosition(PassRefPtr<Geoposition> position);
diff --git a/Source/WebCore/plugins/android/PluginViewAndroid.cpp b/Source/WebCore/plugins/android/PluginViewAndroid.cpp
index fdf6e03..24a14aa 100644
--- a/Source/WebCore/plugins/android/PluginViewAndroid.cpp
+++ b/Source/WebCore/plugins/android/PluginViewAndroid.cpp
@@ -55,7 +55,6 @@
#include "Touch.h"
#include "TouchEvent.h"
#include "TouchList.h"
-#include "android_graphics.h"
#include "SkCanvas.h"
#include "npruntime_impl.h"
// #include "runtime_root.h"
@@ -405,7 +404,7 @@ bool PluginView::platformGetValueStatic(NPNVariable variable, void* value, NPErr
// our interface query is valid with no NPP instance
*result = NPERR_GENERIC_ERROR;
- switch (variable) {
+ switch ((int)variable) {
case NPNVisOfflineBool: {
if (value != NULL) {
bool* retValue = static_cast<bool*>(value);
@@ -422,7 +421,7 @@ bool PluginView::platformGetValueStatic(NPNVariable variable, void* value, NPErr
return true;
}
default:
- ; // do nothing
+ break; // do nothing
}
(void)anp_getInterface(variable, value, result);
@@ -490,7 +489,7 @@ void PluginView::setNPWindowIfNeeded()
bool PluginView::platformGetValue(NPNVariable variable, void* value, NPError* result)
{
- switch (variable) {
+ switch ((int)variable) {
case NPNVWindowNPObject: {
NPObject* windowScriptObject =
m_parentFrame->script()->windowScriptNPObject();
@@ -581,7 +580,7 @@ NPError PluginView::platformSetValue(NPPVariable variable, void* value)
{
NPError error = NPERR_GENERIC_ERROR;
- switch (variable) {
+ switch ((int)variable) {
case kRequestDrawingModel_ANPSetValue: {
ANPDrawingModel model = reinterpret_cast<ANPDrawingModel>(value);
if (m_window->setDrawingModel(model))
@@ -690,15 +689,12 @@ void PluginView::paint(GraphicsContext* context, const IntRect& rect)
notification of its global position change.
*/
updatePluginWidget();
- SkCanvas* canvas = context->platformContext()->getCanvas();
- if (!canvas)
- return;
- m_window->setSurfaceClip(canvas->getTotalClip().getBounds());
+ m_window->setSurfaceClip(context->platformContext()->getTotalClipBounds());
} else {
m_window->inval(rect, false);
context->save();
context->translate(frame.x(), frame.y());
- m_window->draw(android_gc2canvas(context));
+ m_window->draw(context->platformContext());
context->restore();
}
diff --git a/Source/WebKit/Android.mk b/Source/WebKit/Android.mk
index c3e9798..07634b6 100644
--- a/Source/WebKit/Android.mk
+++ b/Source/WebKit/Android.mk
@@ -27,6 +27,9 @@ LOCAL_SRC_FILES := \
android/WebCoreSupport/EditorClientAndroid.cpp \
android/WebCoreSupport/FrameLoaderClientAndroid.cpp \
android/WebCoreSupport/FrameNetworkingContextAndroid.cpp \
+ android/WebCoreSupport/GeolocationClientAndroid.cpp \
+ android/WebCoreSupport/GeolocationClientImpl.cpp \
+ android/WebCoreSupport/GeolocationManager.cpp \
android/WebCoreSupport/GeolocationPermissions.cpp \
android/WebCoreSupport/MediaPlayerPrivateAndroid.cpp \
android/WebCoreSupport/MemoryUsage.cpp \
@@ -61,6 +64,7 @@ LOCAL_SRC_FILES += \
android/jni/DeviceMotionClientImpl.cpp \
android/jni/DeviceOrientationClientImpl.cpp \
android/jni/GeolocationPermissionsBridge.cpp \
+ android/jni/GeolocationServiceBridge.cpp \
android/jni/JavaBridge.cpp \
android/jni/JavaSharedClient.cpp \
android/jni/MIMETypeRegistry.cpp \
diff --git a/Source/WebKit/android/AndroidLog.h b/Source/WebKit/android/AndroidLog.h
index f034d35..6b6c1a0 100644
--- a/Source/WebKit/android/AndroidLog.h
+++ b/Source/WebKit/android/AndroidLog.h
@@ -30,6 +30,8 @@
#define LOG_TAG __FILE__
#endif
+#define ATRACE_TAG ATRACE_TAG_WEBVIEW
+
#include <cutils/log.h>
#include <utils/Trace.h>
#include <wtf/CurrentTime.h>
@@ -58,7 +60,7 @@ extern FILE* gRenderTreeFile;
#define INT_RECT_FORMAT "[x=%d,y=%d,w=%d,h=%d]"
#define INT_RECT_ARGS(ir) ir.x(), ir.y(), ir.width(), ir.height()
-#define TRACE_METHOD() android::ScopedTrace __st(ATRACE_TAG_WEBVIEW, __func__);
+#define TRACE_METHOD() android::ScopedTrace __st(ATRACE_TAG, __func__);
#define TIME_METHOD() MethodTimer __method_timer(__func__)
class MethodTimer {
diff --git a/Source/WebKit/android/RenderSkinMediaButton.cpp b/Source/WebKit/android/RenderSkinMediaButton.cpp
index b3aa57d..a2f19c3 100644
--- a/Source/WebKit/android/RenderSkinMediaButton.cpp
+++ b/Source/WebKit/android/RenderSkinMediaButton.cpp
@@ -26,12 +26,13 @@
#define LOG_TAG "WebCore"
#include "config.h"
-#include "android_graphics.h"
+#include "RenderSkinMediaButton.h"
+
#include "Document.h"
#include "IntRect.h"
#include "Node.h"
#include "RenderObject.h"
-#include "RenderSkinMediaButton.h"
+#include "RenderSkinAndroid.h"
#include "RenderSlider.h"
#include "SkCanvas.h"
#include "SkNinePatch.h"
@@ -88,8 +89,9 @@ void RenderSkinMediaButton::Decode()
}
}
-void RenderSkinMediaButton::Draw(SkCanvas* canvas, const IntRect& r, int buttonType,
- bool translucent, RenderObject* o, bool drawBackground)
+void RenderSkinMediaButton::Draw(SkCanvas* canvas, const IntRect& r,
+ MediaButton buttonType, bool translucent,
+ bool drawBackground, const IntRect& thumb)
{
if (!gDecoded) {
Decode();
@@ -179,9 +181,7 @@ void RenderSkinMediaButton::Draw(SkCanvas* canvas, const IntRect& r, int buttonT
SkScalar quarterHeight = SkScalarHalf(SkScalarHalf(bounds.height()));
bounds.fTop += quarterHeight + SkScalarHalf(3);
bounds.fBottom += -quarterHeight + SK_ScalarHalf;
- if (o && o->isSlider()) {
- RenderSlider* slider = toRenderSlider(o);
- IntRect thumb = slider->thumbRect();
+ if (!thumb.isEmpty()) {
// Inset the track by half the width of the thumb, so the track
// does not appear to go beyond the space where the thumb can
// be.
diff --git a/Source/WebKit/android/RenderSkinMediaButton.h b/Source/WebKit/android/RenderSkinMediaButton.h
index 484b90c..98c9e04 100644
--- a/Source/WebKit/android/RenderSkinMediaButton.h
+++ b/Source/WebKit/android/RenderSkinMediaButton.h
@@ -26,27 +26,43 @@
#ifndef RenderSkinMediaButton_h
#define RenderSkinMediaButton_h
-#include "RenderSkinAndroid.h"
+#include "IntRect.h"
class SkCanvas;
namespace WebCore {
-class IntRect;
-class RenderObject;
class RenderSkinMediaButton {
public:
static void Decode();
+
/**
- * Draw the skin to the canvas, using the rectangle for its bounds and the
- * State to determine which skin to use, i.e. focused or not focused.
+ * Button types
*/
- static void Draw(SkCanvas* , const IntRect& , int buttonType, bool translucent = false,
- RenderObject* o = 0, bool drawBackground = true);
+ typedef enum
+ {
+ PAUSE,
+ PLAY,
+ MUTE,
+ REWIND,
+ FORWARD,
+ FULLSCREEN,
+ SPINNER_OUTER,
+ SPINNER_INNER,
+ VIDEO,
+ BACKGROUND_SLIDER,
+ SLIDER_TRACK,
+ SLIDER_THUMB
+ } MediaButton;
+
/**
- * Button types
+ * Draw the skin to the canvas, using the rectangle for its bounds and the
+ * State to determine which skin to use, i.e. focused or not focused.
*/
- enum { PAUSE, PLAY, MUTE, REWIND, FORWARD, FULLSCREEN, SPINNER_OUTER, SPINNER_INNER , VIDEO, BACKGROUND_SLIDER, SLIDER_TRACK, SLIDER_THUMB };
+ static void Draw(SkCanvas* canvas, const IntRect& rect, MediaButton buttonType,
+ bool translucent = false, bool drawBackground = true,
+ const IntRect& thumb = IntRect());
+
/**
* Slider dimensions
*/
diff --git a/Source/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp b/Source/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp
index 907dc3c..9094732 100644
--- a/Source/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp
+++ b/Source/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp
@@ -512,39 +512,6 @@ void ChromeClientAndroid::populateVisitedLinks()
android::WebViewCore::getWebViewCore(view)->populateVisitedLinks(&page->group());
}
-void ChromeClientAndroid::requestGeolocationPermissionForFrame(Frame* frame, Geolocation* geolocation)
-{
- ASSERT(geolocation);
- if (!m_geolocationPermissions) {
- m_geolocationPermissions = new GeolocationPermissions(android::WebViewCore::getWebViewCore(frame->view()),
- m_webFrame->page()->mainFrame());
- }
- m_geolocationPermissions->queryPermissionState(frame);
-}
-
-void ChromeClientAndroid::cancelGeolocationPermissionRequestForFrame(Frame* frame, WebCore::Geolocation*)
-{
- if (m_geolocationPermissions)
- m_geolocationPermissions->cancelPermissionStateQuery(frame);
-}
-
-void ChromeClientAndroid::provideGeolocationPermissions(const String &origin, bool allow, bool remember)
-{
- ASSERT(m_geolocationPermissions);
- m_geolocationPermissions->providePermissionState(origin, allow, remember);
-}
-
-void ChromeClientAndroid::storeGeolocationPermissions()
-{
- GeolocationPermissions::maybeStorePermanentPermissions();
-}
-
-void ChromeClientAndroid::onMainFrameLoadStarted()
-{
- if (m_geolocationPermissions.get())
- m_geolocationPermissions->resetTemporaryPermissionStates();
-}
-
void ChromeClientAndroid::runOpenPanel(Frame* frame,
PassRefPtr<FileChooser> chooser)
{
@@ -605,16 +572,6 @@ void ChromeClientAndroid::reachedApplicationCacheOriginQuota(SecurityOrigin*)
notImplemented();
}
-#if ENABLE(ANDROID_INSTALLABLE_WEB_APPS)
-void ChromeClientAndroid::webAppCanBeInstalled()
-{
- FrameView* frameView = m_webFrame->page()->mainFrame()->view();
- android::WebViewCore* core = android::WebViewCore::getWebViewCore(frameView);
- if (core)
- core->notifyWebAppCanBeInstalled();
-}
-#endif
-
#if ENABLE(VIDEO)
bool ChromeClientAndroid::supportsFullscreenForNode(const Node* node)
{
@@ -627,16 +584,23 @@ void ChromeClientAndroid::enterFullscreenForNode(Node* node)
return;
HTMLMediaElement* videoElement = static_cast<HTMLMediaElement*>(node);
- String url = videoElement->currentSrc();
- LayerAndroid* layer = videoElement->platformLayer();
- if (!layer)
- return;
FrameView* frameView = m_webFrame->page()->mainFrame()->view();
android::WebViewCore* core = android::WebViewCore::getWebViewCore(frameView);
- m_webFrame->page()->mainFrame()->document()->webkitWillEnterFullScreenForElement(videoElement);
if (core)
- core->enterFullscreenForVideoLayer(layer->uniqueId(), url);
+ core->enterFullscreenForVideoLayer();
+
+ MediaPlayer* player = videoElement->player();
+ if (player) {
+ // We need to use the same document object as the
+ // MediaPlayerPrivateAndroid::onStopFullscreen().
+ Document* doc = player->mediaPlayerClient()->mediaPlayerOwningDocument();
+ if (doc)
+ doc->webkitWillEnterFullScreenForElement(videoElement);
+ // Now the player is responsible to trigger to the java side for
+ // entering full screen mode.
+ player->enterFullscreenMode();
+ }
}
void ChromeClientAndroid::exitFullscreenForNode(Node* node)
diff --git a/Source/WebKit/android/WebCoreSupport/ChromeClientAndroid.h b/Source/WebKit/android/WebCoreSupport/ChromeClientAndroid.h
index 36576e6..4d27605 100644
--- a/Source/WebKit/android/WebCoreSupport/ChromeClientAndroid.h
+++ b/Source/WebKit/android/WebCoreSupport/ChromeClientAndroid.h
@@ -28,7 +28,6 @@
#include "ChromeClient.h"
-#include "GeolocationPermissions.h"
#include "PopupMenu.h"
#include "SearchPopupMenu.h"
#include "Timer.h"
@@ -47,13 +46,13 @@ namespace android {
class ChromeClientAndroid : public ChromeClient {
public:
- ChromeClientAndroid() : m_webFrame(0), m_geolocationPermissions(0)
+ ChromeClientAndroid() : m_webFrame(0)
#if USE(ACCELERATED_COMPOSITING)
- , m_rootGraphicsLayer(0)
- , m_needsLayerSync(false)
+ , m_rootGraphicsLayer(0)
+ , m_needsLayerSync(false)
#endif
- , m_triedToReclaimDBQuota(false)
- { }
+ , m_triedToReclaimDBQuota(false)
+ { }
virtual void chromeDestroyed();
virtual void setWindowRect(const FloatRect&);
@@ -147,12 +146,9 @@ namespace android {
#endif
// Methods used to request and provide Geolocation permissions.
- virtual void requestGeolocationPermissionForFrame(Frame*, Geolocation*);
- virtual void cancelGeolocationPermissionRequestForFrame(WebCore::Frame*, WebCore::Geolocation*);
- // Android-specific
- void provideGeolocationPermissions(const String &origin, bool allow, bool remember);
- void storeGeolocationPermissions();
- void onMainFrameLoadStarted();
+ // Not used with client-based Geolocation
+ virtual void requestGeolocationPermissionForFrame(Frame*, Geolocation*) { ASSERT_NOT_REACHED(); }
+ virtual void cancelGeolocationPermissionRequestForFrame(WebCore::Frame*, WebCore::Geolocation*) { ASSERT_NOT_REACHED(); }
virtual void runOpenPanel(Frame*, PassRefPtr<FileChooser>);
virtual void setCursor(const Cursor&);
@@ -184,10 +180,6 @@ namespace android {
virtual void showContextMenu();
#endif
-#if ENABLE(ANDROID_INSTALLABLE_WEB_APPS)
- virtual void webAppCanBeInstalled();
-#endif
-
#if ENABLE(FULLSCREEN_API)
virtual void exitFullScreenForElement(Element*);
#endif
@@ -202,8 +194,6 @@ namespace android {
private:
android::WebFrame* m_webFrame;
- // The Geolocation permissions manager.
- OwnPtr<GeolocationPermissions> m_geolocationPermissions;
#if USE(ACCELERATED_COMPOSITING)
WebCore::GraphicsLayer* m_rootGraphicsLayer;
bool m_needsLayerSync;
diff --git a/Source/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.cpp b/Source/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.cpp
index ac5cd9d..f62b2d1 100644
--- a/Source/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.cpp
+++ b/Source/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.cpp
@@ -76,7 +76,6 @@
#include "WebViewClientError.h"
#include "WebViewCore.h"
#include "autofill/WebAutofill.h"
-#include "android_graphics.h"
#include <androidfw/AssetManager.h>
#include <wtf/text/CString.h>
diff --git a/Source/WebKit/android/WebCoreSupport/GeolocationClientAndroid.cpp b/Source/WebKit/android/WebCoreSupport/GeolocationClientAndroid.cpp
new file mode 100644
index 0000000..7c5b207
--- /dev/null
+++ b/Source/WebKit/android/WebCoreSupport/GeolocationClientAndroid.cpp
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "GeolocationClientAndroid.h"
+
+#include "WebViewCore.h"
+
+#include <Frame.h>
+#include <Page.h>
+
+using WebCore::Geolocation;
+using WebCore::GeolocationClient;
+using WebCore::GeolocationController;
+using WebCore::GeolocationPosition;
+
+namespace android {
+
+GeolocationClientAndroid::GeolocationClientAndroid() : m_webViewCore(0)
+{
+}
+
+GeolocationClientAndroid::~GeolocationClientAndroid()
+{
+}
+
+void GeolocationClientAndroid::geolocationDestroyed()
+{
+ delete this;
+}
+
+void GeolocationClientAndroid::startUpdating()
+{
+ client()->startUpdating();
+}
+
+void GeolocationClientAndroid::stopUpdating()
+{
+ client()->stopUpdating();
+}
+
+void GeolocationClientAndroid::setEnableHighAccuracy(bool enableHighAccuracy)
+{
+ client()->setEnableHighAccuracy(enableHighAccuracy);
+}
+
+GeolocationPosition* GeolocationClientAndroid::lastPosition()
+{
+ return client()->lastPosition();
+}
+
+void GeolocationClientAndroid::requestPermission(Geolocation* geolocation)
+{
+ client()->requestPermission(geolocation);
+}
+
+void GeolocationClientAndroid::cancelPermissionRequest(Geolocation* geolocation)
+{
+ client()->cancelPermissionRequest(geolocation);
+}
+
+void GeolocationClientAndroid::setWebViewCore(WebViewCore* webViewCore)
+{
+ ASSERT(!m_webViewCore);
+ m_webViewCore = webViewCore;
+ ASSERT(m_webViewCore);
+}
+
+GeolocationClient* GeolocationClientAndroid::client() const
+{
+ return m_webViewCore->geolocationManager()->client();
+}
+
+} // namespace android
diff --git a/Source/WebKit/android/WebCoreSupport/GeolocationClientAndroid.h b/Source/WebKit/android/WebCoreSupport/GeolocationClientAndroid.h
new file mode 100644
index 0000000..22405e1
--- /dev/null
+++ b/Source/WebKit/android/WebCoreSupport/GeolocationClientAndroid.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef GeolocationClientAndroid_h
+#define GeolocationClientAndroid_h
+
+#include <GeolocationClient.h>
+
+namespace android {
+
+class WebViewCore;
+
+// The Android implementation of GeolocationClient. Acts as a proxy to
+// the real or mock impl, which is owned by the GeolocationManager.
+class GeolocationClientAndroid : public WebCore::GeolocationClient {
+public:
+ GeolocationClientAndroid();
+ virtual ~GeolocationClientAndroid();
+
+ // GeolocationClient
+ virtual void geolocationDestroyed();
+ virtual void startUpdating();
+ virtual void stopUpdating();
+ virtual void setEnableHighAccuracy(bool);
+ virtual WebCore::GeolocationPosition* lastPosition();
+ virtual void requestPermission(WebCore::Geolocation*);
+ virtual void cancelPermissionRequest(WebCore::Geolocation*);
+
+ void setWebViewCore(WebViewCore*);
+
+private:
+ WebCore::GeolocationClient* client() const;
+
+ WebViewCore* m_webViewCore;
+};
+
+} // namespace android
+
+#endif // GeolocationClientAndroid_h
diff --git a/Source/WebKit/android/WebCoreSupport/GeolocationClientImpl.cpp b/Source/WebKit/android/WebCoreSupport/GeolocationClientImpl.cpp
new file mode 100644
index 0000000..6291b7d
--- /dev/null
+++ b/Source/WebKit/android/WebCoreSupport/GeolocationClientImpl.cpp
@@ -0,0 +1,223 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "GeolocationClientImpl.h"
+
+#include <Frame.h>
+#include <Page.h>
+#include <GeolocationController.h>
+#include <GeolocationError.h>
+#include <GeolocationPosition.h>
+#include <WebViewCore.h>
+#if PLATFORM(ANDROID)
+// Required for sim-eng build
+#include <math.h>
+#endif
+#include <wtf/CurrentTime.h>
+
+using WebCore::Geolocation;
+using WebCore::GeolocationError;
+using WebCore::GeolocationPosition;
+using WebCore::Timer;
+
+using namespace std;
+
+namespace {
+
+bool isPositionMovement(GeolocationPosition* position1, GeolocationPosition* position2)
+{
+ // For the small distances in which we are likely concerned, it's reasonable
+ // to approximate the distance between the two positions as the sum of the
+ // differences in latitude and longitude.
+ double delta = fabs(position1->latitude() - position2->latitude()) + fabs(position1->longitude() - position2->longitude());
+ // Approximate conversion from degrees of arc to metres.
+ delta *= 60 * 1852;
+ // The threshold is when the distance between the two positions exceeds the
+ // worse (larger) of the two accuracies.
+ int maxAccuracy = max(position1->accuracy(), position2->accuracy());
+ return delta > maxAccuracy;
+}
+
+bool isPositionMoreAccurate(GeolocationPosition* position1, GeolocationPosition* position2)
+{
+ return position2->accuracy() < position1->accuracy();
+}
+
+bool isPositionMoreTimely(GeolocationPosition* position1)
+{
+ double currentTime = WTF::currentTime();
+ double maximumAge = 10 * 60; // 10 minutes
+ return currentTime - position1->timestamp() > maximumAge;
+}
+
+} // anonymous namespace
+
+namespace android {
+
+GeolocationClientImpl::GeolocationClientImpl(WebViewCore* webViewCore)
+ : m_webViewCore(webViewCore)
+ , m_timer(this, &GeolocationClientImpl::timerFired)
+ , m_isSuspended(false)
+ , m_useGps(false)
+{
+}
+
+GeolocationClientImpl::~GeolocationClientImpl()
+{
+}
+
+void GeolocationClientImpl::geolocationDestroyed()
+{
+ // Lifetime is managed by GeolocationManager.
+}
+
+void GeolocationClientImpl::startUpdating()
+{
+ // This method is called every time a new watch or one-shot position request
+ // is started. If we already have a position or an error, call back
+ // immediately.
+ if (m_lastPosition || m_lastError) {
+ m_timer.startOneShot(0);
+ }
+
+ // Lazilly create the Java object.
+ bool haveJavaBridge = m_javaBridge;
+ if (!haveJavaBridge)
+ m_javaBridge.set(new GeolocationServiceBridge(this, m_webViewCore));
+ ASSERT(m_javaBridge);
+
+ // Set whether to use GPS before we start the implementation.
+ m_javaBridge->setEnableGps(m_useGps);
+
+ // If we're suspended, don't start the service. It will be started when we
+ // get the call to resume().
+ if (!haveJavaBridge && !m_isSuspended)
+ m_javaBridge->start();
+}
+
+void GeolocationClientImpl::stopUpdating()
+{
+ // TODO: It would be good to re-use the Java bridge object.
+ m_javaBridge.clear();
+ m_useGps = false;
+ // Reset last position and error to make sure that we always try to get a
+ // new position from the client when a request is first made.
+ m_lastPosition = 0;
+ m_lastError = 0;
+
+ if (m_timer.isActive())
+ m_timer.stop();
+}
+
+void GeolocationClientImpl::setEnableHighAccuracy(bool enableHighAccuracy)
+{
+ // On Android, high power == GPS.
+ m_useGps = enableHighAccuracy;
+ if (m_javaBridge)
+ m_javaBridge->setEnableGps(m_useGps);
+}
+
+GeolocationPosition* GeolocationClientImpl::lastPosition()
+{
+ return m_lastPosition.get();
+}
+
+void GeolocationClientImpl::requestPermission(Geolocation* geolocation)
+{
+ permissions()->queryPermissionState(geolocation->frame());
+}
+
+void GeolocationClientImpl::cancelPermissionRequest(Geolocation* geolocation)
+{
+ permissions()->cancelPermissionStateQuery(geolocation->frame());
+}
+
+// Note that there is no guarantee that subsequent calls to this method offer a
+// more accurate or updated position.
+void GeolocationClientImpl::newPositionAvailable(PassRefPtr<GeolocationPosition> position)
+{
+ ASSERT(position);
+ if (!m_lastPosition
+ || isPositionMovement(m_lastPosition.get(), position.get())
+ || isPositionMoreAccurate(m_lastPosition.get(), position.get())
+ || isPositionMoreTimely(m_lastPosition.get())) {
+ m_lastPosition = position;
+ // Remove the last error.
+ m_lastError = 0;
+ m_webViewCore->mainFrame()->page()->geolocationController()->positionChanged(m_lastPosition.get());
+ }
+}
+
+void GeolocationClientImpl::newErrorAvailable(PassRefPtr<WebCore::GeolocationError> error)
+{
+ ASSERT(error);
+ // We leave the last position
+ m_lastError = error;
+ m_webViewCore->mainFrame()->page()->geolocationController()->errorOccurred(m_lastError.get());
+}
+
+void GeolocationClientImpl::suspend()
+{
+ m_isSuspended = true;
+ if (m_javaBridge)
+ m_javaBridge->stop();
+}
+
+void GeolocationClientImpl::resume()
+{
+ m_isSuspended = false;
+ if (m_javaBridge)
+ m_javaBridge->start();
+}
+
+void GeolocationClientImpl::resetTemporaryPermissionStates()
+{
+ permissions()->resetTemporaryPermissionStates();
+}
+
+void GeolocationClientImpl::providePermissionState(String origin, bool allow, bool remember)
+{
+ permissions()->providePermissionState(origin, allow, remember);
+}
+
+GeolocationPermissions* GeolocationClientImpl::permissions() const
+{
+ if (!m_permissions)
+ m_permissions = new GeolocationPermissions(m_webViewCore);
+ return m_permissions.get();
+}
+
+void GeolocationClientImpl::timerFired(Timer<GeolocationClientImpl>* timer)
+{
+ ASSERT(&m_timer == timer);
+ ASSERT(m_lastPosition || m_lastError);
+ if (m_lastPosition)
+ m_webViewCore->mainFrame()->page()->geolocationController()->positionChanged(m_lastPosition.get());
+ else
+ m_webViewCore->mainFrame()->page()->geolocationController()->errorOccurred(m_lastError.get());
+}
+
+} // namespace android
diff --git a/Source/WebKit/android/WebCoreSupport/GeolocationClientImpl.h b/Source/WebKit/android/WebCoreSupport/GeolocationClientImpl.h
new file mode 100644
index 0000000..26e6c0c
--- /dev/null
+++ b/Source/WebKit/android/WebCoreSupport/GeolocationClientImpl.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef GeolocationClientImpl_h
+#define GeolocationClientImpl_h
+
+#include "GeolocationServiceBridge.h"
+#include "GeolocationClient.h"
+#include "GeolocationPermissions.h"
+
+#include <Timer.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+class Geolocation;
+class GeolocationController;
+}
+
+namespace android {
+
+class WebViewCore;
+
+// The real implementation of GeolocationClient.
+class GeolocationClientImpl : public WebCore::GeolocationClient, public GeolocationServiceBridge::Listener {
+public:
+ GeolocationClientImpl(WebViewCore*);
+ virtual ~GeolocationClientImpl();
+
+ // WebCore::GeolocationClient
+ virtual void geolocationDestroyed();
+ virtual void startUpdating();
+ virtual void stopUpdating();
+ virtual void setEnableHighAccuracy(bool);
+ virtual WebCore::GeolocationPosition* lastPosition();
+ virtual void requestPermission(WebCore::Geolocation*);
+ virtual void cancelPermissionRequest(WebCore::Geolocation*);
+
+ // GeolocationServiceBridge::Listener
+ virtual void newPositionAvailable(PassRefPtr<WebCore::GeolocationPosition>);
+ virtual void newErrorAvailable(PassRefPtr<WebCore::GeolocationError>);
+
+ void suspend();
+ void resume();
+ void resetTemporaryPermissionStates();
+ void providePermissionState(String origin, bool allow, bool remember);
+
+private:
+ GeolocationPermissions* permissions() const;
+ void timerFired(WebCore::Timer<GeolocationClientImpl>*);
+
+ WebViewCore* m_webViewCore;
+ RefPtr<WebCore::GeolocationPosition> m_lastPosition;
+ RefPtr<WebCore::GeolocationError> m_lastError;
+ OwnPtr<GeolocationServiceBridge> m_javaBridge;
+ mutable OwnPtr<GeolocationPermissions> m_permissions;
+ WebCore::Timer<GeolocationClientImpl> m_timer;
+ bool m_isSuspended;
+ bool m_useGps;
+};
+
+} // namespace android
+
+#endif // GeolocationClientImpl_h
diff --git a/Source/WebKit/android/WebCoreSupport/GeolocationManager.cpp b/Source/WebKit/android/WebCoreSupport/GeolocationManager.cpp
new file mode 100644
index 0000000..cbf399d
--- /dev/null
+++ b/Source/WebKit/android/WebCoreSupport/GeolocationManager.cpp
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "GeolocationManager.h"
+
+#include "GeolocationClientImpl.h"
+#include "WebViewCore.h"
+
+#include <Frame.h>
+#include <GeolocationError.h>
+#include <GeolocationPosition.h>
+#include <JNIHelp.h>
+#include <Page.h>
+
+using WebCore::GeolocationClient;
+using WebCore::GeolocationClientMock;
+
+namespace android {
+
+GeolocationManager::GeolocationManager(WebViewCore* webViewCore)
+ : m_useMock(false)
+ , m_webViewCore(webViewCore)
+{
+}
+
+GeolocationClient* GeolocationManager::client() const
+{
+ if (m_useMock)
+ return mockClient();
+ return realClient();
+}
+
+void GeolocationManager::suspendRealClient()
+{
+ // Don't create the real client if it's not present.
+ if (m_realClient)
+ m_realClient->suspend();
+}
+
+void GeolocationManager::resumeRealClient()
+{
+ // Don't create the real client if it's not present.
+ if (m_realClient)
+ m_realClient->resume();
+}
+
+void GeolocationManager::resetRealClientTemporaryPermissionStates()
+{
+ // Don't create the real client if it's not present.
+ if (m_realClient)
+ m_realClient->resetTemporaryPermissionStates();
+}
+
+void GeolocationManager::provideRealClientPermissionState(WTF::String origin, bool allow, bool remember)
+{
+ // Don't create the real client if it's not present.
+ if (m_realClient)
+ m_realClient->providePermissionState(origin, allow, remember);
+}
+
+void GeolocationManager::setUseMock()
+{
+ m_useMock = true;
+ m_mockClient.clear();
+}
+
+void GeolocationManager::setMockPosition(PassRefPtr<WebCore::GeolocationPosition> position)
+{
+ ASSERT(m_useMock);
+ mockClient()->setPosition(position);
+}
+
+void GeolocationManager::setMockError(PassRefPtr<WebCore::GeolocationError> error)
+{
+ ASSERT(m_useMock);
+ mockClient()->setError(error);
+}
+
+void GeolocationManager::setMockPermission(bool allowed)
+{
+ ASSERT(m_useMock);
+ mockClient()->setPermission(allowed);
+}
+
+GeolocationClientImpl* GeolocationManager::realClient() const
+{
+ if (!m_realClient)
+ m_realClient.set(new GeolocationClientImpl(m_webViewCore));
+ return m_realClient.get();
+}
+
+GeolocationClientMock* GeolocationManager::mockClient() const
+{
+ ASSERT(m_useMock);
+ if (!m_mockClient) {
+ m_mockClient.set(new GeolocationClientMock);
+ m_mockClient->setController(m_webViewCore->mainFrame()->page()->geolocationController());
+ }
+ return m_mockClient.get();
+}
+
+} // namespace android
diff --git a/Source/WebKit/android/WebCoreSupport/GeolocationManager.h b/Source/WebKit/android/WebCoreSupport/GeolocationManager.h
new file mode 100644
index 0000000..6459db1
--- /dev/null
+++ b/Source/WebKit/android/WebCoreSupport/GeolocationManager.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef GeolocationManager_h
+#define GeolocationManager_h
+
+#include "GeolocationClientImpl.h"
+
+#include <GeolocationClientMock.h>
+#include <OwnPtr.h>
+#include <PassRefPtr.h>
+
+namespace WebCore {
+class GeolocationError;
+class GeolocationPosition;
+}
+
+namespace android {
+
+class GeolocationClientImpl;
+class WebViewCore;
+
+// This class takes care of the fact that the client used for Geolocation
+// may be either the real implementation or a mock. It also handles setting the
+// data on the mock client. This class is owned by WebViewCore and exists to
+// keep cruft out of that class.
+class GeolocationManager {
+public:
+ GeolocationManager(WebViewCore*);
+
+ // For use by GeolocationClientAndroid. Gets the current client, either the
+ // real or mock.
+ WebCore::GeolocationClient* client() const;
+
+ void suspendRealClient();
+ void resumeRealClient();
+ void resetRealClientTemporaryPermissionStates();
+ void provideRealClientPermissionState(WTF::String origin, bool allow, bool remember);
+
+ // Sets use of the Geolocation mock client. Also resets that client.
+ void setUseMock();
+ void setMockPosition(PassRefPtr<WebCore::GeolocationPosition>);
+ void setMockError(PassRefPtr<WebCore::GeolocationError>);
+ void setMockPermission(bool allowed);
+
+private:
+ GeolocationClientImpl* realClient() const;
+ WebCore::GeolocationClientMock* mockClient() const;
+
+ bool m_useMock;
+ WebViewCore* m_webViewCore;
+ mutable OwnPtr<GeolocationClientImpl> m_realClient;
+ mutable OwnPtr<WebCore::GeolocationClientMock> m_mockClient;
+};
+
+} // namespace android
+
+#endif // GeolocationManager_h
diff --git a/Source/WebKit/android/WebCoreSupport/GeolocationPermissions.cpp b/Source/WebKit/android/WebCoreSupport/GeolocationPermissions.cpp
index 36a9b61..fb29bd6 100755
--- a/Source/WebKit/android/WebCoreSupport/GeolocationPermissions.cpp
+++ b/Source/WebKit/android/WebCoreSupport/GeolocationPermissions.cpp
@@ -26,16 +26,16 @@
#include "config.h"
#include "GeolocationPermissions.h"
-#include "DOMWindow.h"
-#include "Frame.h"
-#include "Geolocation.h"
-#include "Navigator.h"
-#include "SQLiteDatabase.h"
-#include "SQLiteFileSystem.h"
-#include "SQLiteStatement.h"
-#include "SQLiteTransaction.h"
#include "WebViewCore.h"
+#include <DOMWindow.h>
+#include <Frame.h>
+#include <Geolocation.h>
+#include <Navigator.h>
+#include <SQLiteDatabase.h>
+#include <SQLiteFileSystem.h>
+#include <SQLiteStatement.h>
+#include <SQLiteTransaction.h>
#include <text/CString.h>
using namespace WebCore;
@@ -51,9 +51,8 @@ String GeolocationPermissions::s_databasePath;
static const char* databaseName = "GeolocationPermissions.db";
-GeolocationPermissions::GeolocationPermissions(WebViewCore* webViewCore, Frame* mainFrame)
+GeolocationPermissions::GeolocationPermissions(WebViewCore* webViewCore)
: m_webViewCore(webViewCore)
- , m_mainFrame(mainFrame)
, m_timer(this, &GeolocationPermissions::timerFired)
{
@@ -266,7 +265,7 @@ void GeolocationPermissions::maybeCallbackFrames(String origin, bool allow)
// or have their contents replaced. Even uniqueChildName is not unique when
// frames are dynamically deleted and created. Instead, we simply call back
// to the Geolocation object in all frames from the correct origin.
- for (Frame* frame = m_mainFrame; frame; frame = frame->tree()->traverseNext()) {
+ for (Frame* frame = m_webViewCore->mainFrame(); frame; frame = frame->tree()->traverseNext()) {
if (origin == frame->document()->securityOrigin()->toString()) {
// If the page has changed, it may no longer have a Geolocation
// object.
diff --git a/Source/WebKit/android/WebCoreSupport/GeolocationPermissions.h b/Source/WebKit/android/WebCoreSupport/GeolocationPermissions.h
index fb31dfe..8f4b96e 100644
--- a/Source/WebKit/android/WebCoreSupport/GeolocationPermissions.h
+++ b/Source/WebKit/android/WebCoreSupport/GeolocationPermissions.h
@@ -26,9 +26,8 @@
#ifndef GeolocationPermissions_h
#define GeolocationPermissions_h
-#include "PlatformString.h"
-#include "Timer.h"
-
+#include <PlatformString.h>
+#include <Timer.h>
#include <wtf/HashMap.h>
#include <wtf/HashSet.h>
#include <wtf/RefCounted.h>
@@ -63,9 +62,8 @@ namespace android {
class GeolocationPermissions : public RefCounted<GeolocationPermissions> {
public:
// Creates the GeolocationPermissions object to manage permissions for
- // the specified main frame (i.e. tab). The WebViewCore is used to
- // communicate with the browser to display UI.
- GeolocationPermissions(WebViewCore* webViewCore, WebCore::Frame* mainFrame);
+ // the WebView.
+ GeolocationPermissions(WebViewCore* webViewCore);
virtual ~GeolocationPermissions();
// Queries the permission state for the specified frame. If the
@@ -140,7 +138,6 @@ namespace android {
const WTF::String& nextOriginInQueue();
WebViewCore* m_webViewCore;
- WebCore::Frame* m_mainFrame;
// A vector of the origins queued to make a permission request.
// The first in the vector is the origin currently making the request.
typedef Vector<WTF::String> OriginVector;
diff --git a/Source/WebKit/android/WebCoreSupport/MediaPlayerPrivateAndroid.cpp b/Source/WebKit/android/WebCoreSupport/MediaPlayerPrivateAndroid.cpp
index 1607b0e..de91766 100644
--- a/Source/WebKit/android/WebCoreSupport/MediaPlayerPrivateAndroid.cpp
+++ b/Source/WebKit/android/WebCoreSupport/MediaPlayerPrivateAndroid.cpp
@@ -30,6 +30,7 @@
#include "BaseLayerAndroid.h"
#include "GraphicsContext.h"
+#include "HTMLMediaElement.h"
#include "SkiaUtils.h"
#include "TilesManager.h"
#include "VideoLayerAndroid.h"
@@ -55,6 +56,7 @@ static const char* g_ProxyJavaClassAudio = "android/webkit/HTML5Audio";
struct MediaPlayerPrivate::JavaGlue {
jobject m_javaProxy;
jmethodID m_play;
+ jmethodID m_enterFullscreenForVideoLayer;
jmethodID m_teardown;
jmethodID m_seek;
jmethodID m_pause;
@@ -191,11 +193,19 @@ void MediaPlayerPrivate::onTimeupdate(int position)
m_player->timeChanged();
}
-void MediaPlayerPrivate::onStopFullscreen()
+void MediaPlayerPrivate::onStopFullscreen(bool stillPlaying)
{
- if (m_player && m_player->mediaPlayerClient()
- && m_player->mediaPlayerClient()->mediaPlayerOwningDocument()) {
- m_player->mediaPlayerClient()->mediaPlayerOwningDocument()->webkitCancelFullScreen();
+ if (m_player && m_player->mediaPlayerClient()) {
+ Document* doc = m_player->mediaPlayerClient()->mediaPlayerOwningDocument();
+ if (doc) {
+ HTMLMediaElement* element =
+ static_cast<HTMLMediaElement*>(doc->webkitCurrentFullScreenElement());
+ element->exitFullscreen();
+ doc->webkitDidExitFullScreenForElement(element);
+
+ if (stillPlaying)
+ element->play(true);
+ }
}
}
@@ -234,6 +244,22 @@ public:
checkException(env);
}
+
+ void enterFullscreenMode()
+ {
+ JNIEnv* env = JSC::Bindings::getJNIEnv();
+ if (!env || !m_url.length() || !m_glue->m_javaProxy)
+ return;
+
+ jstring jUrl = wtfStringToJstring(env, m_url);
+ env->CallVoidMethod(m_glue->m_javaProxy,
+ m_glue->m_enterFullscreenForVideoLayer, jUrl,
+ m_videoLayer->uniqueId());
+ env->DeleteLocalRef(jUrl);
+
+ checkException(env);
+ }
+
bool canLoadPoster() const { return true; }
void setPoster(const String& url)
{
@@ -260,9 +286,6 @@ public:
if (!m_poster || (!m_poster->getPixels() && !m_poster->pixelRef()))
return;
- SkCanvas* canvas = ctxt->platformContext()->getCanvas();
- if (!canvas)
- return;
// We paint with the following rules in mind:
// - only downscale the poster, never upscale
// - maintain the natural aspect ratio of the poster
@@ -273,7 +296,7 @@ public:
int posterX = ((r.width() - posterWidth) / 2) + r.x();
int posterY = ((r.height() - posterHeight) / 2) + r.y();
IntRect targetRect(posterX, posterY, posterWidth, posterHeight);
- canvas->drawBitmapRect(*m_poster, 0, targetRect, 0);
+ ctxt->platformContext()->drawBitmapRect(*m_poster, 0, targetRect);
}
void onPosterFetched(SkBitmap* poster)
@@ -289,6 +312,13 @@ public:
m_naturalSize = IntSize(poster->width(), poster->height());
m_player->sizeChanged();
}
+ // At this time, we know that the proxy has been setup. And it is the
+ // right time to trigger autoplay through the HTMLMediaElement state
+ // change. Since we are using the java MediaPlayer, so we have to
+ // pretend that the MediaPlayer has enough data.
+ m_readyState = MediaPlayer::HaveEnoughData;
+ m_player->readyStateChanged();
+
}
void onPrepared(int duration, int width, int height)
@@ -319,9 +349,13 @@ public:
return;
m_glue = new JavaGlue;
- m_glue->m_getInstance = env->GetStaticMethodID(clazz, "getInstance", "(Landroid/webkit/WebViewCore;I)Landroid/webkit/HTML5VideoViewProxy;");
+ m_glue->m_getInstance =
+ env->GetStaticMethodID(clazz, "getInstance",
+ "(Landroid/webkit/WebViewCore;I)Landroid/webkit/HTML5VideoViewProxy;");
m_glue->m_loadPoster = env->GetMethodID(clazz, "loadPoster", "(Ljava/lang/String;)V");
m_glue->m_play = env->GetMethodID(clazz, "play", "(Ljava/lang/String;II)V");
+ m_glue->m_enterFullscreenForVideoLayer =
+ env->GetMethodID(clazz, "enterFullscreenForVideoLayer", "(Ljava/lang/String;I)V");
m_glue->m_teardown = env->GetMethodID(clazz, "teardown", "()V");
m_glue->m_seek = env->GetMethodID(clazz, "seek", "(I)V");
@@ -628,12 +662,12 @@ static bool SendSurfaceTexture(JNIEnv* env, jobject obj, jobject surfTex,
return true;
}
-static void OnStopFullscreen(JNIEnv* env, jobject obj, int pointer)
+static void OnStopFullscreen(JNIEnv* env, jobject obj, int stillPlaying, int pointer)
{
if (pointer) {
WebCore::MediaPlayerPrivate* player =
reinterpret_cast<WebCore::MediaPlayerPrivate*>(pointer);
- player->onStopFullscreen();
+ player->onStopFullscreen(stillPlaying);
}
}
@@ -645,7 +679,7 @@ static JNINativeMethod g_MediaPlayerMethods[] = {
(void*) OnPrepared },
{ "nativeOnEnded", "(I)V",
(void*) OnEnded },
- { "nativeOnStopFullscreen", "(I)V",
+ { "nativeOnStopFullscreen", "(II)V",
(void*) OnStopFullscreen },
{ "nativeOnPaused", "(I)V",
(void*) OnPaused },
diff --git a/Source/WebKit/android/WebCoreSupport/MemoryUsage.cpp b/Source/WebKit/android/WebCoreSupport/MemoryUsage.cpp
index 592fad3..5b8c33b 100644
--- a/Source/WebKit/android/WebCoreSupport/MemoryUsage.cpp
+++ b/Source/WebKit/android/WebCoreSupport/MemoryUsage.cpp
@@ -26,50 +26,22 @@
#include "config.h"
#include "MemoryUsage.h"
-#include <malloc.h>
-#include <wtf/CurrentTime.h>
-
#include <v8.h>
-using namespace WTF;
-
-class MemoryUsageCache {
-public:
- MemoryUsageCache()
- : m_cachedMemoryUsage(0)
- , m_cacheTime(0)
- {
- }
+// Workaround an issue where malloc_footprint is in malloc.h
+// but is not actually implemented.
+// See: http://code.google.com/p/android/issues/detail?id=34897
+extern "C" size_t dlmalloc_footprint(void);
- int getCachedMemoryUsage(bool forceFresh);
-
-private:
- unsigned m_cachedMemoryUsage;
- double m_cacheTime;
- static const int CACHE_VALIDITY_MS = 2000;
-};
+using namespace WTF;
-int MemoryUsageCache::getCachedMemoryUsage(bool forceFresh)
+int MemoryUsage::memoryUsageMb(bool /* forceFresh */)
{
- if (!forceFresh && currentTimeMS() <= m_cacheTime + CACHE_VALIDITY_MS)
- return m_cachedMemoryUsage;
-
- struct mallinfo minfo = mallinfo();
- m_cachedMemoryUsage = (minfo.hblkhd + minfo.arena) >> 20;
-
+ size_t footprint = dlmalloc_footprint() >> 20;
v8::HeapStatistics stat;
v8::V8::GetHeapStatistics(&stat);
unsigned v8Usage = stat.total_heap_size() >> 20;
- m_cachedMemoryUsage += v8Usage;
-
- m_cacheTime = currentTimeMS();
- return m_cachedMemoryUsage;
-}
-
-int MemoryUsage::memoryUsageMb(bool forceFresh)
-{
- static MemoryUsageCache cache;
- return cache.getCachedMemoryUsage(forceFresh);
+ return footprint + v8Usage;
}
int MemoryUsage::m_lowMemoryUsageMb = 0;
diff --git a/Source/WebKit/android/WebCoreSupport/PlatformBridge.cpp b/Source/WebKit/android/WebCoreSupport/PlatformBridge.cpp
index 9b8aac8..6e39c33 100644
--- a/Source/WebKit/android/WebCoreSupport/PlatformBridge.cpp
+++ b/Source/WebKit/android/WebCoreSupport/PlatformBridge.cpp
@@ -43,6 +43,7 @@
#include "WebViewCore.h"
#include "npruntime.h"
+#include <gui/ISurfaceComposer.h>
#include <gui/SurfaceComposerClient.h>
#include <ui/DisplayInfo.h>
#include <ui/PixelFormat.h>
@@ -111,12 +112,6 @@ NPObject* PlatformBridge::pluginScriptableObject(Widget* widget)
return pluginView->getNPObject();
}
-bool PlatformBridge::isWebViewPaused(const WebCore::FrameView* frameView)
-{
- android::WebViewCore* webViewCore = android::WebViewCore::getWebViewCore(frameView);
- return webViewCore->isPaused();
-}
-
bool PlatformBridge::popupsAllowed(NPP)
{
return false;
@@ -130,15 +125,21 @@ String PlatformBridge::resolveFilePathForContentUri(const String& contentUri)
int PlatformBridge::PlatformBridge::screenDepth()
{
+ android::sp<android::IBinder> display(
+ android::SurfaceComposerClient::getBuiltInDisplay(
+ android::ISurfaceComposer::eDisplayIdMain));
android::DisplayInfo info;
- android::SurfaceComposerClient::getDisplayInfo(android::DisplayID(0), &info);
+ android::SurfaceComposerClient::getDisplayInfo(display, &info);
return info.pixelFormatInfo.bitsPerPixel;
}
FloatRect PlatformBridge::screenRect()
{
+ android::sp<android::IBinder> display(
+ android::SurfaceComposerClient::getBuiltInDisplay(
+ android::ISurfaceComposer::eDisplayIdMain));
android::DisplayInfo info;
- android::SurfaceComposerClient::getDisplayInfo(android::DisplayID(0), &info);
+ android::SurfaceComposerClient::getDisplayInfo(display, &info);
return FloatRect(0.0, 0.0, info.w, info.h);
}
@@ -170,10 +171,10 @@ void PlatformBridge::updateViewport(FrameView* frameView)
webViewCore->updateViewport();
}
-void PlatformBridge::updateTextfield(FrameView* frameView, Node* nodePtr, bool changeToPassword, const WTF::String& text)
+void PlatformBridge::updateTextfield(FrameView* frameView, Node* nodePtr, const WTF::String& text)
{
android::WebViewCore* webViewCore = android::WebViewCore::getWebViewCore(frameView);
- webViewCore->updateTextfield(nodePtr, changeToPassword, text);
+ webViewCore->updateTextfield(nodePtr, text);
}
void PlatformBridge::setScrollPosition(ScrollView* scrollView, int x, int y) {
diff --git a/Source/WebKit/android/WebCoreSupport/WebCookieJar.cpp b/Source/WebKit/android/WebCoreSupport/WebCookieJar.cpp
index 0af3cc2..f42f307 100644
--- a/Source/WebKit/android/WebCoreSupport/WebCookieJar.cpp
+++ b/Source/WebKit/android/WebCoreSupport/WebCookieJar.cpp
@@ -189,7 +189,7 @@ int WebCookieJar::getNumCookiesInDatabase()
return cookieStore()->GetCookieMonster()->GetAllCookies().size();
}
-class FlushSemaphore : public base::RefCounted<FlushSemaphore>
+class FlushSemaphore : public base::RefCountedThreadSafe<FlushSemaphore>
{
public:
FlushSemaphore()
diff --git a/Source/WebKit/android/WebCoreSupport/WebRequest.cpp b/Source/WebKit/android/WebCoreSupport/WebRequest.cpp
index 9d16378..dda0ee1 100644
--- a/Source/WebKit/android/WebCoreSupport/WebRequest.cpp
+++ b/Source/WebKit/android/WebCoreSupport/WebRequest.cpp
@@ -83,6 +83,7 @@ WebRequest::WebRequest(WebUrlLoaderClient* loader, const WebResourceRequest& web
: m_urlLoader(loader)
, m_url(webResourceRequest.url())
, m_userAgent(webResourceRequest.userAgent())
+ , m_referer(webResourceRequest.referrer())
, m_loadState(Created)
, m_authRequestCount(0)
, m_cacheMode(0)
@@ -109,6 +110,7 @@ WebRequest::WebRequest(WebUrlLoaderClient* loader, const WebResourceRequest& web
, m_interceptResponse(intercept)
, m_url(webResourceRequest.url())
, m_userAgent(webResourceRequest.userAgent())
+ , m_referer(webResourceRequest.referrer())
, m_loadState(Created)
, m_authRequestCount(0)
, m_cacheMode(0)
@@ -136,6 +138,11 @@ const std::string& WebRequest::getUserAgent() const
return m_userAgent;
}
+const std::string& WebRequest::getReferer() const
+{
+ return m_referer;
+}
+
#ifdef LOG_REQUESTS
namespace {
int remaining = 0;
diff --git a/Source/WebKit/android/WebCoreSupport/WebRequest.h b/Source/WebKit/android/WebCoreSupport/WebRequest.h
index d9054e9..4a4e10b 100644
--- a/Source/WebKit/android/WebCoreSupport/WebRequest.h
+++ b/Source/WebKit/android/WebCoreSupport/WebRequest.h
@@ -89,6 +89,7 @@ public:
const std::string& getUrl() const;
const std::string& getUserAgent() const;
+ const std::string& getReferer() const;
void setSync(bool sync) { m_isSync = sync; }
private:
@@ -109,6 +110,7 @@ private:
scoped_ptr<UrlInterceptResponse> m_interceptResponse;
std::string m_url;
std::string m_userAgent;
+ std::string m_referer;
LoadState m_loadState;
int m_authRequestCount;
int m_cacheMode;
diff --git a/Source/WebKit/android/WebCoreSupport/WebUrlLoaderClient.cpp b/Source/WebKit/android/WebCoreSupport/WebUrlLoaderClient.cpp
index 5df0ed2..003b334 100644
--- a/Source/WebKit/android/WebCoreSupport/WebUrlLoaderClient.cpp
+++ b/Source/WebKit/android/WebCoreSupport/WebUrlLoaderClient.cpp
@@ -245,7 +245,7 @@ void WebUrlLoaderClient::downloadFile()
if (m_response) {
std::string contentDisposition;
m_response->getHeader("content-disposition", &contentDisposition);
- m_webFrame->downloadStart(m_response->getUrl(), m_request->getUserAgent(), contentDisposition, m_response->getMimeType(), m_response->getExpectedSize());
+ m_webFrame->downloadStart(m_response->getUrl(), m_request->getUserAgent(), contentDisposition, m_response->getMimeType(), m_request->getReferer(), m_response->getExpectedSize());
m_isCertMimeType = isMimeTypeForCert(m_response->getMimeType());
// Currently, only certificate mime type needs to receive the data.
diff --git a/Source/WebCore/platform/android/GeolocationServiceBridge.cpp b/Source/WebKit/android/jni/GeolocationServiceBridge.cpp
index 697b63b..056c788 100644
--- a/Source/WebCore/platform/android/GeolocationServiceBridge.cpp
+++ b/Source/WebKit/android/jni/GeolocationServiceBridge.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2009, The Android Open Source Project
+ * Copyright 2012, The Android Open Source Project
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -26,16 +26,17 @@
#include "config.h"
#include "GeolocationServiceBridge.h"
-#include "Frame.h"
-#include "GeolocationServiceAndroid.h"
-#include "Geoposition.h"
-#include "PositionError.h"
#include "WebViewCore.h"
-#include <JNIHelp.h>
-namespace WebCore {
+#include <GeolocationError.h>
+#include <GeolocationPosition.h>
+#include <JNIHelp.h>
using JSC::Bindings::getJNIEnv;
+using WebCore::GeolocationError;
+using WebCore::GeolocationPosition;
+
+namespace android {
static const char* javaGeolocationServiceClassName = "android/webkit/GeolocationService";
enum javaGeolocationServiceClassMethods {
@@ -71,12 +72,12 @@ enum javaLocationClassMethods {
};
static jmethodID javaLocationClassMethodIDs[LocationMethodCount];
-GeolocationServiceBridge::GeolocationServiceBridge(ListenerInterface* listener, Frame* frame)
+GeolocationServiceBridge::GeolocationServiceBridge(Listener* listener, WebViewCore* webViewCore)
: m_listener(listener)
, m_javaGeolocationServiceObject(0)
{
ASSERT(m_listener);
- startJavaImplementation(frame);
+ startJavaImplementation(webViewCore);
}
GeolocationServiceBridge::~GeolocationServiceBridge()
@@ -115,18 +116,17 @@ void GeolocationServiceBridge::newLocationAvailable(JNIEnv* env, jclass, jlong n
ASSERT(nativeObject);
ASSERT(location);
GeolocationServiceBridge* object = reinterpret_cast<GeolocationServiceBridge*>(nativeObject);
- object->m_listener->newPositionAvailable(toGeoposition(env, location));
+ object->m_listener->newPositionAvailable(toGeolocationPosition(env, location));
}
void GeolocationServiceBridge::newErrorAvailable(JNIEnv* env, jclass, jlong nativeObject, jstring message)
{
GeolocationServiceBridge* object = reinterpret_cast<GeolocationServiceBridge*>(nativeObject);
- RefPtr<PositionError> error =
- PositionError::create(PositionError::POSITION_UNAVAILABLE, android::jstringToWtfString(env, message));
+ RefPtr<GeolocationError> error = GeolocationError::create(GeolocationError::PositionUnavailable, jstringToWtfString(env, message));
object->m_listener->newErrorAvailable(error.release());
}
-PassRefPtr<Geoposition> GeolocationServiceBridge::toGeoposition(JNIEnv *env, const jobject &location)
+PassRefPtr<GeolocationPosition> GeolocationServiceBridge::toGeolocationPosition(JNIEnv *env, const jobject &location)
{
// Altitude is optional and may not be supplied.
bool hasAltitude =
@@ -155,21 +155,18 @@ PassRefPtr<Geoposition> GeolocationServiceBridge::toGeoposition(JNIEnv *env, con
env->CallFloatMethod(location, javaLocationClassMethodIDs[LocationMethodGetSpeed]) :
0.0;
- RefPtr<Coordinates> newCoordinates = WebCore::Coordinates::create(
+ return GeolocationPosition::create(
+ env->CallLongMethod(location, javaLocationClassMethodIDs[LocationMethodGetTime]) / 1000.0,
env->CallDoubleMethod(location, javaLocationClassMethodIDs[LocationMethodGetLatitude]),
env->CallDoubleMethod(location, javaLocationClassMethodIDs[LocationMethodGetLongitude]),
- hasAltitude, Altitude,
Accuracy,
+ hasAltitude, Altitude,
false, 0.0, // AltitudeAccuracy not provided.
hasHeading, heading,
hasSpeed, speed);
-
- return WebCore::Geoposition::create(
- newCoordinates.release(),
- env->CallLongMethod(location, javaLocationClassMethodIDs[LocationMethodGetTime]));
}
-void GeolocationServiceBridge::startJavaImplementation(Frame* frame)
+void GeolocationServiceBridge::startJavaImplementation(WebViewCore* webViewCore)
{
JNIEnv* env = getJNIEnv();
@@ -188,7 +185,7 @@ void GeolocationServiceBridge::startJavaImplementation(Frame* frame)
env->GetMethodID(javaGeolocationServiceClass, "setEnableGps", "(Z)V");
// Create the Java GeolocationService object.
- jobject context = android::WebViewCore::getWebViewCore(frame->view())->getContext();
+ jobject context = webViewCore->getContext();
if (!context)
return;
jlong nativeObject = reinterpret_cast<jlong>(this);
@@ -237,10 +234,9 @@ void GeolocationServiceBridge::startJavaImplementation(Frame* frame)
void GeolocationServiceBridge::stopJavaImplementation()
{
- // Called by GeolocationServiceAndroid on WebKit thread.
if (!m_javaGeolocationServiceObject)
return;
getJNIEnv()->DeleteGlobalRef(m_javaGeolocationServiceObject);
}
-} // namespace WebCore
+} // namespace android
diff --git a/Source/WebCore/platform/android/GeolocationServiceBridge.h b/Source/WebKit/android/jni/GeolocationServiceBridge.h
index 3997d65..826ba71 100644
--- a/Source/WebCore/platform/android/GeolocationServiceBridge.h
+++ b/Source/WebKit/android/jni/GeolocationServiceBridge.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2009, The Android Open Source Project
+ * Copyright 2012, The Android Open Source Project
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -26,22 +26,31 @@
#ifndef GeolocationServiceBridge_h
#define GeolocationServiceBridge_h
-#include "JNIUtility.h"
+#include <JNIUtility.h>
#include <wtf/PassRefPtr.h>
namespace WebCore {
+class GeolocationError;
+class GeolocationPosition;
+}
-class Frame;
-class GeolocationServiceAndroid;
-class Geoposition;
+namespace android {
+
+class WebViewCore;
// GeolocationServiceBridge is the bridge to the Java implementation. It manages
// the lifetime of the Java object. It is an implementation detail of
-// GeolocationServiceAndroid.
+// GeolocationClientAndroid.
class GeolocationServiceBridge {
public:
- typedef GeolocationServiceAndroid ListenerInterface;
- GeolocationServiceBridge(ListenerInterface* listener, Frame* frame);
+ class Listener {
+ public:
+ virtual ~Listener() {}
+ virtual void newPositionAvailable(PassRefPtr<WebCore::GeolocationPosition>) = 0;
+ virtual void newErrorAvailable(PassRefPtr<WebCore::GeolocationError>) = 0;
+ };
+
+ GeolocationServiceBridge(Listener*, WebViewCore*);
~GeolocationServiceBridge();
bool start();
@@ -51,16 +60,16 @@ public:
// Static wrapper functions to hide JNI nastiness.
static void newLocationAvailable(JNIEnv *env, jclass, jlong nativeObject, jobject location);
static void newErrorAvailable(JNIEnv *env, jclass, jlong nativeObject, jstring message);
- static PassRefPtr<Geoposition> toGeoposition(JNIEnv *env, const jobject &location);
+ static PassRefPtr<WebCore::GeolocationPosition> toGeolocationPosition(JNIEnv *env, const jobject &location);
private:
- void startJavaImplementation(Frame* frame);
+ void startJavaImplementation(WebViewCore*);
void stopJavaImplementation();
- ListenerInterface* m_listener;
+ Listener* m_listener;
jobject m_javaGeolocationServiceObject;
};
-} // namespace WebCore
+} // namespace android
#endif // GeolocationServiceBridge_h
diff --git a/Source/WebKit/android/jni/MockGeolocation.cpp b/Source/WebKit/android/jni/MockGeolocation.cpp
index 250953f..d588010 100755
--- a/Source/WebKit/android/jni/MockGeolocation.cpp
+++ b/Source/WebKit/android/jni/MockGeolocation.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2009, The Android Open Source Project
+ * Copyright 2012, The Android Open Source Project
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -23,19 +23,17 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-// The functions in this file are used to configure the mock GeolocationService
+// The functions in this file are used to configure the mock Geolocation client
// for the LayoutTests.
#include "config.h"
-#include "Coordinates.h"
-#include "GeolocationServiceMock.h"
-#include "Geoposition.h"
-#include "JavaSharedClient.h"
-#include "PositionError.h"
-#include "WebCoreJni.h"
-#include <JNIHelp.h>
-#include <JNIUtility.h>
+#include "WebViewCore.h"
+
+#include <GeolocationError.h>
+#include <GeolocationPosition.h>
+#include "JNIHelp.h"
+#include "ScopedLocalRef.h"
#include <wtf/CurrentTime.h>
using namespace WebCore;
@@ -44,30 +42,46 @@ namespace android {
static const char* javaMockGeolocationClass = "android/webkit/MockGeolocation";
-static void setPosition(JNIEnv* env, jobject, double latitude, double longitude, double accuracy)
+WebViewCore* getWebViewCore(JNIEnv* env, jobject webViewCore)
+{
+ ScopedLocalRef<jclass> webViewCoreClass(env, env->FindClass("android/webkit/WebViewCore"));
+ jfieldID nativeClassField = env->GetFieldID(webViewCoreClass.get(), "mNativeClass", "I");
+ return reinterpret_cast<WebViewCore*>(env->GetIntField(webViewCore, nativeClassField));
+}
+
+static void setUseMock(JNIEnv* env, jobject, jobject webViewCore)
+{
+ getWebViewCore(env, webViewCore)->geolocationManager()->setUseMock();
+}
+
+static void setPosition(JNIEnv* env, jobject, jobject webViewCore, double latitude, double longitude, double accuracy)
+{
+ getWebViewCore(env, webViewCore)->geolocationManager()->setMockPosition(GeolocationPosition::create(WTF::currentTime(),
+ latitude,
+ longitude,
+ accuracy,
+ false, 0.0, // altitude,
+ false, 0.0, // altitudeAccuracy,
+ false, 0.0, // heading
+ false, 0.0)); // speed
+}
+
+static void setError(JNIEnv* env, jobject, jobject webViewCore, int code, jstring message)
{
- RefPtr<Coordinates> coordinates = Coordinates::create(latitude,
- longitude,
- false, 0.0, // altitude,
- accuracy,
- false, 0.0, // altitudeAccuracy,
- false, 0.0, // heading
- false, 0.0); // speed
- RefPtr<Geoposition> position = Geoposition::create(coordinates.release(), WTF::currentTimeMS());
- GeolocationServiceMock::setPosition(position.release());
+ GeolocationError::ErrorCode codeEnum = static_cast<GeolocationError::ErrorCode>(code);
+ getWebViewCore(env, webViewCore)->geolocationManager()->setMockError(GeolocationError::create(codeEnum, jstringToWtfString(env, message)));
}
-static void setError(JNIEnv* env, jobject, int code, jstring message)
+static void setPermission(JNIEnv* env, jobject, jobject webViewCore, bool allow)
{
- PositionError::ErrorCode codeEnum = static_cast<PositionError::ErrorCode>(code);
- String messageString = jstringToWtfString(env, message);
- RefPtr<PositionError> error = PositionError::create(codeEnum, messageString);
- GeolocationServiceMock::setError(error.release());
+ getWebViewCore(env, webViewCore)->geolocationManager()->setMockPermission(allow);
}
static JNINativeMethod gMockGeolocationMethods[] = {
- { "nativeSetPosition", "(DDD)V", (void*) setPosition },
- { "nativeSetError", "(ILjava/lang/String;)V", (void*) setError }
+ { "nativeSetUseMock", "(Landroid/webkit/WebViewCore;)V", (void*) setUseMock },
+ { "nativeSetPosition", "(Landroid/webkit/WebViewCore;DDD)V", (void*) setPosition },
+ { "nativeSetError", "(Landroid/webkit/WebViewCore;ILjava/lang/String;)V", (void*) setError },
+ { "nativeSetPermission", "(Landroid/webkit/WebViewCore;Z)V", (void*) setPermission },
};
int registerMockGeolocation(JNIEnv* env)
diff --git a/Source/WebKit/android/jni/PicturePile.cpp b/Source/WebKit/android/jni/PicturePile.cpp
index ccdfa59..f995e92 100644
--- a/Source/WebKit/android/jni/PicturePile.cpp
+++ b/Source/WebKit/android/jni/PicturePile.cpp
@@ -35,11 +35,16 @@
#include "PlatformGraphicsContextSkia.h"
#include "SkCanvas.h"
#include "SkNWayCanvas.h"
-#include "SkPicture.h"
#include "SkPixelRef.h"
#include "SkRect.h"
#include "SkRegion.h"
+#if USE_RECORDING_CONTEXT
+#include "PlatformGraphicsContextRecording.h"
+#else
+#include "SkPicture.h"
+#endif
+
#define ENABLE_PRERENDERED_INVALS true
#define MAX_OVERLAP_COUNT 2
#define MAX_OVERLAP_AREA .7
@@ -50,11 +55,18 @@ static SkIRect toSkIRect(const IntRect& rect) {
return SkIRect::MakeXYWH(rect.x(), rect.y(), rect.width(), rect.height());
}
-static IntRect extractClipBounds(SkCanvas* canvas, const IntSize& size) {
- SkRect clip;
- canvas->getClipBounds(&clip);
- clip.intersect(0, 0, size.width(), size.height());
- return enclosingIntRect(clip);
+PictureContainer::PictureContainer(const PictureContainer& other)
+ : picture(other.picture)
+ , area(other.area)
+ , dirty(other.dirty)
+ , prerendered(other.prerendered)
+{
+ SkSafeRef(picture);
+}
+
+PictureContainer::~PictureContainer()
+{
+ SkSafeUnref(picture);
}
PicturePile::PicturePile(const PicturePile& other)
@@ -64,15 +76,6 @@ PicturePile::PicturePile(const PicturePile& other)
{
}
-PicturePile::PicturePile(SkPicture* picture)
-{
- m_size = IntSize(picture->width(), picture->height());
- PictureContainer pc(IntRect(0, 0, m_size.width(), m_size.height()));
- pc.picture = picture;
- pc.dirty = false;
- m_pile.append(pc);
-}
-
void PicturePile::draw(SkCanvas* canvas)
{
/* Loop down recursively, subtracting the previous clip from the SkRegion,
@@ -81,10 +84,10 @@ void PicturePile::draw(SkCanvas* canvas)
* the rect bounds of the SkRegion for the clip, so this still can't be
* used for translucent surfaces
*/
- TRACE_METHOD();
- IntRect clipBounds = extractClipBounds(canvas, m_size);
- SkRegion clipRegion(toSkIRect(clipBounds));
- drawWithClipRecursive(canvas, clipRegion, m_pile.size() - 1);
+ if (canvas->quickReject(SkRect::MakeWH(m_size.width(), m_size.height()),
+ SkCanvas::kBW_EdgeType))
+ return;
+ drawWithClipRecursive(canvas, m_pile.size() - 1);
}
void PicturePile::clearPrerenders()
@@ -93,25 +96,23 @@ void PicturePile::clearPrerenders()
m_pile[i].prerendered.clear();
}
-void PicturePile::drawWithClipRecursive(SkCanvas* canvas, SkRegion& clipRegion,
- int index)
+void PicturePile::drawWithClipRecursive(SkCanvas* canvas, int index)
{
// TODO: Add some debug visualizations of this
- if (index < 0 || clipRegion.isEmpty())
+ if (index < 0)
return;
PictureContainer& pc = m_pile[index];
- IntRect intersection = clipRegion.getBounds();
- intersection.intersect(pc.area);
- if (pc.picture && !intersection.isEmpty()) {
- clipRegion.op(intersection, SkRegion::kDifference_Op);
- drawWithClipRecursive(canvas, clipRegion, index - 1);
- int saved = canvas->save();
- canvas->clipRect(intersection);
- canvas->translate(pc.area.x(), pc.area.y());
- canvas->drawPicture(*pc.picture);
+ if (pc.picture && !canvas->quickReject(pc.area, SkCanvas::kBW_EdgeType)) {
+ int saved = canvas->save(SkCanvas::kClip_SaveFlag);
+ if (canvas->clipRect(pc.area, SkRegion::kDifference_Op))
+ drawWithClipRecursive(canvas, index - 1);
+ canvas->restoreToCount(saved);
+ saved = canvas->save(SkCanvas::kClip_SaveFlag);
+ if (canvas->clipRect(pc.area))
+ drawPicture(canvas, pc);
canvas->restoreToCount(saved);
} else
- drawWithClipRecursive(canvas, clipRegion, index - 1);
+ drawWithClipRecursive(canvas, index - 1);
}
// Used by WebViewCore
@@ -140,14 +141,30 @@ void PicturePile::setSize(const IntSize& size)
{
if (m_size == size)
return;
+ IntSize oldSize = m_size;
m_size = size;
- // TODO: See above about just adding invals for new content
- m_pile.clear();
- m_webkitInvals.clear();
- if (!size.isEmpty()) {
- IntRect area(0, 0, size.width(), size.height());
- m_webkitInvals.append(area);
- m_pile.append(area);
+ if (size.width() <= oldSize.width() && size.height() <= oldSize.height()) {
+ // We are shrinking - huzzah, nothing to do!
+ // TODO: Loop through and throw out Pictures that are now clipped out
+ } else if (oldSize.width() == size.width()) {
+ // Only changing vertically
+ IntRect rect(0, std::min(oldSize.height(), size.height()),
+ size.width(), std::abs(oldSize.height() - size.height()));
+ invalidate(rect);
+ } else if (oldSize.height() == size.height()) {
+ // Only changing horizontally
+ IntRect rect(std::min(oldSize.width(), size.width()), 0,
+ std::abs(oldSize.width() - size.width()), size.height());
+ invalidate(rect);
+ } else {
+ // Both width & height changed, full inval :(
+ m_pile.clear();
+ m_webkitInvals.clear();
+ if (!size.isEmpty()) {
+ IntRect area(0, 0, size.width(), size.height());
+ m_webkitInvals.append(area);
+ m_pile.append(area);
+ }
}
}
@@ -163,43 +180,8 @@ void PicturePile::updatePicturesIfNeeded(PicturePainter* painter)
void PicturePile::updatePicture(PicturePainter* painter, PictureContainer& pc)
{
- /* The ref counting here is a bit unusual. What happens is begin/end recording
- * will ref/unref the recording canvas. However, 'canvas' might be pointing
- * at an SkNWayCanvas instead of the recording canvas, which needs to be
- * unref'd. Thus what we do is ref the recording canvas so that we can
- * always unref whatever canvas we have at the end.
- */
TRACE_METHOD();
- SkPicture* picture = new SkPicture();
- SkCanvas* canvas = picture->beginRecording(pc.area.width(), pc.area.height(),
- SkPicture::kUsePathBoundsForClip_RecordingFlag);
- SkSafeRef(canvas);
- canvas->translate(-pc.area.x(), -pc.area.y());
- IntRect drawArea = pc.area;
- if (pc.prerendered.get()) {
- SkCanvas* prerender = painter->createPrerenderCanvas(pc.prerendered.get());
- if (!prerender) {
- ALOGV("Failed to create prerendered for " INT_RECT_FORMAT,
- INT_RECT_ARGS(pc.prerendered->area));
- pc.prerendered.clear();
- } else {
- drawArea.unite(pc.prerendered->area);
- SkNWayCanvas* nwayCanvas = new SkNWayCanvas(drawArea.width(), drawArea.height());
- nwayCanvas->translate(-drawArea.x(), -drawArea.y());
- nwayCanvas->addCanvas(canvas);
- nwayCanvas->addCanvas(prerender);
- SkSafeUnref(canvas);
- SkSafeUnref(prerender);
- canvas = nwayCanvas;
- }
- }
- WebCore::PlatformGraphicsContextSkia pgc(canvas);
- WebCore::GraphicsContext gc(&pgc);
- ALOGV("painting picture: " INT_RECT_FORMAT, INT_RECT_ARGS(drawArea));
- painter->paintContents(&gc, drawArea);
- SkSafeUnref(canvas);
- picture->endRecording();
-
+ Picture* picture = recordPicture(painter, pc);
SkSafeUnref(pc.picture);
pc.picture = picture;
pc.dirty = false;
@@ -298,4 +280,97 @@ PrerenderedInval* PicturePile::prerenderedInvalForArea(const IntRect& area)
return 0;
}
+bool PicturePile::hasText() const
+{
+ for (size_t i = 0; i < m_pile.size(); i++) {
+ if (m_pile[i].hasText)
+ return true;
+ }
+ return false;
+}
+
+bool PicturePile::isEmpty() const
+{
+ for (size_t i = 0; i < m_pile.size(); i++) {
+ if (m_pile[i].picture)
+ return false;
+ }
+ return true;
+}
+
+#if USE_RECORDING_CONTEXT
+void PicturePile::drawPicture(SkCanvas* canvas, PictureContainer& pc)
+{
+ TRACE_METHOD();
+ pc.picture->draw(canvas);
+}
+
+Picture* PicturePile::recordPicture(PicturePainter* painter, PictureContainer& pc)
+{
+ pc.prerendered.clear(); // TODO: Support? Not needed?
+
+ Recording* picture = new Recording();
+ WebCore::PlatformGraphicsContextRecording pgc(picture);
+ WebCore::GraphicsContext gc(&pgc);
+ painter->paintContents(&gc, pc.area);
+ pc.hasText = pgc.hasText();
+ if (pgc.isEmpty()) {
+ SkSafeUnref(picture);
+ picture = 0;
+ }
+
+ return picture;
+}
+#else
+void PicturePile::drawPicture(SkCanvas* canvas, PictureContainer& pc)
+{
+ canvas->translate(pc.area.x(), pc.area.y());
+ pc.picture->draw(canvas);
+}
+
+Picture* PicturePile::recordPicture(PicturePainter* painter, PictureContainer& pc)
+{
+ /* The ref counting here is a bit unusual. What happens is begin/end recording
+ * will ref/unref the recording canvas. However, 'canvas' might be pointing
+ * at an SkNWayCanvas instead of the recording canvas, which needs to be
+ * unref'd. Thus what we do is ref the recording canvas so that we can
+ * always unref whatever canvas we have at the end.
+ */
+ SkPicture* picture = new SkPicture();
+ SkCanvas* canvas = picture->beginRecording(pc.area.width(), pc.area.height(),
+ SkPicture::kUsePathBoundsForClip_RecordingFlag);
+ SkSafeRef(canvas);
+ canvas->translate(-pc.area.x(), -pc.area.y());
+ IntRect drawArea = pc.area;
+ if (pc.prerendered.get()) {
+ SkCanvas* prerender = painter->createPrerenderCanvas(pc.prerendered.get());
+ if (!prerender) {
+ ALOGV("Failed to create prerendered for " INT_RECT_FORMAT,
+ INT_RECT_ARGS(pc.prerendered->area));
+ pc.prerendered.clear();
+ } else {
+ drawArea.unite(pc.prerendered->area);
+ SkNWayCanvas* nwayCanvas = new SkNWayCanvas(drawArea.width(), drawArea.height());
+ nwayCanvas->translate(-drawArea.x(), -drawArea.y());
+ nwayCanvas->addCanvas(canvas);
+ nwayCanvas->addCanvas(prerender);
+ SkSafeUnref(canvas);
+ SkSafeUnref(prerender);
+ canvas = nwayCanvas;
+ }
+ }
+ WebCore::PlatformGraphicsContextSkia pgc(canvas);
+ WebCore::GraphicsContext gc(&pgc);
+ ALOGV("painting picture: " INT_RECT_FORMAT, INT_RECT_ARGS(drawArea));
+ painter->paintContents(&gc, drawArea);
+
+ // TODO: consider paint-time checking for these with SkPicture painting?
+ pc.hasText = true;
+
+ SkSafeUnref(canvas);
+ picture->endRecording();
+ return picture;
+}
+#endif
+
} // namespace WebCore
diff --git a/Source/WebKit/android/jni/PicturePile.h b/Source/WebKit/android/jni/PicturePile.h
index b28a792..1f99054 100644
--- a/Source/WebKit/android/jni/PicturePile.h
+++ b/Source/WebKit/android/jni/PicturePile.h
@@ -38,7 +38,17 @@
#include <wtf/ThreadSafeRefCounted.h>
#include <wtf/Vector.h>
+#define USE_RECORDING_CONTEXT true
+#if USE_RECORDING_CONTEXT
+namespace WebCore {
+class Recording;
+}
+typedef WebCore::Recording Picture;
+#else
class SkPicture;
+typedef SkPicture Picture;
+#endif
+
class SkCanvas;
namespace WebCore {
@@ -57,37 +67,27 @@ public:
class PictureContainer {
public:
- SkPicture* picture;
+ Picture* picture;
IntRect area;
bool dirty;
RefPtr<PrerenderedInval> prerendered;
+ bool hasText;
PictureContainer(const IntRect& area)
: picture(0)
, area(area)
, dirty(true)
+ , hasText(false)
{}
- PictureContainer(const PictureContainer& other)
- : picture(other.picture)
- , area(other.area)
- , dirty(other.dirty)
- , prerendered(other.prerendered)
- {
- SkSafeRef(picture);
- }
-
- ~PictureContainer()
- {
- SkSafeUnref(picture);
- }
+ PictureContainer(const PictureContainer& other);
+ ~PictureContainer();
};
class PicturePile {
public:
PicturePile() {}
PicturePile(const PicturePile& other);
- PicturePile(SkPicture* picture);
const IntSize& size() { return m_size; }
@@ -104,11 +104,17 @@ public:
SkRegion& dirtyRegion() { return m_dirtyRegion; }
PrerenderedInval* prerenderedInvalForArea(const IntRect& area);
+ // UI-side methods used to check content, after construction/updates are complete
+ bool hasText() const;
+ bool isEmpty() const;
+
private:
void applyWebkitInvals();
void updatePicture(PicturePainter* painter, PictureContainer& container);
+ Picture* recordPicture(PicturePainter* painter, PictureContainer& container);
void appendToPile(const IntRect& inval, const IntRect& originalInval = IntRect());
- void drawWithClipRecursive(SkCanvas* canvas, SkRegion& clipRegion, int index);
+ void drawWithClipRecursive(SkCanvas* canvas, int index);
+ void drawPicture(SkCanvas* canvas, PictureContainer& pc);
IntSize m_size;
Vector<PictureContainer> m_pile;
diff --git a/Source/WebKit/android/jni/ViewStateSerializer.cpp b/Source/WebKit/android/jni/ViewStateSerializer.cpp
index 02ddca6..8963837 100644
--- a/Source/WebKit/android/jni/ViewStateSerializer.cpp
+++ b/Source/WebKit/android/jni/ViewStateSerializer.cpp
@@ -30,6 +30,7 @@
#include "BaseLayerAndroid.h"
#include "CreateJavaOutputStreamAdaptor.h"
+#include "DumpLayer.h"
#include "FixedPositioning.h"
#include "ImagesManager.h"
#include "IFrameContentLayerAndroid.h"
@@ -56,6 +57,68 @@ enum LayerTypes {
LTFixedLayerAndroid = 3
};
+#define ID "mID"
+#define LEFT "layout:mLeft"
+#define TOP "layout:mTop"
+#define WIDTH "layout:getWidth()"
+#define HEIGHT "layout:getHeight()"
+
+class HierarchyLayerDumper : public LayerDumper {
+public:
+ HierarchyLayerDumper(SkWStream* stream, int level)
+ : LayerDumper(level)
+ , m_stream(stream)
+ {}
+
+ virtual void beginLayer(const char* className, const LayerAndroid* layerPtr) {
+ LayerDumper::beginLayer(className, layerPtr);
+ for (int i = 0; i < m_indentLevel; i++) {
+ m_stream->writeText(" ");
+ }
+ m_stream->writeText(className);
+ m_stream->writeText("@");
+ m_stream->writeHexAsText(layerPtr->uniqueId());
+ m_stream->writeText(" ");
+
+ writeHexVal(ID, (int) layerPtr);
+ writeIntVal(LEFT, layerPtr->getPosition().fX);
+ writeIntVal(TOP, layerPtr->getPosition().fY);
+ writeIntVal(WIDTH, layerPtr->getWidth());
+ writeIntVal(HEIGHT, layerPtr->getHeight());
+ }
+
+ virtual void beginChildren(int childCount) {
+ m_stream->writeText("\n");
+ LayerDumper::beginChildren(childCount);
+ }
+
+protected:
+ virtual void writeEntry(const char* label, const char* value) {
+ m_stream->writeText(label);
+ m_stream->writeText("=");
+ int len = strlen(value);
+ m_stream->writeDecAsText(len);
+ m_stream->writeText(",");
+ m_stream->writeText(value);
+ m_stream->writeText(" ");
+ }
+
+private:
+ SkWStream* m_stream;
+};
+
+static void nativeDumpLayerHierarchy(JNIEnv* env, jobject, jint jbaseLayer, jint level,
+ jobject jstream, jbyteArray jstorage)
+{
+ SkWStream *stream = CreateJavaOutputStreamAdaptor(env, jstream, jstorage);
+ BaseLayerAndroid* baseLayer = reinterpret_cast<BaseLayerAndroid*>(jbaseLayer);
+ SkSafeRef(baseLayer);
+ HierarchyLayerDumper dumper(stream, level);
+ baseLayer->dumpLayers(&dumper);
+ SkSafeUnref(baseLayer);
+ delete stream;
+}
+
static bool nativeSerializeViewState(JNIEnv* env, jobject, jint jbaseLayer,
jobject jstream, jbyteArray jstorage)
{
@@ -478,6 +541,8 @@ LayerAndroid* deserializeLayer(int version, SkStream* stream)
* JNI registration
*/
static JNINativeMethod gSerializerMethods[] = {
+ { "nativeDumpLayerHierarchy", "(IILjava/io/OutputStream;[B)V",
+ (void*) nativeDumpLayerHierarchy },
{ "nativeSerializeViewState", "(ILjava/io/OutputStream;[B)Z",
(void*) nativeSerializeViewState },
{ "nativeDeserializeViewState", "(ILjava/io/InputStream;[B)I",
diff --git a/Source/WebKit/android/jni/WebCoreFrameBridge.cpp b/Source/WebKit/android/jni/WebCoreFrameBridge.cpp
index 4ce3d8e..61ffd29 100644
--- a/Source/WebKit/android/jni/WebCoreFrameBridge.cpp
+++ b/Source/WebKit/android/jni/WebCoreFrameBridge.cpp
@@ -50,6 +50,7 @@
#include "FrameLoadRequest.h"
#include "FrameTree.h"
#include "FrameView.h"
+#include "GeolocationClientAndroid.h"
#include "GraphicsContext.h"
#include "HistoryItem.h"
#include "HTMLCollection.h"
@@ -88,7 +89,6 @@
#include "WebFrameView.h"
#include "WebUrlLoaderClient.h"
#include "WebViewCore.h"
-#include "android_graphics.h"
#include "jni.h"
#include "wds/DebugServer.h"
@@ -273,7 +273,7 @@ WebFrame::WebFrame(JNIEnv* env, jobject obj, jobject historyList, WebCore::Page*
mJavaFrame->mReportSslCertError = env->GetMethodID(clazz, "reportSslCertError", "(II[BLjava/lang/String;)V");
mJavaFrame->mRequestClientCert = env->GetMethodID(clazz, "requestClientCert", "(ILjava/lang/String;)V");
mJavaFrame->mDownloadStart = env->GetMethodID(clazz, "downloadStart",
- "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;J)V");
+ "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;J)V");
mJavaFrame->mDidReceiveData = env->GetMethodID(clazz, "didReceiveData", "([BI)V");
mJavaFrame->mDidFinishLoading = env->GetMethodID(clazz, "didFinishLoading", "()V");
mJavaFrame->mSetCertificate = env->GetMethodID(clazz, "setCertificate", "([B)V");
@@ -497,15 +497,9 @@ WebFrame::loadStarted(WebCore::Frame* frame)
if (favicon)
env->DeleteLocalRef(favicon);
- // Inform the client that the main frame has started a new load.
- if (isMainFrame && mPage) {
- Chrome* chrome = mPage->chrome();
- if (chrome) {
- ChromeClientAndroid* client = static_cast<ChromeClientAndroid*>(chrome->client());
- if (client)
- client->onMainFrameLoadStarted();
- }
- }
+ // The main frame has started a new load.
+ if (isMainFrame && mPage)
+ WebViewCore::getWebViewCore(mPage->mainFrame()->view())->geolocationManager()->resetRealClientTemporaryPermissionStates();
}
void
@@ -842,7 +836,7 @@ WebFrame::requestClientCert(WebUrlLoaderClient* client, const std::string& hostA
}
void
-WebFrame::downloadStart(const std::string& url, const std::string& userAgent, const std::string& contentDisposition, const std::string& mimetype, long long contentLength)
+WebFrame::downloadStart(const std::string& url, const std::string& userAgent, const std::string& contentDisposition, const std::string& mimetype, const std::string& referer, long long contentLength)
{
JNIEnv* env = getJNIEnv();
AutoJObject javaFrame = mJavaFrame->frame(env);
@@ -852,13 +846,15 @@ WebFrame::downloadStart(const std::string& url, const std::string& userAgent, co
jstring jUserAgent = stdStringToJstring(env, userAgent, true);
jstring jContentDisposition = stdStringToJstring(env, contentDisposition, true);
jstring jMimetype = stdStringToJstring(env, mimetype, true);
+ jstring jReferer = stdStringToJstring(env, referer, true);
- env->CallVoidMethod(javaFrame.get(), mJavaFrame->mDownloadStart, jUrl, jUserAgent, jContentDisposition, jMimetype, contentLength);
+ env->CallVoidMethod(javaFrame.get(), mJavaFrame->mDownloadStart, jUrl, jUserAgent, jContentDisposition, jMimetype, jReferer, contentLength);
env->DeleteLocalRef(jUrl);
env->DeleteLocalRef(jUserAgent);
env->DeleteLocalRef(jContentDisposition);
env->DeleteLocalRef(jMimetype);
+ env->DeleteLocalRef(jReferer);
checkException(env);
}
@@ -1099,6 +1095,7 @@ static void CreateFrame(JNIEnv* env, jobject obj, jobject javaview, jobject jAss
EditorClientAndroid* editorC = new EditorClientAndroid;
DeviceMotionClientAndroid* deviceMotionC = new DeviceMotionClientAndroid;
DeviceOrientationClientAndroid* deviceOrientationC = new DeviceOrientationClientAndroid;
+ GeolocationClientAndroid* geolocationC = new GeolocationClientAndroid;
WebCore::Page::PageClients pageClients;
pageClients.chromeClient = chromeC;
@@ -1108,6 +1105,7 @@ static void CreateFrame(JNIEnv* env, jobject obj, jobject javaview, jobject jAss
pageClients.inspectorClient = new InspectorClientAndroid;
pageClients.deviceMotionClient = deviceMotionC;
pageClients.deviceOrientationClient = deviceOrientationC;
+ pageClients.geolocationClient = geolocationC;
WebCore::Page* page = new WebCore::Page(pageClients);
editorC->setPage(page);
@@ -1150,6 +1148,7 @@ static void CreateFrame(JNIEnv* env, jobject obj, jobject javaview, jobject jAss
frame->page()->focusController()->setFocused(true);
deviceMotionC->setWebViewCore(webViewCore);
deviceOrientationC->setWebViewCore(webViewCore);
+ geolocationC->setWebViewCore(webViewCore);
// Allow local access to file:/// and substitute data
WebCore::SecurityOrigin::setLocalLoadPolicy(
diff --git a/Source/WebKit/android/jni/WebCoreFrameBridge.h b/Source/WebKit/android/jni/WebCoreFrameBridge.h
index 30c1d83..56b095b 100644
--- a/Source/WebKit/android/jni/WebCoreFrameBridge.h
+++ b/Source/WebKit/android/jni/WebCoreFrameBridge.h
@@ -116,7 +116,7 @@ class WebFrame : public WebCoreRefObject {
void didReceiveAuthenticationChallenge(WebUrlLoaderClient*, const std::string& host, const std::string& realm, bool useCachedCredentials, bool suppressDialog);
void reportSslCertError(WebUrlLoaderClient* client, int cert_error, const std::string& cert, const std::string& url);
void requestClientCert(WebUrlLoaderClient* client, const std::string& hostAndPort);
- void downloadStart(const std::string& url, const std::string& userAgent, const std::string& contentDisposition, const std::string& mimetype, long long contentLength);
+ void downloadStart(const std::string& url, const std::string& userAgent, const std::string& contentDisposition, const std::string& mimetype, const std::string& referer, long long contentLength);
void didReceiveData(const char* data, int size);
void didFinishLoading();
void setCertificate(const std::string& cert);
diff --git a/Source/WebKit/android/jni/WebFrameView.cpp b/Source/WebKit/android/jni/WebFrameView.cpp
index 10e31dc..ed332aa 100644
--- a/Source/WebKit/android/jni/WebFrameView.cpp
+++ b/Source/WebKit/android/jni/WebFrameView.cpp
@@ -28,7 +28,6 @@
#include <config.h>
#include "WebFrameView.h"
-#include "android_graphics.h"
#include "GraphicsContext.h"
#include "Frame.h"
#include "FrameTree.h"
diff --git a/Source/WebKit/android/jni/WebHistory.cpp b/Source/WebKit/android/jni/WebHistory.cpp
index 6b71d0f..c06244b 100644
--- a/Source/WebKit/android/jni/WebHistory.cpp
+++ b/Source/WebKit/android/jni/WebHistory.cpp
@@ -60,19 +60,19 @@ static void writeItem(WTF::Vector<char>& vector, WebCore::HistoryItem* item);
static void writeChildrenRecursive(WTF::Vector<char>& vector, WebCore::HistoryItem* parent);
static bool readItemRecursive(WebCore::HistoryItem* child, const char** pData, int length);
-// Field ids for WebHistoryItems
-struct WebHistoryItemFields {
+// Field ids for WebHistoryClassicItems
+struct WebHistoryItemClassicFields {
jmethodID mInit;
-} gWebHistoryItem;
+} gWebHistoryItemClassic;
-struct WebBackForwardListFields {
+struct WebBackForwardListClassicFields {
jmethodID mAddHistoryItem;
jmethodID mRemoveHistoryItem;
jmethodID mSetCurrentIndex;
-} gWebBackForwardList;
+} gWebBackForwardListClassic;
//--------------------------------------------------------------------------
-// WebBackForwardList native methods.
+// WebBackForwardListClassic native methods.
//--------------------------------------------------------------------------
static void WebHistoryClose(JNIEnv* env, jobject obj, jint frame)
@@ -398,9 +398,9 @@ void WebHistory::AddItem(const AutoJObject& list, WebCore::HistoryItem* item)
WebHistoryItem* bridge = new WebHistoryItem(item);
bridge->setActive();
item->setBridge(bridge);
- // Allocate a blank WebHistoryItem
- jclass clazz = env->FindClass("android/webkit/WebHistoryItem");
- jobject newItem = env->NewObject(clazz, gWebHistoryItem.mInit,
+ // Allocate a blank WebHistoryItemClassic
+ jclass clazz = env->FindClass("android/webkit/WebHistoryItemClassic");
+ jobject newItem = env->NewObject(clazz, gWebHistoryItemClassic.mInit,
reinterpret_cast<int>(bridge));
env->DeleteLocalRef(clazz);
@@ -409,7 +409,7 @@ void WebHistory::AddItem(const AutoJObject& list, WebCore::HistoryItem* item)
bridge->updateHistoryItem(item);
// Add it to the list.
- env->CallVoidMethod(list.get(), gWebBackForwardList.mAddHistoryItem, newItem);
+ env->CallVoidMethod(list.get(), gWebBackForwardListClassic.mAddHistoryItem, newItem);
// Delete our local reference.
env->DeleteLocalRef(newItem);
@@ -418,13 +418,13 @@ void WebHistory::AddItem(const AutoJObject& list, WebCore::HistoryItem* item)
void WebHistory::RemoveItem(const AutoJObject& list, int index)
{
if (list.get())
- list.env()->CallVoidMethod(list.get(), gWebBackForwardList.mRemoveHistoryItem, index);
+ list.env()->CallVoidMethod(list.get(), gWebBackForwardListClassic.mRemoveHistoryItem, index);
}
void WebHistory::UpdateHistoryIndex(const AutoJObject& list, int newIndex)
{
if (list.get())
- list.env()->CallVoidMethod(list.get(), gWebBackForwardList.mSetCurrentIndex, newIndex);
+ list.env()->CallVoidMethod(list.get(), gWebBackForwardListClassic.mSetCurrentIndex, newIndex);
}
static void writeString(WTF::Vector<char>& vector, const WTF::String& str)
@@ -948,14 +948,14 @@ static void unitTest()
//---------------------------------------------------------
// JNI registration
//---------------------------------------------------------
-static JNINativeMethod gWebBackForwardListMethods[] = {
+static JNINativeMethod gWebBackForwardListClassicMethods[] = {
{ "nativeClose", "(I)V",
(void*) WebHistoryClose },
{ "restoreIndex", "(II)V",
(void*) WebHistoryRestoreIndex }
};
-static JNINativeMethod gWebHistoryItemMethods[] = {
+static JNINativeMethod gWebHistoryItemClassicMethods[] = {
{ "inflate", "(I[B)I",
(void*) WebHistoryInflate },
{ "nativeRef", "(I)V",
@@ -981,31 +981,30 @@ int registerWebHistory(JNIEnv* env)
#ifdef UNIT_TEST
unitTest();
#endif
- // Find WebHistoryItem, its constructor, and the update method.
- jclass clazz = env->FindClass("android/webkit/WebHistoryItem");
- ALOG_ASSERT(clazz, "Unable to find class android/webkit/WebHistoryItem");
- gWebHistoryItem.mInit = env->GetMethodID(clazz, "<init>", "(I)V");
- ALOG_ASSERT(gWebHistoryItem.mInit, "Could not find WebHistoryItem constructor");
-
+ // Find WebHistoryItemClassic, its constructor, and the update method.
+ jclass clazz = env->FindClass("android/webkit/WebHistoryItemClassic");
+ ALOG_ASSERT(clazz, "Unable to find class android/webkit/WebHistoryItemClassic");
+ gWebHistoryItemClassic.mInit = env->GetMethodID(clazz, "<init>", "(I)V");
+ ALOG_ASSERT(gWebHistoryItemClassic.mInit, "Could not find WebHistoryItemClassic constructor");
env->DeleteLocalRef(clazz);
- // Find the WebBackForwardList object and method.
- clazz = env->FindClass("android/webkit/WebBackForwardList");
- ALOG_ASSERT(clazz, "Unable to find class android/webkit/WebBackForwardList");
- gWebBackForwardList.mAddHistoryItem = env->GetMethodID(clazz, "addHistoryItem",
+ // Find the WebBackForwardListClassic object and method.
+ clazz = env->FindClass("android/webkit/WebBackForwardListClassic");
+ ALOG_ASSERT(clazz, "Unable to find class android/webkit/WebBackForwardListClassic");
+ gWebBackForwardListClassic.mAddHistoryItem = env->GetMethodID(clazz, "addHistoryItem",
"(Landroid/webkit/WebHistoryItem;)V");
- ALOG_ASSERT(gWebBackForwardList.mAddHistoryItem, "Could not find method addHistoryItem");
- gWebBackForwardList.mRemoveHistoryItem = env->GetMethodID(clazz, "removeHistoryItem",
+ ALOG_ASSERT(gWebBackForwardListClassic.mAddHistoryItem, "Could not find method addHistoryItem");
+ gWebBackForwardListClassic.mRemoveHistoryItem = env->GetMethodID(clazz, "removeHistoryItem",
"(I)V");
- ALOG_ASSERT(gWebBackForwardList.mRemoveHistoryItem, "Could not find method removeHistoryItem");
- gWebBackForwardList.mSetCurrentIndex = env->GetMethodID(clazz, "setCurrentIndex", "(I)V");
- ALOG_ASSERT(gWebBackForwardList.mSetCurrentIndex, "Could not find method setCurrentIndex");
+ ALOG_ASSERT(gWebBackForwardListClassic.mRemoveHistoryItem, "Could not find method removeHistoryItem");
+ gWebBackForwardListClassic.mSetCurrentIndex = env->GetMethodID(clazz, "setCurrentIndex", "(I)V");
+ ALOG_ASSERT(gWebBackForwardListClassic.mSetCurrentIndex, "Could not find method setCurrentIndex");
env->DeleteLocalRef(clazz);
- int result = jniRegisterNativeMethods(env, "android/webkit/WebBackForwardList",
- gWebBackForwardListMethods, NELEM(gWebBackForwardListMethods));
- return (result < 0) ? result : jniRegisterNativeMethods(env, "android/webkit/WebHistoryItem",
- gWebHistoryItemMethods, NELEM(gWebHistoryItemMethods));
+ int result = jniRegisterNativeMethods(env, "android/webkit/WebBackForwardListClassic",
+ gWebBackForwardListClassicMethods, NELEM(gWebBackForwardListClassicMethods));
+ return (result < 0) ? result : jniRegisterNativeMethods(env, "android/webkit/WebHistoryItemClassic",
+ gWebHistoryItemClassicMethods, NELEM(gWebHistoryItemClassicMethods));
}
} /* namespace android */
diff --git a/Source/WebKit/android/jni/WebSettings.cpp b/Source/WebKit/android/jni/WebSettings.cpp
index 467da3d..1bd3e36 100644
--- a/Source/WebKit/android/jni/WebSettings.cpp
+++ b/Source/WebKit/android/jni/WebSettings.cpp
@@ -151,6 +151,7 @@ struct FieldIds {
#endif
mOverrideCacheMode = env->GetFieldID(clazz, "mOverrideCacheMode", "I");
mPasswordEchoEnabled = env->GetFieldID(clazz, "mPasswordEchoEnabled", "Z");
+ mMediaPlaybackRequiresUserGesture = env->GetFieldID(clazz, "mMediaPlaybackRequiresUserGesture", "Z");
ALOG_ASSERT(mLayoutAlgorithm, "Could not find field mLayoutAlgorithm");
ALOG_ASSERT(mTextSize, "Could not find field mTextSize");
@@ -195,6 +196,7 @@ struct FieldIds {
ALOG_ASSERT(mUseDoubleTree, "Could not find field mUseDoubleTree");
ALOG_ASSERT(mPageCacheCapacity, "Could not find field mPageCacheCapacity");
ALOG_ASSERT(mPasswordEchoEnabled, "Could not find field mPasswordEchoEnabled");
+ ALOG_ASSERT(mMediaPlaybackRequiresUserGesture, "Could not find field mMediaPlaybackRequiresUserGesture");
jclass enumClass = env->FindClass("java/lang/Enum");
ALOG_ASSERT(enumClass, "Could not find Enum class!");
@@ -281,6 +283,7 @@ struct FieldIds {
#endif
jfieldID mOverrideCacheMode;
jfieldID mPasswordEchoEnabled;
+ jfieldID mMediaPlaybackRequiresUserGesture;
};
static struct FieldIds* gFieldIds;
@@ -616,6 +619,9 @@ public:
bool echoPassword = env->GetBooleanField(obj,
gFieldIds->mPasswordEchoEnabled);
s->setPasswordEchoEnabled(echoPassword);
+
+ flag = env->GetBooleanField(obj, gFieldIds->mMediaPlaybackRequiresUserGesture);
+ s->setMediaPlaybackRequiresUserGesture(flag);
}
};
diff --git a/Source/WebKit/android/jni/WebStorage.cpp b/Source/WebKit/android/jni/WebStorage.cpp
index 66a3517..0cfe414 100644
--- a/Source/WebKit/android/jni/WebStorage.cpp
+++ b/Source/WebKit/android/jni/WebStorage.cpp
@@ -130,14 +130,10 @@ static void DeleteOrigin(JNIEnv* env, jobject obj, jstring origin)
static void DeleteAllData(JNIEnv* env, jobject obj)
{
+ // delete WebSQL database
WebCore::DatabaseTracker::tracker().deleteAllDatabases();
-
- Vector<WebCore::KURL> manifestUrls;
- if (!WebCore::cacheStorage().manifestURLs(&manifestUrls))
- return;
- int size = manifestUrls.size();
- for (int i = 0; i < size; ++i)
- WebCore::cacheStorage().deleteCacheGroup(manifestUrls[i]);
+ // delete AppCache
+ WebCore::cacheStorage().deleteAllEntries();
// FIXME: this is a workaround for eliminating any DOM Storage data (both
// session and local storage) as there is no functionality inside WebKit at the
diff --git a/Source/WebKit/android/jni/WebViewCore.cpp b/Source/WebKit/android/jni/WebViewCore.cpp
index f17e573..aa38222 100644
--- a/Source/WebKit/android/jni/WebViewCore.cpp
+++ b/Source/WebKit/android/jni/WebViewCore.cpp
@@ -30,6 +30,7 @@
#include "AccessibilityObject.h"
#include "AndroidHitTestResult.h"
+#include "ApplicationCacheStorage.h"
#include "Attribute.h"
#include "content/address_detector.h"
#include "Chrome.h"
@@ -62,7 +63,6 @@
#include "Geolocation.h"
#include "GraphicsContext.h"
#include "GraphicsJNI.h"
-#include "GraphicsOperationCollection.h"
#include "HTMLAnchorElement.h"
#include "HTMLAreaElement.h"
#include "HTMLElement.h"
@@ -131,10 +131,10 @@
#include "WebCoreJni.h"
#include "WebFrameView.h"
#include "WindowsKeyboardCodes.h"
-#include "android_graphics.h"
#include "autofill/WebAutofill.h"
#include "htmlediting.h"
#include "markup.h"
+#include "unicode/uloc.h"
#include "visible_units.h"
#include <JNIHelp.h>
@@ -367,8 +367,6 @@ struct WebViewCore::JavaGlue {
jmethodID m_showRect;
jmethodID m_centerFitRect;
jmethodID m_setScrollbarModes;
- jmethodID m_setInstallableWebApp;
- jmethodID m_enterFullscreenForVideoLayer;
jmethodID m_exitFullscreenVideo;
jmethodID m_setWebTextViewAutoFillable;
jmethodID m_selectAt;
@@ -401,7 +399,7 @@ struct WebViewCore::TextFieldInitDataGlue {
jfieldID m_maxLength;
jfieldID m_contentBounds;
jfieldID m_nodeLayerId;
- jfieldID m_contentRect;
+ jfieldID m_clientRect;
};
/*
@@ -423,7 +421,6 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m
, m_mainFrame(mainframe)
, m_popupReply(0)
, m_blockTextfieldUpdates(false)
- , m_focusBoundsChanged(false)
, m_skipContentDraw(false)
, m_textGeneration(0)
, m_maxXScroll(320/4)
@@ -436,7 +433,6 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m
, m_textWrapWidth(320)
, m_scale(1.0f)
, m_groupForVisitedLinks(0)
- , m_isPaused(false)
, m_cacheMode(0)
, m_fullscreenVideoMode(false)
, m_matchCount(0)
@@ -446,6 +442,7 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m
, m_screenOnCounter(0)
, m_currentNodeDomNavigationAxis(0)
, m_deviceMotionAndOrientationManager(this)
+ , m_geolocationManager(this)
#if ENABLE(TOUCH_EVENTS)
, m_forwardingTouchEvents(false)
#endif
@@ -471,7 +468,7 @@ 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_updateTextfield = GetJMethod(env, clazz, "updateTextfield", "(IZLjava/lang/String;I)V");
+ m_javaGlue->m_updateTextfield = GetJMethod(env, clazz, "updateTextfield", "(ILjava/lang/String;I)V");
m_javaGlue->m_updateTextSelection = GetJMethod(env, clazz, "updateTextSelection", "(IIIII)V");
m_javaGlue->m_updateTextSizeAndScroll = GetJMethod(env, clazz, "updateTextSizeAndScroll", "(IIIII)V");
m_javaGlue->m_clearTextEntry = GetJMethod(env, clazz, "clearTextEntry", "()V");
@@ -479,7 +476,7 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m
m_javaGlue->m_needTouchEvents = GetJMethod(env, clazz, "needTouchEvents", "(Z)V");
m_javaGlue->m_requestKeyboard = GetJMethod(env, clazz, "requestKeyboard", "(Z)V");
m_javaGlue->m_exceededDatabaseQuota = GetJMethod(env, clazz, "exceededDatabaseQuota", "(Ljava/lang/String;Ljava/lang/String;JJ)V");
- m_javaGlue->m_reachedMaxAppCacheSize = GetJMethod(env, clazz, "reachedMaxAppCacheSize", "(J)V");
+ m_javaGlue->m_reachedMaxAppCacheSize = GetJMethod(env, clazz, "reachedMaxAppCacheSize", "(JJ)V");
m_javaGlue->m_populateVisitedLinks = GetJMethod(env, clazz, "populateVisitedLinks", "()V");
m_javaGlue->m_geolocationPermissionsShowPrompt = GetJMethod(env, clazz, "geolocationPermissionsShowPrompt", "(Ljava/lang/String;)V");
m_javaGlue->m_geolocationPermissionsHidePrompt = GetJMethod(env, clazz, "geolocationPermissionsHidePrompt", "()V");
@@ -499,9 +496,7 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m
m_javaGlue->m_showRect = GetJMethod(env, clazz, "showRect", "(IIIIIIFFFF)V");
m_javaGlue->m_centerFitRect = GetJMethod(env, clazz, "centerFitRect", "(IIII)V");
m_javaGlue->m_setScrollbarModes = GetJMethod(env, clazz, "setScrollbarModes", "(II)V");
- m_javaGlue->m_setInstallableWebApp = GetJMethod(env, clazz, "setInstallableWebApp", "()V");
#if ENABLE(VIDEO)
- m_javaGlue->m_enterFullscreenForVideoLayer = GetJMethod(env, clazz, "enterFullscreenForVideoLayer", "(ILjava/lang/String;)V");
m_javaGlue->m_exitFullscreenVideo = GetJMethod(env, clazz, "exitFullscreenVideo", "()V");
#endif
m_javaGlue->m_setWebTextViewAutoFillable = GetJMethod(env, clazz, "setWebTextViewAutoFillable", "(ILjava/lang/String;)V");
@@ -526,7 +521,7 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m
m_textFieldInitDataGlue->m_maxLength = env->GetFieldID(tfidClazz, "mMaxLength", "I");
m_textFieldInitDataGlue->m_contentBounds = env->GetFieldID(tfidClazz, "mContentBounds", "Landroid/graphics/Rect;");
m_textFieldInitDataGlue->m_nodeLayerId = env->GetFieldID(tfidClazz, "mNodeLayerId", "I");
- m_textFieldInitDataGlue->m_contentRect = env->GetFieldID(tfidClazz, "mContentRect", "Landroid/graphics/Rect;");
+ m_textFieldInitDataGlue->m_clientRect = env->GetFieldID(tfidClazz, "mClientRect", "Landroid/graphics/Rect;");
m_textFieldInitDataGlue->m_constructor = GetJMethod(env, tfidClazz, "<init>", "()V");
env->DeleteLocalRef(tfidClazz);
@@ -728,13 +723,6 @@ void WebViewCore::clearContent()
updateLocale();
}
-bool WebViewCore::focusBoundsChanged()
-{
- bool result = m_focusBoundsChanged;
- m_focusBoundsChanged = false;
- return result;
-}
-
void WebViewCore::paintContents(WebCore::GraphicsContext* gc, WebCore::IntRect& dirty)
{
WebCore::FrameView* view = m_mainFrame->view();
@@ -1507,6 +1495,7 @@ bool WebViewCore::selectWordAroundPosition(Frame* frame, VisiblePosition pos)
VisibleSelection selection(pos);
selection.expandUsingGranularity(WordGranularity);
SelectionController* selectionController = frame->selection();
+ selection = VisibleSelection(selection.start(), selection.end());
bool wordSelected = false;
if (selectionController->shouldChangeSelection(selection)) {
@@ -1566,7 +1555,8 @@ void WebViewCore::layerToAbsoluteOffset(const LayerAndroid* layer, IntPoint& off
void WebViewCore::setSelectionCaretInfo(SelectText* selectTextContainer,
const WebCore::Position& pos, const IntPoint& frameOffset,
- SelectText::HandleId handleId, int caretRectOffset, EAffinity affinity)
+ SelectText::HandleId handleId, SelectText::HandleType handleType,
+ int caretRectOffset, EAffinity affinity)
{
Node* node = pos.anchorNode();
LayerAndroid* layer = 0;
@@ -1584,8 +1574,9 @@ void WebViewCore::setSelectionCaretInfo(SelectText* selectTextContainer,
caretRect.setX(absoluteOffset.x() - offset.x() + caretRectOffset);
caretRect.setY(absoluteOffset.y() - offset.y());
selectTextContainer->setCaretRect(handleId, caretRect);
+ selectTextContainer->setHandleType(handleId, handleType);
selectTextContainer->setTextRect(handleId,
- positionToTextRect(pos, affinity, offset));
+ positionToTextRect(pos, affinity, offset, caretRect));
}
bool WebViewCore::isLtr(const Position& position)
@@ -1601,14 +1592,28 @@ bool WebViewCore::isLtr(const Position& position)
return isLtr;
}
+static Node* findInputParent(Node* node)
+{
+ Node* testNode = node;
+ while (testNode) {
+ RenderObject* renderer = testNode->renderer();
+ if (renderer
+ && (renderer->isTextArea() || renderer->isTextControl())) {
+ return testNode;
+ }
+ testNode = testNode->parentOrHostNode();
+ }
+ return node;
+}
+
SelectText* WebViewCore::createSelectText(const VisibleSelection& selection)
{
bool isCaret = selection.isCaret();
+ Position base = selection.base();
+ Position extent = selection.extent();
if (selection.isNone() || (!selection.isContentEditable() && isCaret)
- || !selection.start().anchorNode()
- || !selection.start().anchorNode()->renderer()
- || !selection.end().anchorNode()
- || !selection.end().anchorNode()->renderer())
+ || !base.anchorNode() || !base.anchorNode()->renderer()
+ || !extent.anchorNode() || !extent.anchorNode()->renderer())
return 0;
RefPtr<Range> range = selection.firstRange();
@@ -1624,20 +1629,39 @@ SelectText* WebViewCore::createSelectText(const VisibleSelection& selection)
IntPoint frameOffset = convertGlobalContentToFrameContent(IntPoint());
SelectText* selectTextContainer = new SelectText();
if (isCaret) {
- setSelectionCaretInfo(selectTextContainer, selection.start(), frameOffset,
- SelectText::LeftHandle, 0, selection.affinity());
- setSelectionCaretInfo(selectTextContainer, selection.start(), frameOffset,
- SelectText::RightHandle, 0, selection.affinity());
+ setSelectionCaretInfo(selectTextContainer, base, frameOffset,
+ SelectText::BaseHandle, SelectText::CenterHandle, 0,
+ selection.affinity());
+ setSelectionCaretInfo(selectTextContainer, base, frameOffset,
+ SelectText::ExtentHandle, SelectText::CenterHandle, 0,
+ selection.affinity());
} else {
- bool ltr = isLtr(selection.start());
- Position left = ltr ? selection.start() : selection.end();
- Position right = ltr ? selection.end() : selection.start();
- int leftOffset = isLtr(left) ? 0 : -1;
- int rightOffset = isLtr(right) ? 0 : -1;
- setSelectionCaretInfo(selectTextContainer, left, frameOffset,
- SelectText::LeftHandle, leftOffset, selection.affinity());
- setSelectionCaretInfo(selectTextContainer, right, frameOffset,
- SelectText::RightHandle, rightOffset, selection.affinity());
+ bool isBaseLtr = isLtr(base);
+ bool isBaseStart = comparePositions(base, extent) <= 0;
+ int baseOffset = isBaseLtr ? 0 : -1;
+ SelectText::HandleType baseHandleType = (isBaseLtr == isBaseStart)
+ ? SelectText::LeftHandle : SelectText::RightHandle;
+ EAffinity affinity = selection.affinity();
+ setSelectionCaretInfo(selectTextContainer, base, frameOffset,
+ SelectText::BaseHandle, baseHandleType, baseOffset, affinity);
+ bool isExtentLtr = isLtr(extent);
+ int extentOffset = isExtentLtr ? 0 : -1;
+ SelectText::HandleType extentHandleType = (isExtentLtr == isBaseStart)
+ ? SelectText::RightHandle : SelectText::LeftHandle;
+ setSelectionCaretInfo(selectTextContainer, extent, frameOffset,
+ SelectText::ExtentHandle, extentHandleType, extentOffset, affinity);
+ IntRect clipRect;
+ if (selection.isContentEditable()) {
+ Node* editable = findInputParent(base.anchorNode());
+ RenderObject* render = editable->renderer();
+ if (render && render->isBox() && !render->isBody()) {
+ RenderBox* renderBox = toRenderBox(render);
+ clipRect = renderBox->clientBoxRect();
+ FloatPoint pos = renderBox->localToAbsolute(clipRect.location());
+ clipRect.setX(pos.x());
+ clipRect.setY(pos.y());
+ }
+ }
Node* stopNode = range->pastLastNode();
for (Node* node = range->firstNode(); node != stopNode; node = node->traverseNextNode()) {
@@ -1651,7 +1675,8 @@ SelectText* WebViewCore::createSelectText(const VisibleSelection& selection)
int layerId = platformLayerIdFromNode(node, &layer);
Vector<IntRect> rects;
renderText->absoluteRectsForRange(rects, startOffset, endOffset, true);
- selectTextContainer->addHighlightRegion(layer, rects, frameOffset);
+ selectTextContainer->addHighlightRegion(layer, rects, frameOffset,
+ clipRect);
}
}
selectTextContainer->setText(range->text());
@@ -1659,9 +1684,9 @@ SelectText* WebViewCore::createSelectText(const VisibleSelection& selection)
}
IntRect WebViewCore::positionToTextRect(const Position& position,
- EAffinity affinity, const WebCore::IntPoint& offset)
+ EAffinity affinity, const WebCore::IntPoint& offset, const IntRect& caretRect)
{
- IntRect textRect;
+ IntRect textRect = caretRect;
InlineBox* inlineBox;
int offsetIndex;
position.getInlineBoxAndOffset(affinity, inlineBox, offsetIndex);
@@ -1697,25 +1722,25 @@ IntPoint WebViewCore::convertGlobalContentToFrameContent(const IntPoint& point,
return IntPoint(point.x() + frameOffset.x(), point.y() + frameOffset.y());
}
-Position WebViewCore::trimSelectionPosition(const Position &start, const Position& stop)
+VisiblePosition WebViewCore::trimSelectionPosition(const VisiblePosition &start,
+ const VisiblePosition& stop)
{
int direction = comparePositions(start, stop);
if (direction == 0)
return start;
bool forward = direction < 0;
- EAffinity affinity = forward ? DOWNSTREAM : UPSTREAM;
bool move;
- Position pos = start;
+ VisiblePosition pos = start;
bool movedTooFar = false;
do {
move = true;
- Node* node = pos.anchorNode();
+ Node* node = pos.deepEquivalent().anchorNode();
if (node && node->isTextNode() && node->renderer()) {
RenderText *textRenderer = toRenderText(node->renderer());
move = !textRenderer->textLength();
}
if (move) {
- Position nextPos = forward ? pos.next() : pos.previous();
+ VisiblePosition nextPos = forward ? pos.next() : pos.previous();
movedTooFar = nextPos.isNull() || pos == nextPos
|| ((comparePositions(nextPos, stop) < 0) != forward);
pos = nextPos;
@@ -1726,47 +1751,65 @@ Position WebViewCore::trimSelectionPosition(const Position &start, const Positio
return pos;
}
-void WebViewCore::selectText(int startX, int startY, int endX, int endY)
+void WebViewCore::selectText(SelectText::HandleId handleId, int x, int y)
{
SelectionController* sc = focusedFrame()->selection();
- IntPoint startPoint = convertGlobalContentToFrameContent(IntPoint(startX, startY));
- VisiblePosition startPosition(visiblePositionForContentPoint(startPoint));
- IntPoint endPoint = convertGlobalContentToFrameContent(IntPoint(endX, endY));
- VisiblePosition endPosition(visiblePositionForContentPoint(endPoint));
+ VisibleSelection selection = sc->selection();
+ Position base = selection.base();
+ Position extent = selection.extent();
+ IntPoint dragPoint = convertGlobalContentToFrameContent(IntPoint(x, y));
+ VisiblePosition dragPosition(visiblePositionForContentPoint(dragPoint));
- if (startPosition.isNull() || endPosition.isNull())
+ if (base.isNull() || extent.isNull() || dragPosition.isNull())
return;
+ bool draggingBase = (handleId == SelectText::BaseHandle);
+ if (draggingBase)
+ base = dragPosition.deepEquivalent();
+ else
+ extent = dragPosition.deepEquivalent();
- // Ensure startPosition is before endPosition
- if (comparePositions(startPosition, endPosition) > 0)
- swap(startPosition, endPosition);
+ bool baseIsStart = (comparePositions(base, extent) <= 0);
+ Position& start = baseIsStart ? base : extent;
+ Position& end = baseIsStart ? extent : base;
+ VisiblePosition startPosition(start, selection.affinity());
+ VisiblePosition endPosition(end, selection.affinity());
+ bool draggingStart = (baseIsStart == draggingBase);
- if (sc->isContentEditable()) {
- startPosition = sc->selection().visibleStart().honorEditableBoundaryAtOrAfter(startPosition);
- endPosition = sc->selection().visibleEnd().honorEditableBoundaryAtOrBefore(endPosition);
- if (startPosition.isNull() || endPosition.isNull()) {
+ if (draggingStart) {
+ if (selection.isRange()) {
+ startPosition = trimSelectionPosition(startPosition, endPosition);
+ if ((startPosition != endPosition) && isEndOfBlock(startPosition)) {
+ // Ensure startPosition is not at end of block
+ VisiblePosition nextStartPosition(startPosition.next());
+ if (nextStartPosition.isNotNull())
+ startPosition = nextStartPosition;
+ }
+ }
+ startPosition = endPosition.honorEditableBoundaryAtOrAfter(startPosition);
+ if (startPosition.isNull())
return;
+ start = startPosition.deepEquivalent();
+ if (selection.isCaret())
+ end = start;
+ } else {
+ if (selection.isRange()) {
+ endPosition = trimSelectionPosition(endPosition, startPosition);
+ if ((start != end) && isStartOfBlock(endPosition)) {
+ // Ensure endPosition is not at start of block
+ VisiblePosition prevEndPosition(endPosition.previous());
+ if (!prevEndPosition.isNull())
+ endPosition = prevEndPosition;
+ }
}
+ endPosition = startPosition.honorEditableBoundaryAtOrAfter(endPosition);
+ if (endPosition.isNull())
+ return;
+ end = endPosition.deepEquivalent();
+ if (selection.isCaret())
+ start = end;
}
- // Ensure startPosition is not at end of block
- if (startPosition != endPosition && isEndOfBlock(startPosition)) {
- VisiblePosition nextStartPosition(startPosition.next());
- if (!nextStartPosition.isNull())
- startPosition = nextStartPosition;
- }
- // Ensure endPosition is not at start of block
- if (startPosition != endPosition && isStartOfBlock(endPosition)) {
- VisiblePosition prevEndPosition(endPosition.previous());
- if (!prevEndPosition.isNull())
- endPosition = prevEndPosition;
- }
-
- Position start = startPosition.deepEquivalent();
- Position end = endPosition.deepEquivalent();
- start = trimSelectionPosition(start, end);
- end = trimSelectionPosition(end, start);
- VisibleSelection selection(start, end);
+ selection = VisibleSelection(base, extent);
// Only allow changes between caret positions or to text selection.
bool selectChangeAllowed = (!selection.isCaret() || sc->isCaret());
if (selectChangeAllowed && sc->shouldChangeSelection(selection))
@@ -2944,33 +2987,31 @@ void WebViewCore::passToJs(int generation, const WTF::String& current,
WTF::String test = getInputText(focus);
if (test != current) {
// If the text changed during the key event, update the UI text field.
- updateTextfield(focus, false, test);
+ updateTextfield(focus, test);
}
// Now that the selection has settled down, send it.
updateTextSelection();
}
-WebCore::IntRect WebViewCore::scrollFocusedTextInput(float xPercent, int y)
+void WebViewCore::scrollFocusedTextInput(float xPercent, int y)
{
WebCore::Node* focus = currentFocus();
if (!focus) {
clearTextEntry();
- return WebCore::IntRect();
+ return;
}
WebCore::RenderTextControl* renderText = toRenderTextControl(focus);
if (!renderText) {
clearTextEntry();
- return WebCore::IntRect();
+ return;
}
- int x = (int) (xPercent * (renderText->scrollWidth() -
- renderText->clientWidth()));
+ int x = (int)round(xPercent * (renderText->scrollWidth() -
+ renderText->contentWidth()));
renderText->setScrollLeft(x);
renderText->setScrollTop(y);
focus->document()->frame()->selection()->recomputeCaretRect();
- LayerAndroid* layer = 0;
- platformLayerIdFromNode(focus, &layer);
- return absoluteContentRect(focus, layer);
+ updateTextSelection();
}
void WebViewCore::setFocusControllerActive(bool active)
@@ -3364,10 +3405,10 @@ bool WebViewCore::isAutoCompleteEnabled(Node* node)
return isEnabled;
}
-WebCore::IntRect WebViewCore::absoluteContentRect(WebCore::Node* node,
+WebCore::IntRect WebViewCore::absoluteClientRect(WebCore::Node* node,
LayerAndroid* layer)
{
- IntRect contentRect;
+ IntRect clientRect;
if (node) {
RenderObject* render = node->renderer();
if (render && render->isBox() && !render->isBody()) {
@@ -3376,11 +3417,15 @@ WebCore::IntRect WebViewCore::absoluteContentRect(WebCore::Node* node,
WebViewCore::layerToAbsoluteOffset(layer, offset);
RenderBox* renderBox = toRenderBox(render);
- contentRect = renderBox->absoluteContentBox();
- contentRect.move(-offset.x(), -offset.y());
+ clientRect = renderBox->clientBoxRect();
+ IntRect contentBox = renderBox->contentBoxRect();
+ clientRect.setX(contentBox.x());
+ clientRect.setWidth(contentBox.width());
+ FloatPoint absPos = renderBox->localToAbsolute(FloatPoint());
+ clientRect.move(absPos.x() - offset.x(), absPos.y() - offset.y());
}
}
- return contentRect;
+ return clientRect;
}
jobject WebViewCore::createTextFieldInitData(Node* node)
@@ -3417,7 +3462,7 @@ jobject WebViewCore::createTextFieldInitData(Node* node)
env->SetIntField(initData, classDef->m_maxLength, getMaxLength(node));
LayerAndroid* layer = 0;
int layerId = platformLayerIdFromNode(node, &layer);
- IntRect bounds = absoluteContentRect(node, layer);
+ IntRect bounds = absoluteClientRect(node, layer);
ScopedLocalRef<jobject> jbounds(env, intRectToRect(env, bounds));
env->SetObjectField(initData, classDef->m_contentBounds, jbounds.get());
env->SetIntField(initData, classDef->m_nodeLayerId, layerId);
@@ -3429,7 +3474,7 @@ jobject WebViewCore::createTextFieldInitData(Node* node)
contentRect.move(-rtc->scrollLeft(), -rtc->scrollTop());
}
ScopedLocalRef<jobject> jcontentRect(env, intRectToRect(env, contentRect));
- env->SetObjectField(initData, classDef->m_contentRect, jcontentRect.get());
+ env->SetObjectField(initData, classDef->m_clientRect, jcontentRect.get());
return initData;
}
@@ -3611,6 +3656,19 @@ bool WebViewCore::exceededDatabaseQuota(const WTF::String& url, const WTF::Strin
#endif
}
+/*
+ * TODO Note that this logic still needs to be cleaned up. Normally the
+ * information provided in this callback is used to resize the appcache.
+ * so we need to provide the current database size. However, webkit provides no
+ * way to reach this information. It can be calculated by fetching all the
+ * origins and their usage, however this is too expensize (requires one inner
+ * join operation for each origin). Rather, we simply return the maximum cache size,
+ * which should be equivalent to the current cache size. This is generally safe.
+ * However, setting the maximum database size to less than the current database size
+ * may cause a problem. In this case, ApplicationCacheStorage ("the owner of database")
+ * uses the updated value, while database internally ignores it and uses the current size
+ * as quota. This means the value we returned here won't reflect the actual database size.
+ */
bool WebViewCore::reachedMaxAppCacheSize(const unsigned long long spaceNeeded)
{
#if ENABLE(OFFLINE_WEB_APPLICATIONS)
@@ -3618,7 +3676,7 @@ bool WebViewCore::reachedMaxAppCacheSize(const unsigned long long spaceNeeded)
AutoJObject javaObject = m_javaGlue->object(env);
if (!javaObject.get())
return false;
- env->CallVoidMethod(javaObject.get(), m_javaGlue->m_reachedMaxAppCacheSize, spaceNeeded);
+ env->CallVoidMethod(javaObject.get(), m_javaGlue->m_reachedMaxAppCacheSize, spaceNeeded, WebCore::cacheStorage().maximumSize());
checkException(env);
return true;
#endif
@@ -3848,8 +3906,7 @@ void WebViewCore::updateTextSizeAndScroll(WebCore::Node* node)
checkException(env);
}
-void WebViewCore::updateTextfield(WebCore::Node* ptr, bool changeToPassword,
- const WTF::String& text)
+void WebViewCore::updateTextfield(WebCore::Node* ptr, const WTF::String& text)
{
JNIEnv* env = JSC::Bindings::getJNIEnv();
AutoJObject javaObject = m_javaGlue->object(env);
@@ -3857,15 +3914,9 @@ void WebViewCore::updateTextfield(WebCore::Node* ptr, bool changeToPassword,
return;
if (m_blockTextfieldUpdates)
return;
- if (changeToPassword) {
- env->CallVoidMethod(javaObject.get(), m_javaGlue->m_updateTextfield,
- (int) ptr, true, 0, m_textGeneration);
- checkException(env);
- return;
- }
jstring string = wtfStringToJstring(env, text);
env->CallVoidMethod(javaObject.get(), m_javaGlue->m_updateTextfield,
- (int) ptr, false, string, m_textGeneration);
+ (int) ptr, string, m_textGeneration);
env->DeleteLocalRef(string);
checkException(env);
}
@@ -4059,27 +4110,11 @@ void WebViewCore::setScrollbarModes(ScrollbarMode horizontalMode, ScrollbarMode
checkException(env);
}
-void WebViewCore::notifyWebAppCanBeInstalled()
-{
- JNIEnv* env = JSC::Bindings::getJNIEnv();
- AutoJObject javaObject = m_javaGlue->object(env);
- if (!javaObject.get())
- return;
- env->CallVoidMethod(javaObject.get(), m_javaGlue->m_setInstallableWebApp);
- checkException(env);
-}
-
#if ENABLE(VIDEO)
-void WebViewCore::enterFullscreenForVideoLayer(int layerId, const WTF::String& url)
+void WebViewCore::enterFullscreenForVideoLayer()
{
- JNIEnv* env = JSC::Bindings::getJNIEnv();
- AutoJObject javaObject = m_javaGlue->object(env);
- if (!javaObject.get())
- return;
- jstring jUrlStr = wtfStringToJstring(env, url);
- env->CallVoidMethod(javaObject.get(), m_javaGlue->m_enterFullscreenForVideoLayer, layerId, jUrlStr);
+ // Just need to update the video mode, to avoid multiple exit full screen.
m_fullscreenVideoMode = true;
- checkException(env);
}
void WebViewCore::exitFullscreenVideo()
@@ -4373,6 +4408,44 @@ void WebViewCore::getLocale(String& language, String& region)
region = String(propRegn, 2);
}
+// generate bcp47 identifier for the supplied language/region
+static void toLanguageTag(char* output, size_t outSize, const String& language,
+ const String& region) {
+ if (output == NULL || outSize <= 0)
+ return;
+ String locale = language;
+ locale.append('_');
+ locale.append(region);
+ char canonicalChars[ULOC_FULLNAME_CAPACITY];
+ UErrorCode uErr = U_ZERO_ERROR;
+ uloc_canonicalize(locale.ascii().data(), canonicalChars,
+ ULOC_FULLNAME_CAPACITY, &uErr);
+ if (U_SUCCESS(uErr)) {
+ char likelyChars[ULOC_FULLNAME_CAPACITY];
+ uErr = U_ZERO_ERROR;
+ uloc_addLikelySubtags(canonicalChars, likelyChars,
+ ULOC_FULLNAME_CAPACITY, &uErr);
+ if (U_SUCCESS(uErr)) {
+ uErr = U_ZERO_ERROR;
+ uloc_toLanguageTag(likelyChars, output, outSize, FALSE, &uErr);
+ if (U_SUCCESS(uErr)) {
+ return;
+ } else {
+ ALOGD("uloc_toLanguageTag(\"%s\") failed: %s", likelyChars,
+ u_errorName(uErr));
+ }
+ } else {
+ ALOGD("uloc_addLikelySubtags(\"%s\") failed: %s", canonicalChars,
+ u_errorName(uErr));
+ }
+ } else {
+ ALOGD("uloc_canonicalize(\"%s\") failed: %s", locale.ascii().data(),
+ u_errorName(uErr));
+ }
+ // unable to build a proper language identifier
+ output[0] = '\0';
+}
+
void WebViewCore::updateLocale()
{
static String prevLang;
@@ -4387,6 +4460,9 @@ void WebViewCore::updateLocale()
prevRegn = region;
GlyphPageTreeNode::resetRoots();
fontCache()->invalidate();
+ char langTag[ULOC_FULLNAME_CAPACITY];
+ toLanguageTag(langTag, ULOC_FULLNAME_CAPACITY, language, region);
+ FontPlatformData::setDefaultLanguage(langTag);
}
}
@@ -4505,12 +4581,10 @@ static void PassToJs(JNIEnv* env, jobject obj, jint nativeClass,
}
static void ScrollFocusedTextInput(JNIEnv* env, jobject obj, jint nativeClass,
- jfloat xPercent, jint y, jobject contentBounds)
+ jfloat xPercent, jint y)
{
WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
- IntRect bounds = viewImpl->scrollFocusedTextInput(xPercent, y);
- if (contentBounds)
- GraphicsJNI::irect_to_jrect(bounds, env, contentBounds);
+ viewImpl->scrollFocusedTextInput(xPercent, y);
}
static void SetFocusControllerActive(JNIEnv* env, jobject obj, jint nativeClass,
@@ -4765,10 +4839,7 @@ static void GeolocationPermissionsProvide(JNIEnv* env, jobject obj,
jint nativeClass, jstring origin, jboolean allow, jboolean remember)
{
WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
- Frame* frame = viewImpl->mainFrame();
-
- ChromeClientAndroid* chromeClient = static_cast<ChromeClientAndroid*>(frame->page()->chrome()->client());
- chromeClient->provideGeolocationPermissions(jstringToWtfString(env, origin), allow, remember);
+ viewImpl->geolocationManager()->provideRealClientPermissionState(jstringToWtfString(env, origin), allow, remember);
}
static void RegisterURLSchemeAsLocal(JNIEnv* env, jobject obj, jint nativeClass,
@@ -4777,20 +4848,6 @@ static void RegisterURLSchemeAsLocal(JNIEnv* env, jobject obj, jint nativeClass,
WebCore::SchemeRegistry::registerURLSchemeAsLocal(jstringToWtfString(env, scheme));
}
-static bool FocusBoundsChanged(JNIEnv* env, jobject obj, jint nativeClass)
-{
- return reinterpret_cast<WebViewCore*>(nativeClass)->focusBoundsChanged();
-}
-
-static void SetIsPaused(JNIEnv* env, jobject obj, jint nativeClass,
- jboolean isPaused)
-{
- // tell the webcore thread to stop thinking while we do other work
- // (selection and scrolling). This has nothing to do with the lifecycle
- // pause and resume.
- reinterpret_cast<WebViewCore*>(nativeClass)->setIsPaused(isPaused);
-}
-
static void Pause(JNIEnv* env, jobject obj, jint nativeClass)
{
// This is called for the foreground tab when the browser is put to the
@@ -4798,50 +4855,36 @@ static void Pause(JNIEnv* env, jobject obj, jint nativeClass)
// browser). The browser can only be killed by the system when it is in the
// background, so saving the Geolocation permission state now ensures that
// is maintained when the browser is killed.
- WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
- ChromeClient* chromeClient = viewImpl->mainFrame()->page()->chrome()->client();
- ChromeClientAndroid* chromeClientAndroid = static_cast<ChromeClientAndroid*>(chromeClient);
- chromeClientAndroid->storeGeolocationPermissions();
+ GeolocationPermissions::maybeStorePermanentPermissions();
+ WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
Frame* mainFrame = viewImpl->mainFrame();
- for (Frame* frame = mainFrame; frame; frame = frame->tree()->traverseNext()) {
- Geolocation* geolocation = frame->domWindow()->navigator()->optionalGeolocation();
- if (geolocation)
- geolocation->suspend();
- }
if (mainFrame)
mainFrame->settings()->setMinDOMTimerInterval(BACKGROUND_TIMER_INTERVAL);
viewImpl->deviceMotionAndOrientationManager()->maybeSuspendClients();
+ viewImpl->geolocationManager()->suspendRealClient();
ANPEvent event;
SkANP::InitEvent(&event, kLifecycle_ANPEventType);
event.data.lifecycle.action = kPause_ANPLifecycleAction;
viewImpl->sendPluginEvent(event);
-
- viewImpl->setIsPaused(true);
}
static void Resume(JNIEnv* env, jobject obj, jint nativeClass)
{
WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
Frame* mainFrame = viewImpl->mainFrame();
- for (Frame* frame = mainFrame; frame; frame = frame->tree()->traverseNext()) {
- Geolocation* geolocation = frame->domWindow()->navigator()->optionalGeolocation();
- if (geolocation)
- geolocation->resume();
- }
if (mainFrame)
mainFrame->settings()->setMinDOMTimerInterval(FOREGROUND_TIMER_INTERVAL);
viewImpl->deviceMotionAndOrientationManager()->maybeResumeClients();
+ viewImpl->geolocationManager()->resumeRealClient();
ANPEvent event;
SkANP::InitEvent(&event, kLifecycle_ANPEventType);
event.data.lifecycle.action = kResume_ANPLifecycleAction;
viewImpl->sendPluginEvent(event);
-
- viewImpl->setIsPaused(false);
}
static void FreeMemory(JNIEnv* env, jobject obj, jint nativeClass)
@@ -4959,10 +5002,10 @@ static jobject GetText(JNIEnv* env, jobject obj, jint nativeClass,
}
static void SelectText(JNIEnv* env, jobject obj, jint nativeClass,
- jint startX, jint startY, jint endX, jint endY)
+ jint handleId, jint x, jint y)
{
WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
- viewImpl->selectText(startX, startY, endX, endY);
+ viewImpl->selectText(static_cast<SelectText::HandleId>(handleId), x, y);
}
static void ClearSelection(JNIEnv* env, jobject obj, jint nativeClass)
@@ -5006,8 +5049,6 @@ static int FindNext(JNIEnv* env, jobject obj, jint nativeClass,
static JNINativeMethod gJavaWebViewCoreMethods[] = {
{ "nativeClearContent", "(I)V",
(void*) ClearContent },
- { "nativeFocusBoundsChanged", "(I)Z",
- (void*) FocusBoundsChanged } ,
{ "nativeKey", "(IIIIZZZZ)Z",
(void*) Key },
{ "nativeContentInvalidateAll", "(I)V",
@@ -5034,7 +5075,7 @@ static JNINativeMethod gJavaWebViewCoreMethods[] = {
(void*) MoveMouse },
{ "passToJs", "(IILjava/lang/String;IIZZZZ)V",
(void*) PassToJs },
- { "nativeScrollFocusedTextInput", "(IFILandroid/graphics/Rect;)V",
+ { "nativeScrollFocusedTextInput", "(IFI)V",
(void*) ScrollFocusedTextInput },
{ "nativeSetFocusControllerActive", "(IZ)V",
(void*) SetFocusControllerActive },
@@ -5072,7 +5113,6 @@ static JNINativeMethod gJavaWebViewCoreMethods[] = {
(void*) SetNewStorageLimit },
{ "nativeGeolocationPermissionsProvide", "(ILjava/lang/String;ZZ)V",
(void*) GeolocationPermissionsProvide },
- { "nativeSetIsPaused", "(IZ)V", (void*) SetIsPaused },
{ "nativePause", "(I)V", (void*) Pause },
{ "nativeResume", "(I)V", (void*) Resume },
{ "nativeFreeMemory", "(I)V", (void*) FreeMemory },
@@ -5100,7 +5140,7 @@ static JNINativeMethod gJavaWebViewCoreMethods[] = {
(void*) InsertText },
{ "nativeGetText", "(IIIII)Ljava/lang/String;",
(void*) GetText },
- { "nativeSelectText", "(IIIII)V",
+ { "nativeSelectText", "(IIII)V",
(void*) SelectText },
{ "nativeClearTextSelection", "(I)V",
(void*) ClearSelection },
diff --git a/Source/WebKit/android/jni/WebViewCore.h b/Source/WebKit/android/jni/WebViewCore.h
index 5264f7f..4e223b3 100644
--- a/Source/WebKit/android/jni/WebViewCore.h
+++ b/Source/WebKit/android/jni/WebViewCore.h
@@ -30,6 +30,7 @@
#include "DOMSelection.h"
#include "FileChooser.h"
#include "FocusDirection.h"
+#include "GeolocationManager.h"
#include "HitTestResult.h"
#include "PicturePile.h"
#include "PlatformGraphicsContext.h"
@@ -201,13 +202,9 @@ namespace android {
/**
* Tell the java side to update the focused textfield
* @param pointer Pointer to the node for the input field.
- * @param changeToPassword If true, we are changing the textfield to
- * a password field, and ignore the WTF::String
- * @param text If changeToPassword is false, this is the new text that
- * should go into the textfield.
+ * @param text This is the new text that should go into the textfield.
*/
- void updateTextfield(WebCore::Node* pointer,
- bool changeToPassword, const WTF::String& text);
+ void updateTextfield(WebCore::Node* pointer, const WTF::String& text);
/**
* Tell the java side to update the current selection in the focused
@@ -396,7 +393,7 @@ namespace android {
/**
* Scroll the focused textfield to (x, y) in document space
*/
- WebCore::IntRect scrollFocusedTextInput(float x, int y);
+ void scrollFocusedTextInput(float x, int y);
/**
* Set the FocusController's active and focused states, so that
* the caret will draw (true) or not.
@@ -508,8 +505,6 @@ namespace android {
// reset the picture set to empty
void clearContent();
- bool focusBoundsChanged();
-
// record content in a new BaseLayerAndroid, copying the layer tree as well
WebCore::BaseLayerAndroid* recordContent(SkIPoint* );
@@ -526,8 +521,6 @@ namespace android {
WebCore::Frame* mainFrame() const { return m_mainFrame; }
WebCore::Frame* focusedFrame() const;
- void notifyWebAppCanBeInstalled();
-
void deleteText(int startX, int startY, int endX, int endY);
WTF::String getText(int startX, int startY, int endX, int endY);
void insertText(const WTF::String &text);
@@ -539,19 +532,18 @@ namespace android {
void updateMatchCount() const;
#if ENABLE(VIDEO)
- void enterFullscreenForVideoLayer(int layerId, const WTF::String& url);
+ void enterFullscreenForVideoLayer();
void exitFullscreenVideo();
#endif
void setWebTextViewAutoFillable(int queryId, const string16& previewSummary);
DeviceMotionAndOrientationManager* deviceMotionAndOrientationManager() { return &m_deviceMotionAndOrientationManager; }
+ GeolocationManager* geolocationManager() { return &m_geolocationManager; }
void listBoxRequest(WebCoreReply* reply, const uint16_t** labels,
size_t count, const int enabled[], size_t enabledCount,
bool multiple, const int selected[], size_t selectedCountOrSelection);
- bool isPaused() const { return m_isPaused; }
- void setIsPaused(bool isPaused) { m_isPaused = isPaused; }
bool drawIsPaused() const;
// The actual content (without title bar) size in doc coordinate
int screenWidth() const { return m_screenWidth; }
@@ -580,7 +572,7 @@ namespace android {
int startX, int startY, int endX, int endY);
static int platformLayerIdFromNode(WebCore::Node* node,
WebCore::LayerAndroid** outLayer = 0);
- void selectText(int startX, int startY, int endX, int endY);
+ void selectText(SelectText::HandleId handleId, int x, int y);
bool selectWordAt(int x, int y);
// Converts from the global content coordinates that WebView sends
@@ -728,18 +720,20 @@ namespace android {
void setSelectionCaretInfo(SelectText* selectTextContainer,
const WebCore::Position& position,
const WebCore::IntPoint& frameOffset,
- SelectText::HandleId handleId, int offset,
- EAffinity affinity);
+ SelectText::HandleId handleId, SelectText::HandleType handleType,
+ int offset, EAffinity affinity);
static int getMaxLength(WebCore::Node* node);
static WTF::String getFieldName(WebCore::Node* node);
static bool isAutoCompleteEnabled(WebCore::Node* node);
- WebCore::IntRect absoluteContentRect(WebCore::Node* node,
+ WebCore::IntRect absoluteClientRect(WebCore::Node* node,
WebCore::LayerAndroid* layer);
static WebCore::IntRect positionToTextRect(const WebCore::Position& position,
- WebCore::EAffinity affinity, const WebCore::IntPoint& offset);
+ WebCore::EAffinity affinity, const WebCore::IntPoint& offset,
+ const WebCore::IntRect& caretRect);
static bool isLtr(const WebCore::Position& position);
- static WebCore::Position trimSelectionPosition(
- const WebCore::Position& start, const WebCore::Position& stop);
+ static WebCore::VisiblePosition trimSelectionPosition(
+ const WebCore::VisiblePosition& start,
+ const WebCore::VisiblePosition& stop);
// called from constructor, to add this to a global list
static void addInstance(WebViewCore*);
@@ -759,7 +753,6 @@ namespace android {
// Used in passToJS to avoid updating the UI text field until after the
// key event has been processed.
bool m_blockTextfieldUpdates;
- bool m_focusBoundsChanged;
bool m_skipContentDraw;
// Passed in with key events to know when they were generated. Store it
// with the cache so that we can ignore stale text changes.
@@ -782,7 +775,6 @@ namespace android {
int m_textWrapWidth;
float m_scale;
WebCore::PageGroup* m_groupForVisitedLinks;
- bool m_isPaused;
int m_cacheMode;
bool m_fullscreenVideoMode;
@@ -801,6 +793,7 @@ namespace android {
int m_screenOnCounter;
WebCore::Node* m_currentNodeDomNavigationAxis;
DeviceMotionAndOrientationManager m_deviceMotionAndOrientationManager;
+ GeolocationManager m_geolocationManager;
#if ENABLE(TOUCH_EVENTS)
bool m_forwardingTouchEvents;
diff --git a/Source/WebKit/android/nav/DrawExtra.cpp b/Source/WebKit/android/nav/DrawExtra.cpp
index 2f57dc1..a7d686c 100644
--- a/Source/WebKit/android/nav/DrawExtra.cpp
+++ b/Source/WebKit/android/nav/DrawExtra.cpp
@@ -52,7 +52,8 @@ SkRegion* RegionLayerDrawExtra::getHighlightRegionsForLayer(const LayerAndroid*
}
void RegionLayerDrawExtra::addHighlightRegion(const LayerAndroid* layer, const Vector<IntRect>& rects,
- const IntPoint& additionalOffset)
+ const IntPoint& additionalOffset,
+ const IntRect& clipRect)
{
if (rects.isEmpty())
return;
@@ -66,6 +67,11 @@ void RegionLayerDrawExtra::addHighlightRegion(const LayerAndroid* layer, const V
WebViewCore::layerToAbsoluteOffset(layer, offset);
for (size_t i = 0; i < rects.size(); i++) {
IntRect r = rects.at(i);
+ if (!clipRect.isEmpty()) {
+ r.intersect(clipRect);
+ if (r.isEmpty())
+ continue; // don't add it to the region
+ }
r.move(-offset.x(), -offset.y());
region->op(r.x(), r.y(), r.maxX(), r.maxY(), SkRegion::kUnion_Op);
}
diff --git a/Source/WebKit/android/nav/DrawExtra.h b/Source/WebKit/android/nav/DrawExtra.h
index cc94476..1850b6b 100644
--- a/Source/WebKit/android/nav/DrawExtra.h
+++ b/Source/WebKit/android/nav/DrawExtra.h
@@ -65,7 +65,8 @@ public:
virtual ~RegionLayerDrawExtra();
void addHighlightRegion(const LayerAndroid* layer, const Vector<IntRect>& rects,
- const IntPoint& additionalOffset = IntPoint());
+ const IntPoint& additionalOffset = IntPoint(),
+ const IntRect& clipRect = IntRect());
virtual void draw(SkCanvas*, LayerAndroid*);
virtual void drawGL(GLExtras*, const LayerAndroid*);
diff --git a/Source/WebKit/android/nav/SelectText.h b/Source/WebKit/android/nav/SelectText.h
index aaaf3bb..8f7592d 100644
--- a/Source/WebKit/android/nav/SelectText.h
+++ b/Source/WebKit/android/nav/SelectText.h
@@ -35,8 +35,13 @@ namespace android {
class SelectText : public RegionLayerDrawExtra {
public:
enum HandleId {
+ BaseHandle = 0,
+ ExtentHandle = 1,
+ };
+ enum HandleType {
LeftHandle = 0,
- RightHandle = 1,
+ CenterHandle = 1,
+ RightHandle = 2,
};
IntRect& caretRect(HandleId id) { return m_caretRects[id]; }
@@ -48,11 +53,14 @@ public:
void setText(const String& text) { m_text = text.threadsafeCopy(); }
String& getText() { return m_text; }
+ HandleType getHandleType(HandleId id) { return m_handleType[id]; }
+ void setHandleType(HandleId id, HandleType type) { m_handleType[id] = type; }
private:
IntRect m_caretRects[2];
IntRect m_textRects[2];
int m_caretLayerId[2];
+ HandleType m_handleType[2];
String m_text;
};
diff --git a/Source/WebKit/android/nav/WebView.cpp b/Source/WebKit/android/nav/WebView.cpp
index a67b5fd..66dbdc1 100644
--- a/Source/WebKit/android/nav/WebView.cpp
+++ b/Source/WebKit/android/nav/WebView.cpp
@@ -32,6 +32,7 @@
#include "BaseLayerAndroid.h"
#include "BaseRenderer.h"
#include "DrawExtra.h"
+#include "DumpLayer.h"
#include "Frame.h"
#include "GLWebViewState.h"
#include "GraphicsJNI.h"
@@ -57,7 +58,6 @@
#include "WebCoreJni.h"
#include "WebRequestContext.h"
#include "WebViewCore.h"
-#include "android_graphics.h"
#ifdef GET_NATIVE_VIEW
#undef GET_NATIVE_VIEW
@@ -716,7 +716,7 @@ void findMaxVisibleRect(int movingLayerId, SkIRect& visibleContentRect)
if (findMaskedRectsForLayer(m_baseLayer, rects, movingLayerId)) {
float maxSize = 0.0;
const FloatRect* largest = 0;
- for (int i = 0; i < rects.size(); i++) {
+ for (unsigned int i = 0; i < rects.size(); i++) {
const FloatRect& rect = rects[i];
float size = rect.width() * rect.height();
if (size > maxSize) {
@@ -731,6 +731,29 @@ void findMaxVisibleRect(int movingLayerId, SkIRect& visibleContentRect)
}
}
+bool isHandleLeft(SelectText::HandleId handleId)
+{
+ SelectText* selectText = static_cast<SelectText*>(getDrawExtra(DrawExtrasSelection));
+ if (!selectText)
+ return (handleId == SelectText::BaseHandle);
+
+ return (selectText->getHandleType(handleId) == SelectText::LeftHandle);
+}
+
+bool isPointVisible(int layerId, int contentX, int contentY)
+{
+ bool isVisible = true;
+ const TransformationMatrix* transform = getLayerTransform(layerId);
+ if (transform) {
+ // layer is guaranteed to be non-NULL because of getLayerTransform
+ LayerAndroid* layer = m_baseLayer->findById(layerId);
+ IntRect rect = layer->visibleContentArea();
+ rect = transform->mapRect(rect);
+ isVisible = rect.contains(contentX, contentY);
+ }
+ return isVisible;
+}
+
private: // local state for WebView
bool m_isDrawingPaused;
// private to getFrameCache(); other functions operate in a different thread
@@ -972,6 +995,28 @@ static void nativeCopyBaseContentToPicture(JNIEnv *env, jobject obj, jobject pic
GET_NATIVE_VIEW(env, obj)->copyBaseContentToPicture(picture);
}
+static jboolean nativeDumpLayerContentToPicture(JNIEnv *env, jobject obj, jint instance,
+ jstring jclassName, jint layerId, jobject pict)
+{
+ bool success = false;
+ SkPicture* picture = GraphicsJNI::getNativePicture(env, pict);
+ std::string classname = jstringToStdString(env, jclassName);
+ BaseLayerAndroid* baseLayer = reinterpret_cast<WebView*>(instance)->getBaseLayer();
+ LayerAndroid* layer = baseLayer->findById(layerId);
+ SkSafeRef(layer);
+ if (layer && layer->subclassName() == classname) {
+ LayerContent* content = layer->content();
+ if (content) {
+ SkCanvas* canvas = picture->beginRecording(content->width(), content->height());
+ content->draw(canvas);
+ picture->endRecording();
+ success = true;
+ }
+ }
+ SkSafeUnref(layer);
+ return success;
+}
+
static bool nativeHasContent(JNIEnv *env, jobject obj)
{
return GET_NATIVE_VIEW(env, obj)->hasContent();
@@ -1164,7 +1209,8 @@ static void nativeDumpDisplayTree(JNIEnv* env, jobject jwebview, jstring jurl)
if (baseLayer) {
FILE* file = fopen(LAYERS_TREE_LOG_FILE,"w");
if (file) {
- baseLayer->dumpLayers(file, 0);
+ WebCore::FileLayerDumper dumper(file);
+ baseLayer->dumpLayers(&dumper);
fclose(file);
}
}
@@ -1288,6 +1334,20 @@ static void nativeFindMaxVisibleRect(JNIEnv *env, jobject obj, jint nativeView,
GraphicsJNI::irect_to_jrect(nativeRect, env, visibleContentRect);
}
+static bool nativeIsHandleLeft(JNIEnv *env, jobject obj, jint nativeView,
+ jint handleId)
+{
+ WebView* webview = reinterpret_cast<WebView*>(nativeView);
+ return webview->isHandleLeft(static_cast<SelectText::HandleId>(handleId));
+}
+
+static bool nativeIsPointVisible(JNIEnv *env, jobject obj, jint nativeView,
+ jint layerId, jint contentX, jint contentY)
+{
+ WebView* webview = reinterpret_cast<WebView*>(nativeView);
+ return webview->isPointVisible(layerId, contentX, contentY);
+}
+
/*
* JNI registration
*/
@@ -1318,6 +1378,8 @@ static JNINativeMethod gJavaWebViewMethods[] = {
(void*) nativeGetBaseLayer },
{ "nativeCopyBaseContentToPicture", "(Landroid/graphics/Picture;)V",
(void*) nativeCopyBaseContentToPicture },
+ { "nativeDumpLayerContentToPicture", "(ILjava/lang/String;ILandroid/graphics/Picture;)Z",
+ (void*) nativeDumpLayerContentToPicture },
{ "nativeHasContent", "()Z",
(void*) nativeHasContent },
{ "nativeDiscardAllTextures", "()V",
@@ -1366,6 +1428,10 @@ static JNINativeMethod gJavaWebViewMethods[] = {
(void*) nativeSetHwAccelerated },
{ "nativeFindMaxVisibleRect", "(IILandroid/graphics/Rect;)V",
(void*) nativeFindMaxVisibleRect },
+ { "nativeIsHandleLeft", "(II)Z",
+ (void*) nativeIsHandleLeft },
+ { "nativeIsPointVisible", "(IIII)Z",
+ (void*) nativeIsPointVisible },
};
int registerWebView(JNIEnv* env)
diff --git a/Source/WebKit/android/plugins/ANPSoundInterface.cpp b/Source/WebKit/android/plugins/ANPSoundInterface.cpp
index 9d19443..929832b 100644
--- a/Source/WebKit/android/plugins/ANPSoundInterface.cpp
+++ b/Source/WebKit/android/plugins/ANPSoundInterface.cpp
@@ -100,7 +100,7 @@ static ANPAudioTrack* ANPCreateTrack(uint32_t sampleRate,
track->mTrack = new android::AudioTrack(AUDIO_STREAM_MUSIC,
sampleRate,
fromANPFormat(format),
- (channelCount > 1) ? AUDIO_CHANNEL_OUT_STEREO : AUDIO_CHANNEL_OUT_MONO,
+ audio_channel_out_mask_from_count(channelCount),
0, // frameCount
(audio_output_flags_t) 0, // AUDIO_OUTPUT_FLAG_NONE,
callbackProc,
diff --git a/Source/WebKit/android/plugins/ANPSurfaceInterface.cpp b/Source/WebKit/android/plugins/ANPSurfaceInterface.cpp
index 92dbbcd..2b593e2 100644
--- a/Source/WebKit/android/plugins/ANPSurfaceInterface.cpp
+++ b/Source/WebKit/android/plugins/ANPSurfaceInterface.cpp
@@ -30,7 +30,6 @@
#include "PluginView.h"
#include "PluginWidgetAndroid.h"
#include "SkANP.h"
-#include "android_graphics.h"
#include <JNIUtility.h>
#include <gui/Surface.h>
#include <ui/Rect.h>
diff --git a/Source/WebKit/android/plugins/PluginWidgetAndroid.cpp b/Source/WebKit/android/plugins/PluginWidgetAndroid.cpp
index 09bb24e..2fd2ef4 100644
--- a/Source/WebKit/android/plugins/PluginWidgetAndroid.cpp
+++ b/Source/WebKit/android/plugins/PluginWidgetAndroid.cpp
@@ -42,7 +42,6 @@
#include "SkString.h"
#include "SkTime.h"
#include "WebViewCore.h"
-#include "android_graphics.h"
#include <JNIUtility.h>
//#define PLUGIN_DEBUG_LOCAL // controls the printing of log messages
@@ -225,7 +224,7 @@ void PluginWidgetAndroid::viewInvalidate() {
m_core->viewInvalidate(rect);
}
-void PluginWidgetAndroid::draw(SkCanvas* canvas) {
+void PluginWidgetAndroid::draw(PlatformGraphicsContext* context) {
if (NULL == m_flipPixelRef || !m_flipPixelRef->isDirty()) {
return;
}
@@ -249,10 +248,11 @@ void PluginWidgetAndroid::draw(SkCanvas* canvas) {
bitmap) &&
pkg->pluginFuncs()->event(instance, &event)) {
- if (canvas && m_pluginWindow) {
+ if (context && m_pluginWindow) {
SkBitmap bm(bitmap);
bm.setPixelRef(m_flipPixelRef);
- canvas->drawBitmap(bm, 0, 0);
+ IntRect dst(0, 0, bm.width(), bm.height());
+ context->drawBitmapRect(bm, 0, dst);
}
}
break;
diff --git a/Source/WebKit/android/plugins/PluginWidgetAndroid.h b/Source/WebKit/android/plugins/PluginWidgetAndroid.h
index 87612dd..73b116b 100644
--- a/Source/WebKit/android/plugins/PluginWidgetAndroid.h
+++ b/Source/WebKit/android/plugins/PluginWidgetAndroid.h
@@ -28,6 +28,7 @@
#include "android_npapi.h"
#include "ANPSystem_npapi.h"
+#include "GraphicsContext.h"
#include "IntPoint.h"
#include "IntRect.h"
#include "MediaLayer.h"
@@ -98,7 +99,7 @@ struct PluginWidgetAndroid {
/* Called to draw into the plugin's bitmap. If canvas is non-null, the
bitmap itself is then drawn into the canvas.
*/
- void draw(SkCanvas* canvas = NULL);
+ void draw(PlatformGraphicsContext* context = NULL);
/* Send this event to the plugin instance. A non-zero value will be
returned if the plugin handled the event.
diff --git a/Source/WebKit/android/smoke/MessageThread.cpp b/Source/WebKit/android/smoke/MessageThread.cpp
deleted file mode 100644
index 97ab18c..0000000
--- a/Source/WebKit/android/smoke/MessageThread.cpp
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Copyright 2010, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#define LOG_TAG "MessageThread"
-
-#include "config.h"
-
-#include <sys/time.h>
-#include <time.h>
-
-#include "MessageThread.h"
-#include "ScriptController.h"
-
-#include <utils/Log.h>
-
-namespace android {
-
-static bool compareMessages(const Message& msg1,
- const Message& msg2,
- bool memberIsNull) {
- return (msg1.object() == msg2.object() &&
- (memberIsNull || msg1.member() == msg2.member()));
-}
-
-bool MessageQueue::hasMessages(const Message& message) {
- AutoMutex lock(m_mutex);
-
- static const Message::GenericMemberFunction nullMember = NULL;
- const bool memberIsNull = message.member() == nullMember;
-
- for (list<Message*>::iterator it = m_messages.begin();
- it != m_messages.end(); ++it) {
- Message* m = *it;
- if (compareMessages(message, *m, memberIsNull))
- return true;
- }
- return false;
-}
-
-void MessageQueue::remove(const Message& message) {
- AutoMutex lock(m_mutex);
-
- static const Message::GenericMemberFunction nullMember = NULL;
- const bool memberIsNull = message.member() == nullMember;
-
- for (list<Message*>::iterator it = m_messages.begin();
- it != m_messages.end(); ++it) {
- Message* m = *it;
- if (compareMessages(message, *m, memberIsNull)) {
- it = m_messages.erase(it);
- delete m;
- }
- }
-}
-
-void MessageQueue::post(Message* message) {
- AutoMutex lock(m_mutex);
-
- double when = message->m_when;
- ALOG_ASSERT(when > 0, "Message time may not be 0");
-
- list<Message*>::iterator it;
- for (it = m_messages.begin(); it != m_messages.end(); ++it) {
- Message* m = *it;
- if (when < m->m_when) {
- break;
- }
- }
- m_messages.insert(it, message);
- m_condition.signal();
-}
-
-void MessageQueue::postAtFront(Message* message) {
- AutoMutex lock(m_mutex);
- message->m_when = 0;
- m_messages.push_front(message);
-}
-
-Message* MessageQueue::next() {
- AutoMutex lock(m_mutex);
- while (true) {
- if (m_messages.empty()) {
- // No messages, wait until another arrives
- m_condition.wait(m_mutex);
- }
- Message* next = m_messages.front();
- double now = WTF::currentTimeMS();
- double diff = next->m_when - now;
- if (diff > 0) {
- // Not time for this message yet, wait the difference in nanos
- m_condition.waitRelative(m_mutex,
- static_cast<nsecs_t>(diff * 1000000) /* nanos */);
- } else {
- // Time for this message to run.
- m_messages.pop_front();
- return next;
- }
- }
-}
-
-bool MessageThread::threadLoop() {
- WebCore::ScriptController::initializeThreading();
-
- while (true) {
- Message* message = m_queue.next();
- if (message != NULL) {
- message->run();
- }
- }
- return false;
-}
-
-// Global thread object obtained by messageThread().
-static sp<MessageThread> gMessageThread;
-
-MessageThread* messageThread() {
- if (gMessageThread == NULL) {
- gMessageThread = new MessageThread();
- gMessageThread->run("WebCoreThread");
- }
- return gMessageThread.get();
-}
-
-} // namespace android
diff --git a/Source/WebKit/android/smoke/MessageThread.h b/Source/WebKit/android/smoke/MessageThread.h
deleted file mode 100644
index 34ff4af..0000000
--- a/Source/WebKit/android/smoke/MessageThread.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright 2010, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef MessageThread_h
-#define MessageThread_h
-
-#include <list>
-
-#include "MessageTypes.h"
-
-#include <utils/threads.h>
-
-using std::list;
-
-namespace android {
-
-class MessageQueue {
-public:
- MessageQueue() {}
-
- // Return true if the queue has messages with the given object and member
- // function. If member is null, return true if the message has the same
- // object.
- template <class T>
- bool hasMessages(T* object, void (T::*member)(void));
-
- // Remove all messages with the given object and member function. If
- // member is null, remove all messages with the given object.
- template <class T>
- void remove(T* object, void (T::*member)(void));
-
- // Post a new message to the queue.
- void post(Message* closure);
-
- // Post a new message at the front of the queue.
- void postAtFront(Message* closure);
-
- // Obtain the next message. Blocks until either a new message arrives or
- // we reach the time of the next message.
- Message* next();
-
-private:
- bool hasMessages(const Message& message);
- void remove(const Message& message);
-
- list<Message*> m_messages;
- Mutex m_mutex;
- Condition m_condition;
-};
-
-template <class T>
-bool MessageQueue::hasMessages(T* object, void (T::*member)(void)) {
- MemberFunctionMessage<T, void> message(object, member);
- return hasMessages(message);
-}
-
-template <class T>
-void MessageQueue::remove(T* object, void (T::*member)(void)) {
- MemberFunctionMessage<T, void> message(object, member);
- remove(message);
-}
-
-class MessageThread : public Thread {
-public:
- MessageQueue& queue() { return m_queue; }
-
-private:
- MessageThread() : Thread(true /* canCallJava */) {}
-
- virtual bool threadLoop();
-
- MessageQueue m_queue;
- // Used for thread initialization
- Mutex m_mutex;
- Condition m_condition;
-
- friend MessageThread* messageThread();
-};
-
-// Get (possibly creating) the global MessageThread object used to pass
-// messages to WebCore.
-MessageThread* messageThread();
-
-} // namespace android
-
-#endif // MessageThread_h
diff --git a/Source/WebKit/android/smoke/MessageTypes.h b/Source/WebKit/android/smoke/MessageTypes.h
deleted file mode 100644
index 4d30648..0000000
--- a/Source/WebKit/android/smoke/MessageTypes.h
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Copyright 2010, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef MessageTypes_h
-#define MessageTypes_h
-
-#include <wtf/CurrentTime.h>
-
-// TODO(phanna): autogenerate these types!
-
-namespace android {
-
-// Forward declared for friendship!
-class MessageQueue;
-
-// Removes the reference from the typename so we store the actual value in the
-// closure.
-template <typename T> struct remove_reference { typedef T type; };
-template <typename T> struct remove_reference<T&> { typedef T type; };
-
-// Prevent the compiler from inferring the type.
-template <typename T> struct identity { typedef T type; };
-
-// Message base class. Defines the public run() method and contains generic
-// object and member function variables for use in MessageQueue.
-//
-// Note: The template subclass MemberFunctionMessage casts its object and
-// member function to the generic void* and Message::* types. During run(),
-// each template specialization downcasts to the original type and invokes the
-// correct function. This may seem dangerous but the compiler enforces
-// correctness in NewMessage and in the template constructor.
-class Message {
-public:
- typedef void (Message::*GenericMemberFunction)(void);
-
- virtual ~Message() {}
- virtual void run() = 0;
-
- // The wall time that the message is supposed to run.
- double m_when;
-
- void* object() const { return m_object; }
- GenericMemberFunction member() const { return m_member; }
-
-protected:
- Message(void* object, GenericMemberFunction member, long delay = 0)
- : m_object(object)
- , m_member(member) {
- m_when = WTF::currentTimeMS() + delay;
- }
-
- // Downcast back to the original template params in run(). Also accessed
- // by MessageQueue to compare messages.
- void* m_object;
- GenericMemberFunction m_member;
-
-private:
- // Disallow copy
- Message(const Message&);
-};
-
-// Forward declaration for partial specialization.
-template <class T, typename A1>
-class MemberFunctionMessage;
-
-template <class T>
-class MemberFunctionMessage<T, void> : public Message {
-private:
- typedef void (T::*MemberSignature)();
-
-public:
- inline MemberFunctionMessage(T* object,
- MemberSignature member,
- long delay = 0)
- : Message(reinterpret_cast<void*>(object),
- reinterpret_cast<GenericMemberFunction>(member),
- delay) {}
-
- virtual void run() {
- MemberSignature member = reinterpret_cast<MemberSignature>(m_member);
- (reinterpret_cast<T*>(m_object)->*member)();
- delete this;
- }
-};
-
-template <class T>
-inline Message* NewMessage(T* object, void (T::*member)()) {
- return new MemberFunctionMessage<T, void>(object, member);
-}
-
-template <class T>
-inline Message* NewDelayedMessage(T* object, void (T::*member)(), long delay) {
- return new MemberFunctionMessage<T, void>(object, member, delay);
-}
-
-template <class T, typename A1>
-class MemberFunctionMessage : public Message {
-private:
- typedef void (T::*MemberSignature)(A1);
-
-public:
- inline MemberFunctionMessage(T* object,
- MemberSignature member,
- A1 arg1,
- long delay = 0)
- : Message(reinterpret_cast<void*>(object),
- reinterpret_cast<GenericMemberFunction>(member),
- delay)
- , m_arg1(arg1) {}
-
- virtual void run() {
- MemberSignature member = reinterpret_cast<MemberSignature>(m_member);
- (reinterpret_cast<T*>(m_object)->*member)(m_arg1);
- delete this;
- }
-
-private:
- typename remove_reference<A1>::type m_arg1;
-};
-
-template <class T, typename A1>
-inline Message* NewMessage(T* object, void (T::*member)(A1),
- typename identity<A1>::type arg1) {
- return new MemberFunctionMessage<T, A1>(
- object, member, arg1);
-}
-
-template <class T, typename A1>
-inline Message* NewDelayedMessage(T* object, void (T::*member)(A1),
- typename identity<A1>::type arg1, long delay) {
- return new MemberFunctionMessage<T, A1>(object, member, arg1, delay);
-}
-
-} // namespace android
-
-
-#endif // MessageTypes_h
diff --git a/ThirdPartyProject.prop b/ThirdPartyProject.prop
deleted file mode 100644
index ae9d227..0000000
--- a/ThirdPartyProject.prop
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright 2010 Google Inc. All Rights Reserved.
-#Fri Sep 10 11:49:27 BST 2010
-currentVersion=55486
-version=84325
-isNative=true
-name=webkit
-keywords=webkit
-onDevice=true
-homepage=http\://webkit.org/
-# Currently we track the Chromium 12.0.742 release branch:
-# http://trac.webkit.org/browser/branches/chromium/742
-# which is WebKit trunk r84325 plus stability cherry picks.
-webkit.chromiumRelease=http\://src.chromium.org/svn/releases/12.0.742.130/DEPS
diff --git a/WEBKIT_MERGE_REVISION b/WEBKIT_MERGE_REVISION
new file mode 100644
index 0000000..956ae85
--- /dev/null
+++ b/WEBKIT_MERGE_REVISION
@@ -0,0 +1,5 @@
+Currently we track the Chromium 12.0.742 release branch:
+http://trac.webkit.org/browser/branches/chromium/742
+which is WebKit trunk r84325 plus stability cherry picks.
+
+See also http://src.chromium.org/svn/releases/12.0.742.130/DEPS