summaryrefslogtreecommitdiffstats
path: root/WebKit/android
diff options
context:
space:
mode:
Diffstat (limited to 'WebKit/android')
-rw-r--r--WebKit/android/WebCoreSupport/CachedFramePlatformDataAndroid.h2
-rw-r--r--WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp34
-rw-r--r--WebKit/android/WebCoreSupport/ChromeClientAndroid.h2
-rw-r--r--WebKit/android/WebCoreSupport/PlatformBridge.cpp20
-rw-r--r--WebKit/android/jni/WebCoreFrameBridge.cpp91
-rw-r--r--WebKit/android/jni/WebViewCore.cpp177
-rw-r--r--WebKit/android/jni/WebViewCore.h20
-rw-r--r--WebKit/android/nav/SelectText.cpp403
-rw-r--r--WebKit/android/nav/SelectText.h3
-rw-r--r--WebKit/android/nav/WebView.cpp163
10 files changed, 545 insertions, 370 deletions
diff --git a/WebKit/android/WebCoreSupport/CachedFramePlatformDataAndroid.h b/WebKit/android/WebCoreSupport/CachedFramePlatformDataAndroid.h
index ac22d05..20c7be4 100644
--- a/WebKit/android/WebCoreSupport/CachedFramePlatformDataAndroid.h
+++ b/WebKit/android/WebCoreSupport/CachedFramePlatformDataAndroid.h
@@ -60,4 +60,4 @@ private:
}
-#endif \ No newline at end of file
+#endif
diff --git a/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp b/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp
index 7a18221..30ac36c 100644
--- a/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp
+++ b/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp
@@ -56,27 +56,14 @@ static unsigned long long tryToReclaimDatabaseQuota(SecurityOrigin* originNeedin
#if USE(ACCELERATED_COMPOSITING)
-void ChromeClientAndroid::layersSync()
+WebCore::GraphicsLayer* ChromeClientAndroid::layersSync()
{
- if (!m_rootGraphicsLayer)
- return;
-
- if (!m_needsLayerSync)
- return;
-
- m_needsLayerSync = false;
-
- if (m_webFrame) {
- FrameView* frameView = m_webFrame->page()->mainFrame()->view();
- if (frameView && frameView->syncCompositingStateRecursive()) {
- GraphicsLayerAndroid* androidGraphicsLayer =
- static_cast<GraphicsLayerAndroid*>(m_rootGraphicsLayer);
- if (androidGraphicsLayer) {
- androidGraphicsLayer->sendImmediateRepaint();
- androidGraphicsLayer->notifyClientAnimationStarted();
- }
- }
+ if (m_rootGraphicsLayer && m_needsLayerSync && m_webFrame) {
+ if (FrameView* frameView = m_webFrame->page()->mainFrame()->view())
+ frameView->syncCompositingStateRecursive();
}
+ m_needsLayerSync = false;
+ return m_rootGraphicsLayer;
}
void ChromeClientAndroid::scheduleCompositingLayerSync()
@@ -89,15 +76,12 @@ void ChromeClientAndroid::setNeedsOneShotDrawingSynchronization()
// This should not be needed
}
-void ChromeClientAndroid::attachRootGraphicsLayer(WebCore::Frame* frame, WebCore::GraphicsLayer* layer)
+void ChromeClientAndroid::attachRootGraphicsLayer(WebCore::Frame*, WebCore::GraphicsLayer* layer)
{
+ // frame is not used in Android as we should only get root graphics layer for the main frame
m_rootGraphicsLayer = layer;
- if (!layer) {
- WebViewCore::getWebViewCore(frame->view())->setUIRootLayer(0);
+ if (!layer)
return;
- }
- WebCore::GraphicsLayerAndroid* androidGraphicsLayer = static_cast<GraphicsLayerAndroid*>(layer);
- androidGraphicsLayer->setFrame(frame);
scheduleCompositingLayerSync();
}
diff --git a/WebKit/android/WebCoreSupport/ChromeClientAndroid.h b/WebKit/android/WebCoreSupport/ChromeClientAndroid.h
index 517a439..a1f097c 100644
--- a/WebKit/android/WebCoreSupport/ChromeClientAndroid.h
+++ b/WebKit/android/WebCoreSupport/ChromeClientAndroid.h
@@ -169,7 +169,7 @@ namespace android {
virtual void attachRootGraphicsLayer(WebCore::Frame*, WebCore::GraphicsLayer* g);
virtual void setNeedsOneShotDrawingSynchronization();
virtual void scheduleCompositingLayerSync();
- void layersSync();
+ WebCore::GraphicsLayer* layersSync();
#endif
#if ENABLE(ANDROID_INSTALLABLE_WEB_APPS)
diff --git a/WebKit/android/WebCoreSupport/PlatformBridge.cpp b/WebKit/android/WebCoreSupport/PlatformBridge.cpp
index b75cdfc..833deb5 100644
--- a/WebKit/android/WebCoreSupport/PlatformBridge.cpp
+++ b/WebKit/android/WebCoreSupport/PlatformBridge.cpp
@@ -38,30 +38,10 @@
#include <wtf/android/AndroidThreading.h>
#include <wtf/MainThread.h>
-#if USE(ACCELERATED_COMPOSITING)
-#include "LayerAndroid.h"
-#endif
-
using namespace android;
namespace WebCore {
-#if USE(ACCELERATED_COMPOSITING)
-
-void PlatformBridge::setUIRootLayer(const WebCore::FrameView* view, const LayerAndroid* layer)
-{
- android::WebViewCore* core = android::WebViewCore::getWebViewCore(view);
- core->setUIRootLayer(layer);
-}
-
-void PlatformBridge::immediateRepaint(const WebCore::FrameView* view)
-{
- android::WebViewCore* core = android::WebViewCore::getWebViewCore(view);
- core->immediateRepaint();
-}
-
-#endif // USE(ACCELERATED_COMPOSITING)
-
WTF::Vector<String> PlatformBridge::getSupportedKeyStrengthList()
{
KeyGeneratorClient* client = JavaSharedClient::GetKeyGeneratorClient();
diff --git a/WebKit/android/jni/WebCoreFrameBridge.cpp b/WebKit/android/jni/WebCoreFrameBridge.cpp
index 87ee07b..bfd4b62 100644
--- a/WebKit/android/jni/WebCoreFrameBridge.cpp
+++ b/WebKit/android/jni/WebCoreFrameBridge.cpp
@@ -112,6 +112,10 @@
#include "TimeCounter.h"
#endif
+#if ENABLE(ARCHIVE)
+#include "WebArchiveAndroid.h"
+#endif
+
using namespace JSC::Bindings;
static String* gUploadFileLabel;
@@ -1095,6 +1099,91 @@ static void StopLoading(JNIEnv *env, jobject obj)
pFrame->loader()->stopForUserCancel();
}
+#if ENABLE(ARCHIVE)
+static String saveArchiveAutoname(String basename, String name, String extension) {
+ if (name.isNull() || name.isEmpty()) {
+ name = String("index");
+ }
+
+ String testname = basename;
+ testname.append(name);
+ testname.append(extension);
+
+ errno = 0;
+ struct stat permissions;
+ if (stat(testname.utf8().data(), &permissions) < 0) {
+ if (errno == ENOENT)
+ return testname;
+ return String();
+ }
+
+ const int maxAttempts = 100;
+ for (int i = 1; i < maxAttempts; i++) {
+ String testname = basename;
+ testname.append(name);
+ testname.append("-");
+ testname.append(String::number(i));
+ testname.append(extension);
+
+ errno = 0;
+ if (stat(testname.utf8().data(), &permissions) < 0) {
+ if (errno == ENOENT)
+ return testname;
+ return String();
+ }
+ }
+
+ return String();
+}
+#endif
+
+static jobject SaveWebArchive(JNIEnv *env, jobject obj, jstring basename, jboolean autoname)
+{
+#if ENABLE(ARCHIVE)
+ WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
+ LOG_ASSERT(pFrame, "nativeSaveWebArchive must take a valid frame pointer!");
+
+ const char* basenameNative = getCharactersFromJStringInEnv(env, basename);
+ String basenameString = String::fromUTF8(basenameNative);
+ String filename;
+
+ if (autoname) {
+ String name = pFrame->loader()->documentLoader()->originalURL().lastPathComponent();
+ String extension = String(".webarchivexml");
+ filename = saveArchiveAutoname(basenameString, name, extension);
+ } else {
+ filename = basenameString;
+ }
+
+ if (filename.isNull() || filename.isEmpty()) {
+ LOGD("saveWebArchive: Failed to select a filename to save.");
+ releaseCharactersForJStringInEnv(env, basename, basenameNative);
+ return JNI_FALSE;
+ }
+
+ const int noCompression = 0;
+ xmlTextWriterPtr writer = xmlNewTextWriterFilename(filename.utf8().data(), noCompression);
+ if (writer == NULL) {
+ LOGD("saveWebArchive: Failed to initialize xml writer.");
+ releaseCharactersForJStringInEnv(env, basename, basenameNative);
+ return JNI_FALSE;
+ }
+
+ RefPtr<WebArchiveAndroid> archive = WebCore::WebArchiveAndroid::create(pFrame);
+
+ bool result = archive->saveWebArchive(writer);
+
+ releaseCharactersForJStringInEnv(env, basename, basenameNative);
+ xmlFreeTextWriter(writer);
+
+ if (result) {
+ return env->NewStringUTF(filename.utf8().data());
+ }
+
+ return NULL;
+#endif
+}
+
static jstring ExternalRepresentation(JNIEnv *env, jobject obj)
{
#ifdef ANDROID_INSTRUMENT
@@ -1640,6 +1729,8 @@ static JNINativeMethod gBrowserFrameNativeMethods[] = {
(void*) PostUrl },
{ "nativeLoadData", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V",
(void*) LoadData },
+ { "nativeSaveWebArchive", "(Ljava/lang/String;Z)Ljava/lang/String;",
+ (void*) SaveWebArchive },
{ "externalRepresentation", "()Ljava/lang/String;",
(void*) ExternalRepresentation },
{ "documentAsText", "()Ljava/lang/String;",
diff --git a/WebKit/android/jni/WebViewCore.cpp b/WebKit/android/jni/WebViewCore.cpp
index 955b654..daca51e 100644
--- a/WebKit/android/jni/WebViewCore.cpp
+++ b/WebKit/android/jni/WebViewCore.cpp
@@ -29,6 +29,7 @@
#include "WebViewCore.h"
#include "AtomicString.h"
+#include "BaseLayerAndroid.h"
#include "CachedNode.h"
#include "CachedRoot.h"
#include "Chrome.h"
@@ -230,8 +231,6 @@ struct WebViewCore::JavaGlue {
jmethodID m_updateViewport;
jmethodID m_sendNotifyProgressFinished;
jmethodID m_sendViewInvalidate;
- jmethodID m_sendImmediateRepaint;
- jmethodID m_setRootLayer;
jmethodID m_updateTextfield;
jmethodID m_updateTextSelection;
jmethodID m_clearTextEntry;
@@ -276,7 +275,6 @@ static jmethodID GetJMethod(JNIEnv* env, jclass clazz, const char name[], const
Mutex WebViewCore::gFrameCacheMutex;
Mutex WebViewCore::gButtonMutex;
Mutex WebViewCore::gCursorBoundsMutex;
-Mutex WebViewCore::m_contentMutex;
WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* mainframe)
: m_pluginInvalTimer(this, &WebViewCore::pluginInvalTimerFired)
@@ -321,8 +319,6 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m
m_javaGlue->m_updateViewport = GetJMethod(env, clazz, "updateViewport", "()V");
m_javaGlue->m_sendNotifyProgressFinished = GetJMethod(env, clazz, "sendNotifyProgressFinished", "()V");
m_javaGlue->m_sendViewInvalidate = GetJMethod(env, clazz, "sendViewInvalidate", "(IIII)V");
- m_javaGlue->m_sendImmediateRepaint = GetJMethod(env, clazz, "sendImmediateRepaint", "()V");
- m_javaGlue->m_setRootLayer = GetJMethod(env, clazz, "setRootLayer", "(I)V");
m_javaGlue->m_updateTextfield = GetJMethod(env, clazz, "updateTextfield", "(IZLjava/lang/String;I)V");
m_javaGlue->m_updateTextSelection = GetJMethod(env, clazz, "updateTextSelection", "(IIII)V");
m_javaGlue->m_clearTextEntry = GetJMethod(env, clazz, "clearTextEntry", "()V");
@@ -749,50 +745,11 @@ void WebViewCore::updateCursorBounds(const CachedRoot* root,
void WebViewCore::clearContent()
{
DBG_SET_LOG("");
- m_contentMutex.lock();
m_content.clear();
- m_contentMutex.unlock();
m_addInval.setEmpty();
m_rebuildInval.setEmpty();
}
-void WebViewCore::copyContentToPicture(SkPicture* picture)
-{
- DBG_SET_LOG("start");
- m_contentMutex.lock();
- PictureSet copyContent = PictureSet(m_content);
- m_contentMutex.unlock();
-
- int w = copyContent.width();
- int h = copyContent.height();
- copyContent.draw(picture->beginRecording(w, h, PICT_RECORD_FLAGS));
- picture->endRecording();
- DBG_SET_LOG("end");
-}
-
-bool WebViewCore::drawContent(SkCanvas* canvas, SkColor color)
-{
-#ifdef ANDROID_INSTRUMENT
- TimeCounterAuto counter(TimeCounter::WebViewUIDrawTimeCounter);
-#endif
- DBG_SET_LOG("start");
- m_contentMutex.lock();
- PictureSet copyContent = PictureSet(m_content);
- m_contentMutex.unlock();
- int sc = canvas->save(SkCanvas::kClip_SaveFlag);
- SkRect clip;
- clip.set(0, 0, copyContent.width(), copyContent.height());
- canvas->clipRect(clip, SkRegion::kDifference_Op);
- canvas->drawColor(color);
- canvas->restoreToCount(sc);
- bool tookTooLong = copyContent.draw(canvas);
- m_contentMutex.lock();
- m_content.setDrawTimes(copyContent);
- m_contentMutex.unlock();
- DBG_SET_LOG("end");
- return tookTooLong;
-}
-
bool WebViewCore::focusBoundsChanged()
{
bool result = m_focusBoundsChanged;
@@ -800,18 +757,6 @@ bool WebViewCore::focusBoundsChanged()
return result;
}
-bool WebViewCore::pictureReady()
-{
- bool done;
- m_contentMutex.lock();
- PictureSet copyContent = PictureSet(m_content);
- done = m_progressDone;
- m_contentMutex.unlock();
- DBG_NAV_LOGD("done=%s empty=%s", done ? "true" : "false",
- copyContent.isEmpty() ? "true" : "false");
- return done || !copyContent.isEmpty();
-}
-
SkPicture* WebViewCore::rebuildPicture(const SkIRect& inval)
{
WebCore::FrameView* view = m_mainFrame->view();
@@ -859,54 +804,52 @@ void WebViewCore::rebuildPictureSet(PictureSet* pictureSet)
pictureSet->validate(__FUNCTION__);
}
-bool WebViewCore::recordContent(SkRegion* region, SkIPoint* point)
+BaseLayerAndroid* WebViewCore::recordContent(SkRegion* region, SkIPoint* point)
{
DBG_SET_LOG("start");
float progress = (float) m_mainFrame->page()->progress()->estimatedProgress();
- m_contentMutex.lock();
- PictureSet contentCopy(m_content);
m_progressDone = progress <= 0.0f || progress >= 1.0f;
- m_contentMutex.unlock();
- recordPictureSet(&contentCopy);
- if (!m_progressDone && contentCopy.isEmpty()) {
+ recordPictureSet(&m_content);
+ if (!m_progressDone && m_content.isEmpty()) {
DBG_SET_LOGD("empty (progress=%g)", progress);
- return false;
+ return 0;
}
region->set(m_addInval);
m_addInval.setEmpty();
region->op(m_rebuildInval, SkRegion::kUnion_Op);
m_rebuildInval.setEmpty();
- m_contentMutex.lock();
- contentCopy.setDrawTimes(m_content);
- m_content.set(contentCopy);
point->fX = m_content.width();
point->fY = m_content.height();
- m_contentMutex.unlock();
DBG_SET_LOGD("region={%d,%d,r=%d,b=%d}", region->getBounds().fLeft,
region->getBounds().fTop, region->getBounds().fRight,
region->getBounds().fBottom);
DBG_SET_LOG("end");
+ BaseLayerAndroid* base = new BaseLayerAndroid();
+ base->setContent(m_content);
+
#if USE(ACCELERATED_COMPOSITING)
// We update the layers
ChromeClientAndroid* chromeC = static_cast<ChromeClientAndroid*>(m_mainFrame->page()->chrome()->client());
- chromeC->layersSync();
+ GraphicsLayerAndroid* root = static_cast<GraphicsLayerAndroid*>(chromeC->layersSync());
+ if (root) {
+ root->notifyClientAnimationStarted();
+ LayerAndroid* copyLayer = new LayerAndroid(*root->contentLayer());
+ base->addChild(copyLayer);
+ copyLayer->unref();
+ }
#endif
- return true;
+
+ return base;
}
-void WebViewCore::splitContent()
+void WebViewCore::splitContent(PictureSet* content)
{
bool layoutSuceeded = layoutIfNeededRecursive(m_mainFrame);
LOG_ASSERT(layoutSuceeded, "Can never be called recursively");
- PictureSet tempPictureSet;
- m_contentMutex.lock();
- m_content.split(&tempPictureSet);
- m_contentMutex.unlock();
- rebuildPictureSet(&tempPictureSet);
- m_contentMutex.lock();
- m_content.set(tempPictureSet);
- m_contentMutex.unlock();
+ content->split(&m_content);
+ rebuildPictureSet(&m_content);
+ content->set(m_content);
}
void WebViewCore::scrollTo(int x, int y, bool animate)
@@ -950,28 +893,6 @@ void WebViewCore::scrollBy(int dx, int dy, bool animate)
checkException(env);
}
-#if USE(ACCELERATED_COMPOSITING)
-
-void WebViewCore::immediateRepaint()
-{
- LOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");
- JNIEnv* env = JSC::Bindings::getJNIEnv();
- env->CallVoidMethod(m_javaGlue->object(env).get(),
- m_javaGlue->m_sendImmediateRepaint);
- checkException(env);
-}
-
-void WebViewCore::setUIRootLayer(const LayerAndroid* layer)
-{
- JNIEnv* env = JSC::Bindings::getJNIEnv();
- env->CallVoidMethod(m_javaGlue->object(env).get(),
- m_javaGlue->m_setRootLayer,
- reinterpret_cast<jint>(layer));
- checkException(env);
-}
-
-#endif // USE(ACCELERATED_COMPOSITING)
-
void WebViewCore::contentDraw()
{
JNIEnv* env = JSC::Bindings::getJNIEnv();
@@ -3058,7 +2979,7 @@ void WebViewCore::addVisitedLink(const UChar* string, int length)
m_groupForVisitedLinks->addVisitedLink(string, length);
}
-static bool RecordContent(JNIEnv *env, jobject obj, jobject region, jobject pt)
+static jint RecordContent(JNIEnv *env, jobject obj, jobject region, jobject pt)
{
#ifdef ANDROID_INSTRUMENT
TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
@@ -3066,18 +2987,18 @@ static bool RecordContent(JNIEnv *env, jobject obj, jobject region, jobject pt)
WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
SkRegion* nativeRegion = GraphicsJNI::getNativeRegion(env, region);
SkIPoint nativePt;
- bool result = viewImpl->recordContent(nativeRegion, &nativePt);
+ BaseLayerAndroid* result = viewImpl->recordContent(nativeRegion, &nativePt);
GraphicsJNI::ipoint_to_jpoint(nativePt, env, pt);
- return result;
+ return reinterpret_cast<jint>(result);
}
-static void SplitContent(JNIEnv *env, jobject obj)
+static void SplitContent(JNIEnv *env, jobject obj, jint content)
{
#ifdef ANDROID_INSTRUMENT
TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
#endif
WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
- viewImpl->splitContent();
+ viewImpl->splitContent(reinterpret_cast<PictureSet*>(content));
}
static void SendListBoxChoice(JNIEnv* env, jobject obj, jint choice)
@@ -3366,45 +3287,11 @@ static void RegisterURLSchemeAsLocal(JNIEnv* env, jobject obj, jstring scheme) {
WebCore::SecurityOrigin::registerURLSchemeAsLocal(to_string(env, scheme));
}
-static void ClearContent(JNIEnv *env, jobject obj)
-{
-#ifdef ANDROID_INSTRUMENT
- TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
-#endif
- WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
- viewImpl->clearContent();
-}
-
-static void CopyContentToPicture(JNIEnv *env, jobject obj, jobject pict)
-{
-#ifdef ANDROID_INSTRUMENT
- TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
-#endif
- WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
- if (!viewImpl)
- return;
- SkPicture* picture = GraphicsJNI::getNativePicture(env, pict);
- viewImpl->copyContentToPicture(picture);
-}
-
-static bool DrawContent(JNIEnv *env, jobject obj, jobject canv, jint color)
-{
- // Note: this is called from UI thread, don't count it for WebViewCoreTimeCounter
- WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
- SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, canv);
- return viewImpl->drawContent(canvas, color);
-}
-
static bool FocusBoundsChanged(JNIEnv* env, jobject obj)
{
return GET_NATIVE_VIEW(env, obj)->focusBoundsChanged();
}
-static bool PictureReady(JNIEnv* env, jobject obj)
-{
- return GET_NATIVE_VIEW(env, obj)->pictureReady();
-}
-
static void Pause(JNIEnv* env, jobject obj)
{
// This is called for the foreground tab when the browser is put to the
@@ -3541,20 +3428,12 @@ static jobject GetTouchHighlightRects(JNIEnv* env, jobject obj, jint x, jint y,
* JNI registration.
*/
static JNINativeMethod gJavaWebViewCoreMethods[] = {
- { "nativeClearContent", "()V",
- (void*) ClearContent },
- { "nativeCopyContentToPicture", "(Landroid/graphics/Picture;)V",
- (void*) CopyContentToPicture },
- { "nativeDrawContent", "(Landroid/graphics/Canvas;I)Z",
- (void*) DrawContent } ,
{ "nativeFocusBoundsChanged", "()Z",
(void*) FocusBoundsChanged } ,
{ "nativeKey", "(IIIZZZZ)Z",
(void*) Key },
{ "nativeClick", "(II)V",
(void*) Click },
- { "nativePictureReady", "()Z",
- (void*) PictureReady } ,
{ "nativeSendListBoxChoices", "([ZI)V",
(void*) SendListBoxChoices },
{ "nativeSendListBoxChoice", "(I)V",
@@ -3601,11 +3480,11 @@ static JNINativeMethod gJavaWebViewCoreMethods[] = {
(void*) UpdateFrameCache },
{ "nativeGetContentMinPrefWidth", "()I",
(void*) GetContentMinPrefWidth },
- { "nativeRecordContent", "(Landroid/graphics/Region;Landroid/graphics/Point;)Z",
+ { "nativeRecordContent", "(Landroid/graphics/Region;Landroid/graphics/Point;)I",
(void*) RecordContent },
{ "setViewportSettingsFromNative", "()V",
(void*) SetViewportSettingsFromNative },
- { "nativeSplitContent", "()V",
+ { "nativeSplitContent", "(I)V",
(void*) SplitContent },
{ "nativeSetBackgroundColor", "(I)V",
(void*) SetBackgroundColor },
diff --git a/WebKit/android/jni/WebViewCore.h b/WebKit/android/jni/WebViewCore.h
index 42656d4..99f02e9 100644
--- a/WebKit/android/jni/WebViewCore.h
+++ b/WebKit/android/jni/WebViewCore.h
@@ -61,10 +61,13 @@ namespace WebCore {
#if USE(ACCELERATED_COMPOSITING)
namespace WebCore {
class GraphicsLayerAndroid;
- class LayerAndroid;
}
#endif
+namespace WebCore {
+ class BaseLayerAndroid;
+}
+
struct PluginWidgetAndroid;
class SkPicture;
class SkIRect;
@@ -137,8 +140,6 @@ namespace android {
#if USE(ACCELERATED_COMPOSITING)
GraphicsLayerAndroid* graphicsRootLayer() const;
- void immediateRepaint();
- void setUIRootLayer(const LayerAndroid* layer);
#endif
/** Invalidate the view/screen, NOT the content/DOM, but expressed in
@@ -449,16 +450,10 @@ namespace android {
// reset the picture set to empty
void clearContent();
- // flatten the picture set to a picture
- void copyContentToPicture(SkPicture* );
-
- // draw the picture set with the specified background color
- bool drawContent(SkCanvas* , SkColor );
bool focusBoundsChanged();
- bool pictureReady();
// record the inval area, and the picture size
- bool recordContent(SkRegion* , SkIPoint* );
+ BaseLayerAndroid* recordContent(SkRegion* , SkIPoint* );
int textWrapWidth() const { return m_textWrapWidth; }
float scale() const { return m_scale; }
float textWrapScale() const { return m_screenWidth * m_scale / m_textWrapWidth; }
@@ -468,7 +463,7 @@ namespace android {
void updateFrameCacheIfLoading();
// utility to split slow parts of the picture set
- void splitContent();
+ void splitContent(PictureSet*);
void notifyWebAppCanBeInstalled();
@@ -520,8 +515,7 @@ namespace android {
WebCore::IntRect m_lastFocusedBounds;
int m_lastFocusedSelStart;
int m_lastFocusedSelEnd;
- static Mutex m_contentMutex; // protects ui/core thread pictureset access
- PictureSet m_content; // the set of pictures to draw (accessed by UI too)
+ PictureSet m_content; // the set of pictures to draw
SkRegion m_addInval; // the accumulated inval region (not yet drawn)
SkRegion m_rebuildInval; // the accumulated region for rebuilt pictures
// Used in passToJS to avoid updating the UI text field until after the
diff --git a/WebKit/android/nav/SelectText.cpp b/WebKit/android/nav/SelectText.cpp
index 7d2aaa7..9df6ef5 100644
--- a/WebKit/android/nav/SelectText.cpp
+++ b/WebKit/android/nav/SelectText.cpp
@@ -236,7 +236,7 @@ public:
return isSpace(rec);
}
- void finish()
+ void finishGlyph()
{
mLastGlyph = mLastCandidate;
mLastUni = mLastUniCandidate;
@@ -400,8 +400,9 @@ public:
reset();
}
- const SkIRect& adjustedBounds(const SkIRect& area)
+ const SkIRect& adjustedBounds(const SkIRect& area, int* base)
{
+ *base = mBestBase + area.fTop;
mBestBounds.offset(area.fLeft, area.fTop);
DBG_NAV_LOGD("FirstCheck mBestBounds:(%d, %d, %d, %d) mTop=%d mBottom=%d",
mBestBounds.fLeft, mBestBounds.fTop, mBestBounds.fRight,
@@ -424,6 +425,7 @@ public:
DBG_NAV_LOGD("FirstCheck distance=%d mDistance=%d", distance, mDistance);
#endif
if (mDistance > distance) {
+ mBestBase = base();
mBestBounds.set(rect.fLeft, top(), rect.fRight, bottom());
if (distance < 100) {
DBG_NAV_LOGD("FirstCheck mBestBounds={%d,%d,r=%d,b=%d} distance=%d",
@@ -449,6 +451,7 @@ public:
}
protected:
+ int mBestBase;
SkIRect mBestBounds;
int mDistance;
int mFocusX;
@@ -475,8 +478,9 @@ public:
return !mLast.isSpace(mLastGlyph);
}
- const SkIRect& bestBounds()
+ const SkIRect& bestBounds(int* base)
{
+ *base = mBestBase;
return mBestBounds;
}
@@ -501,6 +505,7 @@ public:
}
recordGlyph(rec);
mDistance = distance;
+ mBestBase = base();
mBestBounds.set(rect.fLeft, top(), rect.fRight, bottom());
if (distance <= 100) {
DBG_NAV_LOGD("EdgeCheck mBestBounds={%d,%d,r=%d,b=%d} distance=%d",
@@ -535,19 +540,23 @@ public:
mBestBounds.set(width, height, width, height);
}
- const SkIRect& bestBounds()
+ const SkIRect& bestBounds(int* base)
{
+ *base = mBestBase;
return mBestBounds;
}
virtual bool onIRect(const SkIRect& rect)
{
- if (mBestBounds.isEmpty())
+ if (mBestBounds.isEmpty()) {
+ mBestBase = base();
mBestBounds.set(rect.fLeft, top(), rect.fRight, bottom());
+ }
return false;
}
protected:
+ int mBestBase;
SkIRect mBestBounds;
private:
typedef CommonCheck INHERITED;
@@ -563,6 +572,7 @@ public:
virtual bool onIRect(const SkIRect& rect)
{
+ mBestBase = base();
mBestBounds.set(rect.fLeft, top(), rect.fRight, bottom());
return false;
}
@@ -571,71 +581,197 @@ private:
typedef FindFirst INHERITED;
};
+static bool baseLinesAgree(const SkIRect& rectA, int baseA,
+ const SkIRect& rectB, int baseB)
+{
+ return (rectA.fTop < baseB && rectA.fBottom >= baseB)
+ || (rectB.fTop < baseA && rectB.fBottom >= baseA);
+}
+
class MultilineBuilder : public CommonCheck {
public:
- MultilineBuilder(const SkIRect& start, const SkIRect& end,
- const SkIRect& area, SkRegion* region)
+ MultilineBuilder(const SkIRect& start, int startBase, const SkIRect& end,
+ int endBase, const SkIRect& area, SkRegion* region)
: INHERITED(area.width(),area.height())
- , mStart(start)
+ , mCapture(false)
, mEnd(end)
+ , mEndBase(endBase)
+ , mFlipped(false)
, mSelectRegion(region)
- , mCapture(false)
+ , mStart(start)
+ , mStartBase(startBase)
{
+ mEnd.offset(-area.fLeft, -area.fTop);
+ mEndBase -= area.fTop;
mLast.setEmpty();
mLastBase = INT_MAX;
mStart.offset(-area.fLeft, -area.fTop);
- mEnd.offset(-area.fLeft, -area.fTop);
+ mStartBase -= area.fTop;
}
- virtual bool onIRect(const SkIRect& rect) {
- bool captureLast = false;
- if ((rect.fLeft == mStart.fLeft && rect.fRight == mStart.fRight &&
- top() == mStart.fTop && bottom() == mStart.fBottom) ||
- (rect.fLeft == mEnd.fLeft && rect.fRight == mEnd.fRight &&
- top() == mEnd.fTop && bottom() == mEnd.fBottom)) {
- captureLast = mCapture;
- mCapture ^= true;
+ void finish() {
+ if (!mFlipped || SkIRect::Intersects(mLast, mSelectRect)) {
+ if (VERBOSE_LOGGING) DBG_NAV_LOGD(" mLast=(%d,%d,r=%d,b=%d)",
+ mLast.fLeft, mLast.fTop, mLast.fRight, mLast.fBottom);
+ mSelectRegion->op(mLast, SkRegion::kUnion_Op);
}
- if (mCapture || captureLast) {
- SkIRect full;
- full.set(rect.fLeft, top(), rect.fRight, bottom());
- if ((mLast.fTop < base() && mLast.fBottom >= base())
- || (mLastBase <= full.fBottom && mLastBase > full.fTop)) {
- if (full.fLeft > mLast.fRight)
- full.fLeft = mLast.fRight;
- else if (full.fRight < mLast.fLeft)
- full.fRight = mLast.fLeft;
+ }
+
+ // return true if capture end was not found after capture begin
+ bool flipped() {
+ DBG_NAV_LOGD("flipped=%s", mCapture ? "true" : "false");
+ if (!mCapture)
+ return false;
+ mFlipped = true;
+ mSelectRect = mStart;
+ mSelectRect.join(mEnd);
+ mLast.setEmpty();
+ mLastBase = INT_MAX;
+ mSelectRegion->setEmpty();
+ return true;
+ }
+
+ virtual bool onIRect(const SkIRect& rect) {
+ SkIRect full;
+ full.set(rect.fLeft, top(), rect.fRight, bottom());
+ int fullBase = base();
+ if (mFlipped) {
+ if (fullBase < mStart.fTop || fullBase > mEnd.fBottom
+ || (baseLinesAgree(mStart, mStartBase, full, fullBase)
+ && full.fLeft < mStart.fLeft)
+ || (baseLinesAgree(mEnd, mEndBase, full, fullBase)
+ && full.fRight > mEnd.fRight)) {
+ return false;
+ }
+ if (baseLinesAgree(mLast, mLastBase, full, fullBase)
+ && (full.fLeft - mLast.fRight < minSpaceWidth() * 3
+ || (SkIRect::Intersects(full, mSelectRect)
+ && SkIRect::Intersects(mLast, mSelectRect)))) {
+ mLast.join(full);
+ return false;
}
- mSelectRegion->op(full, SkRegion::kUnion_Op);
- if (VERBOSE_LOGGING) DBG_NAV_LOGD("MultilineBuilder full=(%d,%d,r=%d,b=%d)",
- full.fLeft, full.fTop, full.fRight, full.fBottom);
+ finish();
mLast = full;
- mLastBase = base();
- if (mStart == mEnd)
- mCapture = false;
+ mLastBase = fullBase;
+ return false;
}
+ if (full == mStart)
+ mCapture = true;
+ if (mCapture) {
+ if (baseLinesAgree(mLast, mLastBase, full, fullBase))
+ mLast.join(full);
+ else {
+ finish();
+ mLast = full;
+ mLastBase = fullBase;
+ }
+ }
+ if (full == mEnd)
+ mCapture = false;
return false;
}
-protected:
- SkIRect mStart;
+
+protected:
+ bool mCapture;
SkIRect mEnd;
+ int mEndBase;
+ bool mFlipped;
SkIRect mLast;
int mLastBase;
+ SkIRect mSelectRect;
SkRegion* mSelectRegion;
- bool mCapture;
+ SkIRect mStart;
+ int mStartBase;
private:
typedef CommonCheck INHERITED;
};
+static inline bool compareBounds(const SkIRect* first, const SkIRect* second)
+{
+ return first->fTop < second->fTop;
+}
+
class TextExtractor : public CommonCheck {
public:
- TextExtractor(const SkIRect& start, const SkIRect& end, const SkIRect& area)
+ TextExtractor(const SkIRect& start, int startBase, const SkIRect& end,
+ int endBase, const SkIRect& area, bool flipped)
: INHERITED(area.width(), area.height())
+ , mEnd(end)
+ , mEndBase(endBase)
+ , mFlipped(flipped)
, mRecord(false)
- , mSelectEnd(end)
- , mSelectStart(start)
+ , mSelectRect(start)
, mSkipFirstSpace(true) // don't start with a space
+ , mStart(start)
+ , mStartBase(startBase)
{
+ mEmpty.setEmpty();
+ mEnd.offset(-area.fLeft, -area.fTop);
+ mEndBase -= area.fTop;
+ mLast.setEmpty();
+ mLastBase = INT_MAX;
+ mSelectRect.join(end);
+ mSelectRect.offset(-area.fLeft, -area.fTop);
+ mStart.offset(-area.fLeft, -area.fTop);
+ mStartBase -= area.fTop;
+ }
+
+ void addCharacter(const SkBounder::GlyphRec& rec)
+ {
+ if (!mSkipFirstSpace) {
+ if (addNewLine(rec)) {
+ DBG_NAV_LOG("write new line");
+ *mSelectText.append() = '\n';
+ *mSelectText.append() = '\n';
+ } else if (addSpace(rec)) {
+ DBG_NAV_LOG("write space");
+ *mSelectText.append() = ' ';
+ }
+ } else
+ mSkipFirstSpace = false;
+ recordGlyph(rec);
+ finishGlyph();
+ if (VERBOSE_LOGGING) DBG_NAV_LOGD("glyphID=%d uni=%d '%c'", rec.fGlyphID,
+ mLastUni, mLastUni && mLastUni < 0x7f ? mLastUni : '?');
+ if (mLastUni) {
+ uint16_t chars[2];
+ size_t count = SkUTF16_FromUnichar(mLastUni, chars);
+ *mSelectText.append() = chars[0];
+ if (count == 2)
+ *mSelectText.append() = chars[1];
+ }
+ }
+
+ void finish()
+ {
+ Vector<SkIRect*> sortedBounds;
+ SkTDArray<uint16_t> temp;
+ int index;
+ DBG_NAV_LOGD("mSelectBounds.count=%d text=%d", mSelectBounds.count(),
+ mSelectText.count());
+ for (index = 0; index < mSelectBounds.count(); index++)
+ sortedBounds.append(&mSelectBounds[index]);
+ std::sort(sortedBounds.begin(), sortedBounds.end(), compareBounds);
+ int lastEnd = -1;
+ for (index = 0; index < mSelectBounds.count(); index++) {
+ if (sortedBounds[index]->isEmpty())
+ continue;
+ int order = sortedBounds[index] - &mSelectBounds[0];
+ int start = order > 0 ? mSelectCount[order - 1] : 0;
+ int end = mSelectCount[order];
+ DBG_NAV_LOGD("order=%d start=%d end=%d top=%d", order, start, end,
+ mSelectBounds[order].fTop);
+ int count = temp.count();
+ if (count > 0 && temp[count - 1] != '\n' && start != lastEnd) {
+ // always separate paragraphs when original text is out of order
+ DBG_NAV_LOG("write new line");
+ *temp.append() = '\n';
+ *temp.append() = '\n';
+ }
+ temp.append(end - start, &mSelectText[start]);
+ lastEnd = end;
+ }
+ mSelectText.swap(temp);
}
virtual bool onIRectGlyph(const SkIRect& rect,
@@ -643,44 +779,54 @@ public:
{
SkIRect full;
full.set(rect.fLeft, top(), rect.fRight, bottom());
- if (full == mSelectStart)
- mRecord = true;
- if (mRecord) {
- if (!mSkipFirstSpace) {
- if (addNewLine(rec)) {
- DBG_NAV_LOG("write new line");
- *mSelectText.append() = '\n';
- *mSelectText.append() = '\n';
- } else if (addSpace(rec)) {
- DBG_NAV_LOG("write space");
- *mSelectText.append() = ' ';
- }
- } else
- mSkipFirstSpace = false;
- recordGlyph(rec);
- finish();
- DBG_NAV_LOGD("TextExtractor glyphID=%d uni=%d '%c'"
- " append full=(%d,%d,r=%d,b=%d)", rec.fGlyphID,
- mLastUni, mLastUni && mLastUni < 0x7f ? mLastUni : '?',
- full.fLeft, full.fTop, full.fRight, full.fBottom);
- if (mLastUni) {
- uint16_t chars[2];
- size_t count = SkUTF16_FromUnichar(mLastUni, chars);
- *mSelectText.append() = chars[0];
- if (count == 2)
- *mSelectText.append() = chars[1];
+ int fullBase = base();
+ if (mFlipped) {
+ if (fullBase < mStart.fTop || fullBase > mEnd.fBottom
+ || (baseLinesAgree(mStart, mStartBase, full, fullBase)
+ && full.fLeft < mStart.fLeft)
+ || (baseLinesAgree(mEnd, mEndBase, full, fullBase)
+ && full.fRight > mEnd.fRight)) {
+ mSkipFirstSpace = true;
+ return false;
}
- } else {
- mSkipFirstSpace = true;
- DBG_NAV_LOGD("TextExtractor [%02x] skip full=(%d,%d,r=%d,b=%d)",
- rec.fGlyphID, full.fLeft, full.fTop, full.fRight, full.fBottom);
+ if (baseLinesAgree(mLast, mLastBase, full, fullBase)
+ && (full.fLeft - mLast.fRight < minSpaceWidth() * 3
+ || (SkIRect::Intersects(full, mSelectRect)
+ && SkIRect::Intersects(mLast, mSelectRect)))) {
+ mLast.join(full);
+ addCharacter(rec);
+ return false;
+ }
+ if (VERBOSE_LOGGING) DBG_NAV_LOGD("baseLinesAgree=%s"
+ " mLast=(%d,%d,r=%d,b=%d) mLastBase=%d"
+ " full=(%d,%d,r=%d,b=%d) fullBase=%d"
+ " mSelectRect=(%d,%d,r=%d,b=%d)",
+ baseLinesAgree(mLast, mLastBase, full, fullBase) ? "true" : "false",
+ mLast.fLeft, mLast.fTop, mLast.fRight, mLast.fBottom, mLastBase,
+ full.fLeft, full.fTop, full.fRight, full.fBottom, fullBase,
+ mSelectRect.fLeft, mSelectRect.fTop, mSelectRect.fRight, mSelectRect.fBottom);
+ *mSelectBounds.append() = SkIRect::Intersects(mLast, mSelectRect)
+ ? mLast : mEmpty;
+ *mSelectCount.append() = mSelectText.count();
+ addCharacter(rec);
+ mLast = full;
+ mLastBase = fullBase;
+ return false;
}
- if (full == mSelectEnd)
+ if (full == mStart)
+ mRecord = true;
+ if (mRecord)
+ addCharacter(rec);
+ else
+ mSkipFirstSpace = true;
+ if (full == mEnd)
mRecord = false;
return false;
}
WebCore::String text() {
+ if (mFlipped)
+ finish();
// the text has been copied in visual order. Reverse as needed if
// result contains right-to-left characters.
const uint16_t* start = mSelectText.begin();
@@ -698,11 +844,20 @@ public:
}
protected:
+ SkIRect mEmpty;
+ SkIRect mEnd;
+ int mEndBase;
+ bool mFlipped;
+ SkIRect mLast;
+ int mLastBase;
bool mRecord;
- const SkIRect& mSelectEnd;
- const SkIRect& mSelectStart;
+ SkTDArray<SkIRect> mSelectBounds;
+ SkTDArray<int> mSelectCount;
+ SkIRect mSelectRect;
SkTDArray<uint16_t> mSelectText;
bool mSkipFirstSpace;
+ SkIRect mStart;
+ int mStartBase;
private:
typedef CommonCheck INHERITED;
};
@@ -768,39 +923,48 @@ public:
CommonCheck& mBounder;
};
-static void buildSelection(const SkPicture& picture, const SkIRect& area,
- const SkIRect& selStart, const SkIRect& selEnd, SkRegion* region)
+static bool buildSelection(const SkPicture& picture, const SkIRect& area,
+ const SkIRect& selStart, int startBase,
+ const SkIRect& selEnd, int endBase, SkRegion* region)
{
DBG_NAV_LOGD("area=(%d, %d, %d, %d) selStart=(%d, %d, %d, %d)"
" selEnd=(%d, %d, %d, %d)",
area.fLeft, area.fTop, area.fRight, area.fBottom,
selStart.fLeft, selStart.fTop, selStart.fRight, selStart.fBottom,
selEnd.fLeft, selEnd.fTop, selEnd.fRight, selEnd.fBottom);
- MultilineBuilder builder(selStart, selEnd, area, region);
+ MultilineBuilder builder(selStart, startBase, selEnd, endBase, area, region);
TextCanvas checker(&builder, area);
checker.drawPicture(const_cast<SkPicture&>(picture));
+ bool flipped = builder.flipped();
+ if (flipped) {
+ TextCanvas checker(&builder, area);
+ checker.drawPicture(const_cast<SkPicture&>(picture));
+ }
+ builder.finish();
region->translate(area.fLeft, area.fTop);
+ return flipped;
}
static SkIRect findClosest(FirstCheck& _check, const SkPicture& picture,
- const SkIRect& area)
+ const SkIRect& area, int* base)
{
DBG_NAV_LOGD("area=(%d, %d, %d, %d)", area.fLeft, area.fTop,
area.fRight, area.fBottom);
TextCanvas checker(&_check, area);
checker.drawPicture(const_cast<SkPicture&>(picture));
- _check.finish();
- return _check.adjustedBounds(area);
+ _check.finishGlyph();
+ return _check.adjustedBounds(area, base);
}
static SkIRect findEdge(const SkPicture& picture, const SkIRect& area,
- int x, int y, bool left)
+ int x, int y, bool left, int* base)
{
SkIRect result;
result.setEmpty();
FirstCheck center(x, y, area);
center.setRecordGlyph();
- SkIRect closest = findClosest(center, picture, area);
+ int closestBase;
+ SkIRect closest = findClosest(center, picture, area, &closestBase);
closest.inset(-TOUCH_SLOP, -TOUCH_SLOP);
if (!closest.contains(x, y)) {
DBG_NAV_LOGD("closest=(%d, %d, %d, %d) area=(%d, %d, %d, %d) x/y=%d,%d",
@@ -814,12 +978,13 @@ static SkIRect findEdge(const SkPicture& picture, const SkIRect& area,
&edge, &picture, area.fLeft, area.fTop, area.fRight, area.fBottom);
TextCanvas checker(&edge, area);
checker.drawPicture(const_cast<SkPicture&>(picture));
- edge.finish();
+ edge.finishGlyph();
if (!edge.adjacent()) {
DBG_NAV_LOG("adjacent break");
break;
}
- const SkIRect& next = edge.bestBounds();
+ int nextBase;
+ const SkIRect& next = edge.bestBounds(&nextBase);
if (next.isEmpty()) {
DBG_NAV_LOG("empty");
break;
@@ -828,50 +993,54 @@ static SkIRect findEdge(const SkPicture& picture, const SkIRect& area,
DBG_NAV_LOG("result == next");
break;
}
+ *base = nextBase;
result = next;
edge.shiftStart(result);
} while (true);
- if (!result.isEmpty())
+ if (!result.isEmpty()) {
+ *base += area.fTop;
result.offset(area.fLeft, area.fTop);
+ }
return result;
}
-static SkIRect findFirst(const SkPicture& picture)
+static SkIRect findFirst(const SkPicture& picture, int* base)
{
FindFirst finder(picture.width(), picture.height());
SkIRect area;
area.set(0, 0, picture.width(), picture.height());
TextCanvas checker(&finder, area);
checker.drawPicture(const_cast<SkPicture&>(picture));
- return finder.bestBounds();
+ return finder.bestBounds(base);
}
-static SkIRect findLast(const SkPicture& picture)
+static SkIRect findLast(const SkPicture& picture, int* base)
{
FindLast finder(picture.width(), picture.height());
SkIRect area;
area.set(0, 0, picture.width(), picture.height());
TextCanvas checker(&finder, area);
checker.drawPicture(const_cast<SkPicture&>(picture));
- return finder.bestBounds();
+ return finder.bestBounds(base);
}
static SkIRect findLeft(const SkPicture& picture, const SkIRect& area,
- int x, int y)
+ int x, int y, int* base)
{
- return findEdge(picture, area, x, y, true);
+ return findEdge(picture, area, x, y, true, base);
}
static SkIRect findRight(const SkPicture& picture, const SkIRect& area,
- int x, int y)
+ int x, int y, int* base)
{
- return findEdge(picture, area, x, y, false);
+ return findEdge(picture, area, x, y, false, base);
}
static WebCore::String text(const SkPicture& picture, const SkIRect& area,
- const SkIRect& start, const SkIRect& end)
+ const SkIRect& start, int startBase, const SkIRect& end,
+ int endBase, bool flipped)
{
- TextExtractor extractor(start, end, area);
+ TextExtractor extractor(start, startBase, end, endBase, area, flipped);
TextCanvas checker(&extractor, area);
checker.drawPicture(const_cast<SkPicture&>(picture));
return extractor.text();
@@ -995,7 +1164,8 @@ void SelectText::drawSelectionRegion(SkCanvas* canvas)
DBG_NAV_LOGD("m_selStart=(%d, %d, %d, %d) m_selEnd=(%d, %d, %d, %d)",
m_selStart.fLeft, m_selStart.fTop, m_selStart.fRight, m_selStart.fBottom,
m_selEnd.fLeft, m_selEnd.fTop, m_selEnd.fRight, m_selEnd.fBottom);
- buildSelection(*m_picture, ivisBounds, m_selStart, m_selEnd, &m_selRegion);
+ m_flipped = buildSelection(*m_picture, ivisBounds, m_selStart, m_startBase,
+ m_selEnd, m_endBase, &m_selRegion);
SkPath path;
m_selRegion.getBoundaryPath(&path);
path.setFillType(SkPath::kEvenOdd_FillType);
@@ -1018,6 +1188,7 @@ void SelectText::drawSelectionRegion(SkCanvas* canvas)
void SelectText::extendSelection(const SkPicture* picture, int x, int y)
{
SkIRect clipRect = m_visibleRect;
+ int base;
if (m_startSelection) {
if (!clipRect.contains(x, y)
|| !clipRect.contains(m_original.fX, m_original.fY)) {
@@ -1029,7 +1200,8 @@ void SelectText::extendSelection(const SkPicture* picture, int x, int y)
clipRect.fTop, clipRect.fRight, clipRect.fBottom);
m_picture = picture;
FirstCheck center(m_original.fX, m_original.fY, clipRect);
- m_selStart = m_selEnd = findClosest(center, *picture, clipRect);
+ m_selStart = m_selEnd = findClosest(center, *picture, clipRect, &base);
+ m_startBase = m_endBase = base;
m_startSelection = false;
m_extendSelection = true;
m_original.fX = m_original.fY = 0;
@@ -1045,17 +1217,20 @@ void SelectText::extendSelection(const SkPicture* picture, int x, int y)
DBG_NAV_LOGD("extend clip=(%d,%d,%d,%d)", clipRect.fLeft,
clipRect.fTop, clipRect.fRight, clipRect.fBottom);
FirstCheck extension(x, y, clipRect);
- SkIRect found = findClosest(extension, *picture, clipRect);
+ SkIRect found = findClosest(extension, *picture, clipRect, &base);
DBG_NAV_LOGD("pic=%p x=%d y=%d m_startSelection=%s %s=(%d, %d, %d, %d)"
" m_extendSelection=%s",
picture, x, y, m_startSelection ? "true" : "false",
m_hitTopLeft ? "m_selStart" : "m_selEnd",
found.fLeft, found.fTop, found.fRight, found.fBottom,
m_extendSelection ? "true" : "false");
- if (m_hitTopLeft)
+ if (m_hitTopLeft) {
+ m_startBase = base;
m_selStart = found;
- else
+ } else {
+ m_endBase = base;
m_selEnd = found;
+ }
swapAsNeeded();
}
@@ -1063,7 +1238,8 @@ const String SelectText::getSelection()
{
SkIRect clipRect;
clipRect.set(0, 0, m_picture->width(), m_picture->height());
- String result = text(*m_picture, clipRect, m_selStart, m_selEnd);
+ String result = text(*m_picture, clipRect, m_selStart, m_startBase,
+ m_selEnd, m_endBase, m_flipped);
DBG_NAV_LOGD("clip=(%d,%d,%d,%d)"
" m_selStart=(%d, %d, %d, %d) m_selEnd=(%d, %d, %d, %d)",
clipRect.fLeft, clipRect.fTop, clipRect.fRight, clipRect.fBottom,
@@ -1125,11 +1301,16 @@ void SelectText::moveSelection(const SkPicture* picture, int x, int y)
if (!m_extendSelection)
m_picture = picture;
FirstCheck center(x, y, clipRect);
- SkIRect found = findClosest(center, *picture, clipRect);
- if (m_hitTopLeft || !m_extendSelection)
+ int base;
+ SkIRect found = findClosest(center, *picture, clipRect, &base);
+ if (m_hitTopLeft || !m_extendSelection) {
+ m_startBase = base;
m_selStart = found;
- if (!m_hitTopLeft || !m_extendSelection)
+ }
+ if (!m_hitTopLeft || !m_extendSelection) {
+ m_endBase = base;
m_selEnd = found;
+ }
swapAsNeeded();
DBG_NAV_LOGD("x=%d y=%d extendSelection=%s m_selStart=(%d, %d, %d, %d)"
" m_selEnd=(%d, %d, %d, %d)", x, y, m_extendSelection ? "true" : "false",
@@ -1148,8 +1329,8 @@ void SelectText::reset()
void SelectText::selectAll(const SkPicture* picture)
{
- m_selStart = findFirst(*picture);
- m_selEnd = findLast(*picture);
+ m_selStart = findFirst(*picture, &m_startBase);
+ m_selEnd = findLast(*picture, &m_endBase);
m_extendSelection = true;
}
@@ -1205,16 +1386,21 @@ bool SelectText::wordSelection(const SkPicture* picture)
int y = (m_selStart.fTop + m_selStart.fBottom) >> 1;
SkIRect clipRect = m_visibleRect;
clipRect.fLeft -= m_visibleRect.width() >> 1;
- SkIRect left = findLeft(*picture, clipRect, x, y);
- if (!left.isEmpty())
+ int base;
+ SkIRect left = findLeft(*picture, clipRect, x, y, &base);
+ if (!left.isEmpty()) {
+ m_startBase = base;
m_selStart = left;
+ }
x = m_selEnd.fRight;
y = (m_selEnd.fTop + m_selEnd.fBottom) >> 1;
clipRect = m_visibleRect;
clipRect.fRight += m_visibleRect.width() >> 1;
- SkIRect right = findRight(*picture, clipRect, x, y);
- if (!right.isEmpty())
+ SkIRect right = findRight(*picture, clipRect, x, y, &base);
+ if (!right.isEmpty()) {
+ m_endBase = base;
m_selEnd = right;
+ }
DBG_NAV_LOGD("m_selStart=(%d, %d, %d, %d) m_selEnd=(%d, %d, %d, %d)",
m_selStart.fLeft, m_selStart.fTop, m_selStart.fRight, m_selStart.fBottom,
m_selEnd.fLeft, m_selEnd.fTop, m_selEnd.fRight, m_selEnd.fBottom);
@@ -1231,6 +1417,7 @@ void SelectText::swapAsNeeded()
|| (m_selStart.fBottom > m_selEnd.fTop
&& m_selStart.fRight > m_selEnd.fLeft))
{
+ SkTSwap(m_startBase, m_endBase);
SkTSwap(m_selStart, m_selEnd);
m_hitTopLeft ^= true;
DBG_NAV_LOGD("m_hitTopLeft=%s", m_hitTopLeft ? "true" : "false");
diff --git a/WebKit/android/nav/SelectText.h b/WebKit/android/nav/SelectText.h
index 00b9ca9..404e9e7 100644
--- a/WebKit/android/nav/SelectText.h
+++ b/WebKit/android/nav/SelectText.h
@@ -70,6 +70,8 @@ private:
SkIPoint m_original; // computed start of extend selection
SkIRect m_selStart;
SkIRect m_selEnd;
+ int m_startBase;
+ int m_endBase;
SkIRect m_visibleRect; // constrains picture computations to visible area
SkRegion m_selRegion; // computed from sel start, end
SkPicture m_startControl;
@@ -77,6 +79,7 @@ private:
const SkPicture* m_picture;
bool m_drawPointer;
bool m_extendSelection; // false when trackball is moving pointer
+ bool m_flipped;
bool m_hitTopLeft;
bool m_startSelection;
};
diff --git a/WebKit/android/nav/WebView.cpp b/WebKit/android/nav/WebView.cpp
index 9dbefd9..ac36b73 100644
--- a/WebKit/android/nav/WebView.cpp
+++ b/WebKit/android/nav/WebView.cpp
@@ -30,6 +30,7 @@
#include "AndroidAnimation.h"
#include "AndroidLog.h"
#include "AtomicString.h"
+#include "BaseLayerAndroid.h"
#include "CachedFrame.h"
#include "CachedNode.h"
#include "CachedRoot.h"
@@ -177,7 +178,7 @@ WebView(JNIEnv* env, jobject javaWebView, int viewImpl) :
m_lastDx = 0;
m_lastDxTime = 0;
m_ringAnimationEnd = 0;
- m_rootLayer = 0;
+ m_baseLayer = 0;
}
~WebView()
@@ -190,7 +191,7 @@ WebView(JNIEnv* env, jobject javaWebView, int viewImpl) :
}
delete m_frameCacheUI;
delete m_navPictureUI;
- delete m_rootLayer;
+ delete m_baseLayer;
}
WebViewCore* getWebViewCore() const {
@@ -303,10 +304,11 @@ void scrollRectOnScreen(const IntRect& rect)
SkRect visible;
calcOurContentVisibleRect(&visible);
#if USE(ACCELERATED_COMPOSITING)
- if (m_rootLayer) {
- m_rootLayer->updateFixedLayersPositions(visible);
- m_rootLayer->updatePositions();
- visible = m_rootLayer->subtractLayers(visible);
+ LayerAndroid* root = compositeRoot();
+ if (root) {
+ root->updateFixedLayersPositions(visible);
+ root->updatePositions();
+ visible = root->subtractLayers(visible);
}
#endif
int dx = 0;
@@ -394,14 +396,30 @@ void drawCursorPostamble()
}
}
-void drawExtras(SkCanvas* canvas, int extras)
+PictureSet* draw(SkCanvas* canvas, SkColor bgColor, int extras, bool split)
{
+ PictureSet* ret = 0;
+ if (!m_baseLayer) {
+ canvas->drawColor(bgColor);
+ return ret;
+ }
+
+ // draw the content of the base layer first
+ PictureSet* content = m_baseLayer->content();
+ int sc = canvas->save(SkCanvas::kClip_SaveFlag);
+ canvas->clipRect(SkRect::MakeLTRB(0, 0, content->width(),
+ content->height()), SkRegion::kDifference_Op);
+ canvas->drawColor(bgColor);
+ canvas->restoreToCount(sc);
+ if (content->draw(canvas))
+ ret = split ? new PictureSet(*content) : 0;
+
CachedRoot* root = getFrameCache(AllowNewer);
if (!root) {
DBG_NAV_LOG("!root");
if (extras == DrawExtrasCursorRing)
resetCursorRing();
- return;
+ return ret;
}
LayerAndroid mainPicture(m_navPictureUI);
DrawExtra* extra = 0;
@@ -425,22 +443,24 @@ void drawExtras(SkCanvas* canvas, int extras)
if (extra)
extra->draw(canvas, &mainPicture);
#if USE(ACCELERATED_COMPOSITING)
- if (!m_rootLayer)
- return;
- m_rootLayer->setExtra(extra);
+ LayerAndroid* compositeLayer = compositeRoot();
+ if (!compositeLayer)
+ return ret;
+ compositeLayer->setExtra(extra);
SkRect visible;
calcOurContentVisibleRect(&visible);
// call this to be sure we've adjusted for any scrolling or animations
// before we actually draw
- m_rootLayer->updateFixedLayersPositions(visible);
- m_rootLayer->updatePositions();
- // We have to set the canvas' matrix on the root layer
+ compositeLayer->updateFixedLayersPositions(visible);
+ compositeLayer->updatePositions();
+ // We have to set the canvas' matrix on the base layer
// (to have fixed layers work as intended)
SkAutoCanvasRestore restore(canvas, true);
- m_rootLayer->setMatrix(canvas->getTotalMatrix());
+ m_baseLayer->setMatrix(canvas->getTotalMatrix());
canvas->resetMatrix();
- m_rootLayer->draw(canvas);
+ m_baseLayer->draw(canvas);
#endif
+ return ret;
}
@@ -565,7 +585,7 @@ CachedRoot* getFrameCache(FrameCachePermission allowNewer)
m_viewImpl->m_navPictureKit = 0;
m_viewImpl->gFrameCacheMutex.unlock();
if (m_frameCacheUI)
- m_frameCacheUI->setRootLayer(m_rootLayer);
+ m_frameCacheUI->setRootLayer(compositeRoot());
#if USE(ACCELERATED_COMPOSITING)
if (layerId >= 0) {
SkRect visible;
@@ -1170,20 +1190,49 @@ int moveGeneration()
return m_viewImpl->m_moveGeneration;
}
-LayerAndroid* rootLayer() const
+LayerAndroid* compositeRoot() const
{
- return m_rootLayer;
+ LOG_ASSERT(!m_baseLayer || m_baseLayer->countChildren() == 1,
+ "base layer can't have more than one child %s", __FUNCTION__);
+ if (m_baseLayer && m_baseLayer->countChildren() == 1)
+ return static_cast<LayerAndroid*>(m_baseLayer->getChild(0));
+ else
+ return 0;
}
-void setRootLayer(LayerAndroid* layer)
+void setBaseLayer(BaseLayerAndroid* layer)
{
- delete m_rootLayer;
- m_rootLayer = layer;
+ delete m_baseLayer;
+ m_baseLayer = layer;
CachedRoot* root = getFrameCache(DontAllowNewer);
if (!root)
return;
root->resetLayers();
- root->setRootLayer(m_rootLayer);
+ root->setRootLayer(compositeRoot());
+}
+
+void replaceBaseContent(PictureSet* set)
+{
+ if (!m_baseLayer)
+ return;
+ m_baseLayer->setContent(*set);
+ delete set;
+}
+
+void copyBaseContentToPicture(SkPicture* picture)
+{
+ if (!m_baseLayer)
+ return;
+ PictureSet* content = m_baseLayer->content();
+ content->draw(picture->beginRecording(content->width(), content->height(),
+ SkPicture::kUsePathBoundsForClip_RecordingFlag));
+ picture->endRecording();
+}
+
+bool hasContent() {
+ if (!m_baseLayer)
+ return false;
+ return !m_baseLayer->content()->isEmpty();
}
private: // local state for WebView
@@ -1200,7 +1249,7 @@ private: // local state for WebView
SelectText m_selectText;
FindOnPage m_findOnPage;
CursorRing m_ring;
- LayerAndroid* m_rootLayer;
+ BaseLayerAndroid* m_baseLayer;
}; // end of WebView class
/*
@@ -1431,28 +1480,43 @@ static void nativeDebugDump(JNIEnv *env, jobject obj)
#endif
}
-static void nativeDrawExtras(JNIEnv *env, jobject obj, jobject canv, jint extras)
-{
+static jint nativeDraw(JNIEnv *env, jobject obj, jobject canv, jint color,
+ jint extras, jboolean split) {
SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, canv);
- GET_NATIVE_VIEW(env, obj)->drawExtras(canvas, extras);
+ return reinterpret_cast<jint>(GET_NATIVE_VIEW(env, obj)->draw(canvas, color, extras, split));
}
static bool nativeEvaluateLayersAnimations(JNIEnv *env, jobject obj)
{
#if USE(ACCELERATED_COMPOSITING)
- const LayerAndroid* root = GET_NATIVE_VIEW(env, obj)->rootLayer();
+ const LayerAndroid* root = GET_NATIVE_VIEW(env, obj)->compositeRoot();
if (root)
return root->evaluateAnimations();
#endif
return false;
}
-static void nativeSetRootLayer(JNIEnv *env, jobject obj, jint layer)
+static void nativeSetBaseLayer(JNIEnv *env, jobject obj, jint layer)
{
-#if USE(ACCELERATED_COMPOSITING)
- LayerAndroid* layerImpl = reinterpret_cast<LayerAndroid*>(layer);
- GET_NATIVE_VIEW(env, obj)->setRootLayer(layerImpl);
-#endif
+ BaseLayerAndroid* layerImpl = reinterpret_cast<BaseLayerAndroid*>(layer);
+ GET_NATIVE_VIEW(env, obj)->setBaseLayer(layerImpl);
+}
+
+static void nativeReplaceBaseContent(JNIEnv *env, jobject obj, jint content)
+{
+ PictureSet* set = reinterpret_cast<PictureSet*>(content);
+ GET_NATIVE_VIEW(env, obj)->replaceBaseContent(set);
+}
+
+static void nativeCopyBaseContentToPicture(JNIEnv *env, jobject obj, jobject pict)
+{
+ SkPicture* picture = GraphicsJNI::getNativePicture(env, pict);
+ GET_NATIVE_VIEW(env, obj)->copyBaseContentToPicture(picture);
+}
+
+static bool nativeHasContent(JNIEnv *env, jobject obj)
+{
+ return GET_NATIVE_VIEW(env, obj)->hasContent();
}
static jobject nativeImageURI(JNIEnv *env, jobject obj, jint x, jint y)
@@ -1642,7 +1706,7 @@ static jobject nativeSubtractLayers(JNIEnv* env, jobject obj, jobject jrect)
{
SkIRect irect = jrect_to_webrect(env, jrect);
#if USE(ACCELERATED_COMPOSITING)
- LayerAndroid* root = GET_NATIVE_VIEW(env, obj)->rootLayer();
+ LayerAndroid* root = GET_NATIVE_VIEW(env, obj)->compositeRoot();
if (root) {
SkRect rect;
rect.set(irect);
@@ -1981,26 +2045,13 @@ static void nativeDumpDisplayTree(JNIEnv* env, jobject jwebview, jstring jurl)
SkDumpCanvas canvas(&dumper);
// this will playback the picture into the canvas, which will
// spew its contents to the dumper
- view->getWebViewCore()->drawContent(&canvas, 0);
-#if USE(ACCELERATED_COMPOSITING)
- if (true) {
- LayerAndroid* rootLayer = view->rootLayer();
- if (rootLayer) {
- // We have to set the canvas' matrix on the root layer
- // (to have fixed layers work as intended)
- SkAutoCanvasRestore restore(&canvas, true);
- rootLayer->setMatrix(canvas.getTotalMatrix());
- canvas.resetMatrix();
- rootLayer->draw(&canvas);
- }
- }
-#endif
+ view->draw(&canvas, 0, 0, false);
// we're done with the file now
fwrite("\n", 1, 1, file);
fclose(file);
}
#if USE(ACCELERATED_COMPOSITING)
- const LayerAndroid* rootLayer = view->rootLayer();
+ const LayerAndroid* rootLayer = view->compositeRoot();
if (rootLayer) {
FILE* file = fopen(LAYERS_TREE_LOG_FILE,"w");
if (file) {
@@ -2053,8 +2104,8 @@ static JNINativeMethod gJavaWebViewMethods[] = {
(void*) nativeDebugDump },
{ "nativeDestroy", "()V",
(void*) nativeDestroy },
- { "nativeDrawExtras", "(Landroid/graphics/Canvas;I)V",
- (void*) nativeDrawExtras },
+ { "nativeDraw", "(Landroid/graphics/Canvas;IIZ)I",
+ (void*) nativeDraw },
{ "nativeDumpDisplayTree", "(Ljava/lang/String;)V",
(void*) nativeDumpDisplayTree },
{ "nativeEvaluateLayersAnimations", "()Z",
@@ -2147,8 +2198,14 @@ static JNINativeMethod gJavaWebViewMethods[] = {
(void*) nativeSetFollowedLink },
{ "nativeSetHeightCanMeasure", "(Z)V",
(void*) nativeSetHeightCanMeasure },
- { "nativeSetRootLayer", "(I)V",
- (void*) nativeSetRootLayer },
+ { "nativeSetBaseLayer", "(I)V",
+ (void*) nativeSetBaseLayer },
+ { "nativeReplaceBaseContent", "(I)V",
+ (void*) nativeReplaceBaseContent },
+ { "nativeCopyBaseContentToPicture", "(Landroid/graphics/Picture;)V",
+ (void*) nativeCopyBaseContentToPicture },
+ { "nativeHasContent", "()Z",
+ (void*) nativeHasContent },
{ "nativeSetSelectionPointer", "(ZFII)V",
(void*) nativeSetSelectionPointer },
{ "nativeStartSelection", "(II)Z",