diff options
Diffstat (limited to 'Source/WebCore')
96 files changed, 3206 insertions, 1836 deletions
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/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/GeolocationServiceBridge.cpp b/Source/WebCore/platform/android/GeolocationServiceBridge.cpp deleted file mode 100644 index 697b63b..0000000 --- a/Source/WebCore/platform/android/GeolocationServiceBridge.cpp +++ /dev/null @@ -1,246 +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 "GeolocationServiceBridge.h" - -#include "Frame.h" -#include "GeolocationServiceAndroid.h" -#include "Geoposition.h" -#include "PositionError.h" -#include "WebViewCore.h" -#include <JNIHelp.h> - -namespace WebCore { - -using JSC::Bindings::getJNIEnv; - -static const char* javaGeolocationServiceClassName = "android/webkit/GeolocationService"; -enum javaGeolocationServiceClassMethods { - GeolocationServiceMethodInit = 0, - GeolocationServiceMethodStart, - GeolocationServiceMethodStop, - GeolocationServiceMethodSetEnableGps, - GeolocationServiceMethodCount, -}; -static jmethodID javaGeolocationServiceClassMethodIDs[GeolocationServiceMethodCount]; - -static const JNINativeMethod javaGeolocationServiceClassNativeMethods[] = { - { "nativeNewLocationAvailable", "(JLandroid/location/Location;)V", - (void*) GeolocationServiceBridge::newLocationAvailable }, - { "nativeNewErrorAvailable", "(JLjava/lang/String;)V", - (void*) GeolocationServiceBridge::newErrorAvailable } -}; - -static const char *javaLocationClassName = "android/location/Location"; -enum javaLocationClassMethods { - LocationMethodGetLatitude = 0, - LocationMethodGetLongitude, - LocationMethodHasAltitude, - LocationMethodGetAltitude, - LocationMethodHasAccuracy, - LocationMethodGetAccuracy, - LocationMethodHasBearing, - LocationMethodGetBearing, - LocationMethodHasSpeed, - LocationMethodGetSpeed, - LocationMethodGetTime, - LocationMethodCount, -}; -static jmethodID javaLocationClassMethodIDs[LocationMethodCount]; - -GeolocationServiceBridge::GeolocationServiceBridge(ListenerInterface* listener, Frame* frame) - : m_listener(listener) - , m_javaGeolocationServiceObject(0) -{ - ASSERT(m_listener); - startJavaImplementation(frame); -} - -GeolocationServiceBridge::~GeolocationServiceBridge() -{ - stop(); - stopJavaImplementation(); -} - -bool GeolocationServiceBridge::start() -{ - if (!m_javaGeolocationServiceObject) - return false; - return getJNIEnv()->CallBooleanMethod(m_javaGeolocationServiceObject, - javaGeolocationServiceClassMethodIDs[GeolocationServiceMethodStart]); -} - -void GeolocationServiceBridge::stop() -{ - if (!m_javaGeolocationServiceObject) - return; - getJNIEnv()->CallVoidMethod(m_javaGeolocationServiceObject, - javaGeolocationServiceClassMethodIDs[GeolocationServiceMethodStop]); -} - -void GeolocationServiceBridge::setEnableGps(bool enable) -{ - if (!m_javaGeolocationServiceObject) - return; - getJNIEnv()->CallVoidMethod(m_javaGeolocationServiceObject, - javaGeolocationServiceClassMethodIDs[GeolocationServiceMethodSetEnableGps], - enable); -} - -void GeolocationServiceBridge::newLocationAvailable(JNIEnv* env, jclass, jlong nativeObject, jobject location) -{ - ASSERT(nativeObject); - ASSERT(location); - GeolocationServiceBridge* object = reinterpret_cast<GeolocationServiceBridge*>(nativeObject); - object->m_listener->newPositionAvailable(toGeoposition(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)); - object->m_listener->newErrorAvailable(error.release()); -} - -PassRefPtr<Geoposition> GeolocationServiceBridge::toGeoposition(JNIEnv *env, const jobject &location) -{ - // Altitude is optional and may not be supplied. - bool hasAltitude = - env->CallBooleanMethod(location, javaLocationClassMethodIDs[LocationMethodHasAltitude]); - double Altitude = - hasAltitude ? - env->CallDoubleMethod(location, javaLocationClassMethodIDs[LocationMethodGetAltitude]) : - 0.0; - // Accuracy is required, but is not supplied by the emulator. - double Accuracy = - env->CallBooleanMethod(location, javaLocationClassMethodIDs[LocationMethodHasAccuracy]) ? - env->CallFloatMethod(location, javaLocationClassMethodIDs[LocationMethodGetAccuracy]) : - 0.0; - // heading is optional and may not be supplied. - bool hasHeading = - env->CallBooleanMethod(location, javaLocationClassMethodIDs[LocationMethodHasBearing]); - double heading = - hasHeading ? - env->CallFloatMethod(location, javaLocationClassMethodIDs[LocationMethodGetBearing]) : - 0.0; - // speed is optional and may not be supplied. - bool hasSpeed = - env->CallBooleanMethod(location, javaLocationClassMethodIDs[LocationMethodHasSpeed]); - double speed = - hasSpeed ? - env->CallFloatMethod(location, javaLocationClassMethodIDs[LocationMethodGetSpeed]) : - 0.0; - - RefPtr<Coordinates> newCoordinates = WebCore::Coordinates::create( - env->CallDoubleMethod(location, javaLocationClassMethodIDs[LocationMethodGetLatitude]), - env->CallDoubleMethod(location, javaLocationClassMethodIDs[LocationMethodGetLongitude]), - hasAltitude, Altitude, - Accuracy, - 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) -{ - JNIEnv* env = getJNIEnv(); - - // Get the Java GeolocationService class. - jclass javaGeolocationServiceClass = env->FindClass(javaGeolocationServiceClassName); - ASSERT(javaGeolocationServiceClass); - - // Set up the methods we wish to call on the Java GeolocationService class. - javaGeolocationServiceClassMethodIDs[GeolocationServiceMethodInit] = - env->GetMethodID(javaGeolocationServiceClass, "<init>", "(Landroid/content/Context;J)V"); - javaGeolocationServiceClassMethodIDs[GeolocationServiceMethodStart] = - env->GetMethodID(javaGeolocationServiceClass, "start", "()Z"); - javaGeolocationServiceClassMethodIDs[GeolocationServiceMethodStop] = - env->GetMethodID(javaGeolocationServiceClass, "stop", "()V"); - javaGeolocationServiceClassMethodIDs[GeolocationServiceMethodSetEnableGps] = - env->GetMethodID(javaGeolocationServiceClass, "setEnableGps", "(Z)V"); - - // Create the Java GeolocationService object. - jobject context = android::WebViewCore::getWebViewCore(frame->view())->getContext(); - if (!context) - return; - jlong nativeObject = reinterpret_cast<jlong>(this); - jobject object = env->NewObject(javaGeolocationServiceClass, - javaGeolocationServiceClassMethodIDs[GeolocationServiceMethodInit], - context, - nativeObject); - - m_javaGeolocationServiceObject = getJNIEnv()->NewGlobalRef(object); - ASSERT(m_javaGeolocationServiceObject); - - // Register to handle calls to native methods of the Java GeolocationService - // object. We register once only. - static int registered = jniRegisterNativeMethods(env, - javaGeolocationServiceClassName, - javaGeolocationServiceClassNativeMethods, - NELEM(javaGeolocationServiceClassNativeMethods)); - ASSERT(registered == JNI_OK); - - // Set up the methods we wish to call on the Java Location class. - jclass javaLocationClass = env->FindClass(javaLocationClassName); - ASSERT(javaLocationClass); - javaLocationClassMethodIDs[LocationMethodGetLatitude] = - env->GetMethodID(javaLocationClass, "getLatitude", "()D"); - javaLocationClassMethodIDs[LocationMethodGetLongitude] = - env->GetMethodID(javaLocationClass, "getLongitude", "()D"); - javaLocationClassMethodIDs[LocationMethodHasAltitude] = - env->GetMethodID(javaLocationClass, "hasAltitude", "()Z"); - javaLocationClassMethodIDs[LocationMethodGetAltitude] = - env->GetMethodID(javaLocationClass, "getAltitude", "()D"); - javaLocationClassMethodIDs[LocationMethodHasAccuracy] = - env->GetMethodID(javaLocationClass, "hasAccuracy", "()Z"); - javaLocationClassMethodIDs[LocationMethodGetAccuracy] = - env->GetMethodID(javaLocationClass, "getAccuracy", "()F"); - javaLocationClassMethodIDs[LocationMethodHasBearing] = - env->GetMethodID(javaLocationClass, "hasBearing", "()Z"); - javaLocationClassMethodIDs[LocationMethodGetBearing] = - env->GetMethodID(javaLocationClass, "getBearing", "()F"); - javaLocationClassMethodIDs[LocationMethodHasSpeed] = - env->GetMethodID(javaLocationClass, "hasSpeed", "()Z"); - javaLocationClassMethodIDs[LocationMethodGetSpeed] = - env->GetMethodID(javaLocationClass, "getSpeed", "()F"); - javaLocationClassMethodIDs[LocationMethodGetTime] = - env->GetMethodID(javaLocationClass, "getTime", "()J"); -} - -void GeolocationServiceBridge::stopJavaImplementation() -{ - // Called by GeolocationServiceAndroid on WebKit thread. - if (!m_javaGeolocationServiceObject) - return; - getJNIEnv()->DeleteGlobalRef(m_javaGeolocationServiceObject); -} - -} // namespace WebCore 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..25441f4 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" @@ -828,22 +829,9 @@ 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, @@ -853,19 +841,22 @@ bool GraphicsLayerAndroid::paintContext(LayerAndroid* layer, if (!layer) return false; - SkPicture* picture = paintPicture(rect); - if (!picture) - return false; - picture->endRecording(); + TRACE_METHOD(); + + // TODO: we might be able to reuse an existing picture instead of recreating it. + // we can't do that because of transparency -- for now, we just create + // a new picture every time. + WebCore::PicturePile picture; + picture.setSize(IntSize(m_size.width(), m_size.height())); + + // 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; } diff --git a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.h b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.h index 460e00f..b40459d 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,7 +154,6 @@ private: bool repaint(); void needsNotifyClient(); - SkPicture* paintPicture(const IntRect& rect); bool paintContext(LayerAndroid* layer, const IntRect& rect, bool checkOptimisations = true); 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 3b93d51..23b22e6 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..c9c382a 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; -}; - -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; -}; + virtual const IntRect* opaqueRect() { return &m_absoluteOpaqueRect; } + virtual void setOpaqueRect(const IntRect& bounds) { m_absoluteOpaqueRect = bounds; } -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,72 @@ 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); - } - virtual OperationType type() { return DrawTextOperation; } -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; + DrawPosText(const void* text, size_t byteLength, + const SkPoint pos[], const SkPaint& paint) + : m_byteLength(byteLength) + , m_paint(paint) + { + size_t points = paint.countText(text, byteLength); + m_pos = new SkPoint[points]; + memcpy(m_pos, pos, sizeof(SkPoint) * points); + m_text = malloc(byteLength); + memcpy(m_text, text, byteLength); + } + ~DrawPosText() { delete m_pos; free(m_text); } + virtual bool applyImpl(PlatformGraphicsContext* context) { + context->drawPosText(m_text, m_byteLength, m_pos, m_paint); + return true; + } + TYPE(DrawPosTextOperation) +private: + void* m_text; + size_t m_byteLength; + SkPoint* m_pos; + 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..6c033b6 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,470 @@ #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 "wtf/NonCopyingSort.h" +#include "wtf/HashSet.h" +#include "wtf/StringHasher.h" + +#define NEW_OP(X) new (operationHeap()) GraphicsOperation::X + +#define USE_CLIPPING_PAINTER true 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; +}; + +typedef HashSet<PlatformGraphicsContext::State*, StateHash> StateHashSet; + +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++) + delete m_operations[i]; + 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_operationHeap; + LinearAllocator m_canvasStateHeap; + LinearAllocator m_stateHeap; +public: + RecordingImpl() + : m_canvasStateHeap(sizeof(CanvasState)) + , m_stateHeap(sizeof(PlatformGraphicsContext::State)) + , m_nodeCount(0) + { + } + + ~RecordingImpl() { + clearStates(); + clearCanvasStates(); + } + + PlatformGraphicsContext::State* getState(PlatformGraphicsContext::State* inState) { + StateHashSet::iterator it = m_states.find(inState); + if (it != m_states.end()) + return (*it); + void* buf = m_stateHeap.alloc(sizeof(PlatformGraphicsContext::State)); + PlatformGraphicsContext::State* state = new (buf) PlatformGraphicsContext::State(*inState); + m_states.add(state); + return state; + } + + 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* operationHeap() { return &m_operationHeap; } + LinearAllocator* canvasStateHeap() { return &m_canvasStateHeap; } + + RTree::RTree m_tree; + int m_nodeCount; + +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 clearCanvasStates() { + for (size_t i = 0; i < m_canvasStates.size(); i++) + m_canvasStates[i]->~CanvasState(); + m_canvasStates.clear(); + } + + // TODO: Use a global pool? + StateHashSet m_states; + 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) { + SkRegion coveredArea(bounds); + + drawWithClipRecursive(static_cast<int>(m_nodes.size()) - 1, coveredArea); + + while (m_currState) { + m_currState->exitState(&m_context); + m_currState = m_currState->parent(); + } + } + +private: + void drawOperation(RecordingData* node, const SkRegion& covered) + { + 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 (!covered.isEmpty()) { + m_context.save(); + m_context.canvas()->clipRegion(covered, SkRegion::kIntersect_Op); + } + op->apply(&(m_context)); + if (!covered.isEmpty()) + m_context.restore(); + } + + void drawWithClipRecursive(int index, const SkRegion& covered) + { + 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, covered); + } else { + SkRegion newCovered = covered; + SkRect mappedRect = *opaqueRect; + m_initialMatrix.mapRect(&mappedRect); + newCovered.op(enclosedIntRect(mappedRect), SkRegion::kDifference_Op); + if (!newCovered.isEmpty()) + drawWithClipRecursive(index - 1, newCovered); + } + } + drawOperation(recordingData, covered); + } + + 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 + ClippingPainter painter(recording(), context, canvas->getTotalMatrix(), nodes); + painter.draw(canvas->getTotalClip().getBounds()); +#else + 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(); + } +#endif + 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) { + if (mRecording) + mRecording->setRecording(new RecordingImpl()); + mMatrixStack.append(SkMatrix::I()); + mCurrentMatrix = &(mMatrixStack.last()); + pushStateOperation(new (canvasStateHeap()) CanvasState(0)); } bool PlatformGraphicsContextRecording::isPaintingDisabled() { - return !mGraphicsOperationCollection; + return !mRecording; } SkCanvas* PlatformGraphicsContextRecording::recordingCanvas() { - SkSafeUnref(mPicture); - mPicture = new SkPicture(); - return mPicture->beginRecording(0, 0, 0); + m_hasText = true; + return &m_canvasProxy; } -void PlatformGraphicsContextRecording::endRecording(int type) -{ - if (!mPicture) - return; - mPicture->endRecording(); - GraphicsOperation::DrawComplexText* text = new GraphicsOperation::DrawComplexText(mPicture); - mGraphicsOperationCollection->append(text); - mPicture = 0; -} - - //************************************** // State management //************************************** void PlatformGraphicsContextRecording::beginTransparencyLayer(float opacity) { - mGraphicsOperationCollection->append(new GraphicsOperation::BeginTransparencyLayer(opacity)); + CanvasState* parent = mRecordingStateStack.last().mCanvasState; + pushStateOperation(new (canvasStateHeap()) CanvasState(parent, opacity)); } 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 (canvasStateHeap()) CanvasState(parent)); + pushMatrix(); } void PlatformGraphicsContextRecording::restore() { PlatformGraphicsContext::restore(); - mGraphicsOperationCollection->append(new GraphicsOperation::Restore()); + popMatrix(); + popStateOperation(); } //************************************** @@ -79,86 +503,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 +603,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 +638,65 @@ const SkMatrix& PlatformGraphicsContextRecording::getTotalMatrix() void PlatformGraphicsContextRecording::addInnerRoundedRectClip(const IntRect& rect, int thickness) { - mGraphicsOperationCollection->append(new GraphicsOperation::InnerRoundedRectClip(rect, thickness)); + mRecordingStateStack.last().setHasComplexClip(); + appendStateOperation(NEW_OP(InnerRoundedRectClip)(rect, thickness)); } void PlatformGraphicsContextRecording::canvasClip(const Path& path) { + mRecordingStateStack.last().setHasComplexClip(); 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().setHasComplexClip(); + 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().setHasComplexClip(); + 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().setHasComplexClip(); + 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().setHasComplexClip(); + 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 +707,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 +773,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 +821,186 @@ 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* text, size_t byteLength, + const SkPoint pos[], const SkPaint& paint) +{ + if (paint.getTextEncoding() != SkPaint::kGlyphID_TextEncoding) { + ALOGE("Unsupported text encoding! %d", paint.getTextEncoding()); + } + FloatRect bounds = approximateTextBounds(byteLength / sizeof(uint16_t), pos, paint); + 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("pushStateOperation: %p(isLayer=%d)", canvasState, canvasState->isTransparencyLayer()); + mRecordingStateStack.append(canvasState); + mRecording->recording()->addCanvasState(canvasState); +} + +void PlatformGraphicsContextRecording::popStateOperation() +{ + RecordingState state = mRecordingStateStack.last(); + mRecordingStateStack.removeLast(); + if (!state.mHasDrawing) { + ALOGV("popStateOperation is deleting %p(isLayer=%d)", + state.mCanvasState, state.mCanvasState->isTransparencyLayer()); + mRecording->recording()->removeCanvasState(state.mCanvasState); + state.mCanvasState->~CanvasState(); + canvasStateHeap()->rewindTo(state.mCanvasState); + } else { + ALOGV("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) +{ + 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("Operation %s() was clipped out", operation->name()); + operation->~Operation(); + operationHeap()->rewindTo(operation); + return; + } + if (operation->isOpaque() + && !untranslatedBounds.isEmpty() + && operation->m_state->alpha == 1.0f + && mCurrentMatrix->rectStaysRect() + && !state.mHasComplexClip) { + // if the operation maps to an opaque rect, record the area it will cover + operation->setOpaqueRect(calculateCoveredBounds(untranslatedBounds)); + } + ALOGV("appendOperation %p->%s() bounds " INT_RECT_FORMAT, operation, operation->name(), + INT_RECT_ARGS(ibounds)); + RecordingData* data = new RecordingData(operation, mRecording->recording()->m_nodeCount++); + mRecording->recording()->m_tree.insert(ibounds, data); +} + +void PlatformGraphicsContextRecording::appendStateOperation(GraphicsOperation::Operation* operation) +{ + ALOGV("appendOperation %p->%s()", operation, operation->name()); + RecordingData* data = new RecordingData(operation, mRecording->recording()->m_nodeCount++); + mRecordingStateStack.last().mCanvasState->adoptAndAppend(data); } +LinearAllocator* PlatformGraphicsContextRecording::operationHeap() +{ + return mRecording->recording()->operationHeap(); +} + +LinearAllocator* PlatformGraphicsContextRecording::canvasStateHeap() +{ + return mRecording->recording()->canvasStateHeap(); +} } // WebCore diff --git a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.h b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.h index ebb0075..0461749 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); + 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* operationHeap(); + LinearAllocator* canvasStateHeap(); + SkPicture* mPicture; + SkMatrix* mCurrentMatrix; + + Recording* mRecording; + class RecordingState { + public: + RecordingState(CanvasState* state) + : mCanvasState(state) + , mHasDrawing(false) + , mHasClip(false) + , mHasComplexClip(false) + {} + + RecordingState(const RecordingState& other) + : mCanvasState(other.mCanvasState) + , mHasDrawing(other.mHasDrawing) + , mHasClip(other.mHasClip) + , mHasComplexClip(false) + , mBounds(other.mBounds) + {} + + void setHasComplexClip() { mHasComplexClip = true; } + + void clip(const FloatRect& rect) + { + if (mHasClip) + mBounds.intersect(rect); + else { + mBounds = rect; + mHasClip = true; + } + } + + CanvasState* mCanvasState; + bool mHasDrawing; + bool mHasClip; + bool mHasComplexClip; + 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..fa048b7 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/context/RTree.cpp @@ -0,0 +1,589 @@ +/* + * 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 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(int M) +{ + m_maxChildren = M; + m_listA = new ElementList(M); + m_listB = new ElementList(M); + m_allocator = new WebCore::LinearAllocator(sizeof(Node)); + m_root = Node::create(this); +} + +RTree::~RTree() +{ + delete m_listA; + delete m_listB; + deleteNode(m_root); + delete m_allocator; +} + +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; + delete m_payload; +} + +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..366e3d1 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/context/RTree.h @@ -0,0 +1,180 @@ +/* + * 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; +}; + +} // namespace WebCore + +namespace RTree { + +class ElementList; +class Node; + +class RTree { +public: + // M -- max number of children per node + RTree(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/android/GeolocationServiceBridge.h b/Source/WebCore/platform/graphics/android/context/RecordingContextCanvasProxy.cpp index 3997d65..838e450 100644 --- a/Source/WebCore/platform/android/GeolocationServiceBridge.h +++ b/Source/WebCore/platform/graphics/android/context/RecordingContextCanvasProxy.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,44 +23,46 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef GeolocationServiceBridge_h -#define GeolocationServiceBridge_h +#include "config.h" +#include "RecordingContextCanvasProxy.h" -#include "JNIUtility.h" -#include <wtf/PassRefPtr.h> +#include "PlatformGraphicsContextRecording.h" namespace WebCore { -class Frame; -class GeolocationServiceAndroid; -class Geoposition; +// Return value is unused by FontAndroid +int RecordingContextCanvasProxy::save(SaveFlags) +{ + m_pgc->save(); + return -1; +} -// GeolocationServiceBridge is the bridge to the Java implementation. It manages -// the lifetime of the Java object. It is an implementation detail of -// GeolocationServiceAndroid. -class GeolocationServiceBridge { -public: - typedef GeolocationServiceAndroid ListenerInterface; - GeolocationServiceBridge(ListenerInterface* listener, Frame* frame); - ~GeolocationServiceBridge(); +void RecordingContextCanvasProxy::restore() +{ + m_pgc->restore(); +} - bool start(); - void stop(); - void setEnableGps(bool enable); +void RecordingContextCanvasProxy::drawPosText(const void* text, + size_t byteLength, + const SkPoint pos[], + const SkPaint& paint) +{ + m_pgc->drawPosText(text, byteLength, pos, paint); +} - // 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); +void RecordingContextCanvasProxy::drawBitmapRect(const SkBitmap& bitmap, + const SkIRect* src, + const SkRect& dst, + const SkPaint*) +{ + m_pgc->drawBitmapRect(bitmap, src, dst); +} -private: - void startJavaImplementation(Frame* frame); - void stopJavaImplementation(); +// Return value is unused by FontAndroid +bool RecordingContextCanvasProxy::rotate(SkScalar degrees) +{ + m_pgc->rotate(degrees / (180.0f / 3.14159265f)); + return true; +} - ListenerInterface* m_listener; - jobject m_javaGeolocationServiceObject; -}; - -} // namespace WebCore - -#endif // GeolocationServiceBridge_h +} // 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/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..438d96c 100644 --- a/Source/WebCore/platform/graphics/android/layers/LayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/layers/LayerAndroid.cpp @@ -601,7 +601,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" : "", @@ -954,60 +954,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..b28daef 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: @@ -195,9 +196,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 +291,7 @@ public: } protected: + virtual void dumpLayer(LayerDumper*) const; /** Call this with the current viewport (scrolling, zoom) to update the position of the fixed layers. 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/InstrumentedPlatformCanvas.h b/Source/WebCore/platform/graphics/android/rendering/InstrumentedPlatformCanvas.h new file mode 100644 index 0000000..508795a --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/InstrumentedPlatformCanvas.h @@ -0,0 +1,305 @@ +/* + * 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 +#define WRAPCANVAS_LOG_ENTRY(...) do { \ + fprintf(stderr, "%s ", __FUNCTION__); \ + fprintf(stderr, __VA_ARGS__); \ + fprintf(stderr, "\n"); \ +} while (0) +#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(""); + 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); + } + + virtual void drawRect(const SkRect& rect, const SkPaint& paint) + { +#if DEBUG_SKIA_DRAWING + IntRect rectToDraw(rect); + WRAPCANVAS_LOG_ENTRY("rect = (x=%d,y=%d,width=%d,height=%d)", INT_RECT_ARGS(rectToDraw); +#endif + IntRect canvasRect(IntPoint(), m_size); + if (m_isSolidColor + && getTotalMatrix().rectStaysRect() + && getTotalClip().contains(canvasRect)) { + const SkMatrix& matrix = getTotalMatrix(); + SkRect mapped; + matrix.mapRect(&mapped, rect); + if (mapped.contains(canvasRect)) { + Color color = solidColor(paint); + m_isSolidColor = color.isValid(); + m_solidColor = color; + } else + m_isSolidColor = false; + } 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..b59b6e2 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) @@ -321,6 +331,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 +340,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 +352,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 +364,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 +378,7 @@ void ShaderProgram::initGLResources() repeatTexInvProjMtx, -1, repeatTexInvTexSampler, -1, repeatTexInvFillPortion, repeatTexInvScale); + initProgram(RepeatTexInv); GLint texOESAlpha = glGetUniformLocation(texOESProgram, "alpha"); GLint texOESPosition = glGetAttribLocation(texOESProgram, "vPosition"); @@ -372,6 +387,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 +399,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 +408,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 +557,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 +723,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 +758,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 +856,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 +878,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/SurfaceCollectionManager.cpp b/Source/WebCore/platform/graphics/android/rendering/SurfaceCollectionManager.cpp index 174720f..1270498 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,12 +246,12 @@ 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); @@ -261,6 +282,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 +310,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..e584b81 100644 --- a/Source/WebCore/platform/graphics/android/rendering/TilesManager.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/TilesManager.cpp @@ -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() @@ -105,10 +109,21 @@ TilesManager::TilesManager() 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_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..1899557 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/utils/LinearAllocator.cpp @@ -0,0 +1,180 @@ +/* + * 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 +#define TARGET_PAGE_SIZE 16384 // 16kb + +// our pool needs to big enough to hold at least this many items +#define MIN_OBJECT_COUNT 4 + +#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(size_t averageAllocSize) + : m_next(0) + , m_currentPage(0) + , m_pages(0) +{ + if (averageAllocSize) { + int usable_page_size = TARGET_PAGE_SIZE - sizeof(LinearAllocator::Page); + int pcount = usable_page_size / averageAllocSize; + if (pcount < MIN_OBJECT_COUNT) + pcount = MIN_OBJECT_COUNT; + m_pageSize = pcount * averageAllocSize + sizeof(LinearAllocator::Page); + } else + m_pageSize = TARGET_PAGE_SIZE; + m_maxAllocSize = (m_pageSize - sizeof(LinearAllocator::Page)); +} + +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; +} + +void LinearAllocator::ensureNext(size_t size) +{ + if (m_next && ((char*)m_next + size) <= end(m_currentPage)) + return; + Page* p = newPage(); + if (m_currentPage) + m_currentPage->setNext(p); + m_currentPage = p; + if (!m_pages) + m_pages = m_currentPage; + m_next = start(m_currentPage); +} + +unsigned LinearAllocator::memusage() +{ + unsigned memusage = 0; + Page* p = m_pages; + while (p) { + memusage += m_pageSize; + p = p->next(); + } + return memusage; +} + +void* LinearAllocator::alloc(size_t size) +{ + if (size > m_maxAllocSize) { + ALOGE("Allocation too large! (%d exceeds max size %d)", size, m_maxAllocSize); + return 0; + } + ensureNext(size); + void* ptr = m_next; + m_next = ((char*)m_next) + size; + return ptr; +} + +void LinearAllocator::rewindTo(void* ptr) +{ + // Don't bother rewinding across pages + if (ptr >= start(m_currentPage) && ptr < end(m_currentPage)) + m_next = ptr; +} + +LinearAllocator::Page* LinearAllocator::newPage() +{ + ADD_ALLOCATION(m_pageSize); + void* buf = malloc(m_pageSize); + return new (buf) Page(); +} + +} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/context/GraphicsOperationCollection.h b/Source/WebCore/platform/graphics/android/utils/LinearAllocator.h index 9d7b530..1f3265c 100644 --- a/Source/WebCore/platform/graphics/android/context/GraphicsOperationCollection.h +++ b/Source/WebCore/platform/graphics/android/utils/LinearAllocator.h @@ -23,50 +23,39 @@ * 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(size_t averageAllocSize = 0); + ~LinearAllocator(); - void apply(PlatformGraphicsContext* context); - void append(GraphicsOperation::Operation* operation); - - bool isEmpty(); + void* alloc(size_t size); + void rewindTo(void*); 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(); + void ensureNext(size_t size); + void* start(Page *p); + void* end(Page* p); -} + unsigned memusage(); + + size_t m_pageSize; + size_t m_maxAllocSize; + void* m_next; + Page* m_currentPage; + Page* m_pages; +}; -#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(); } |