diff options
Diffstat (limited to 'WebKit/android/nav')
| -rw-r--r-- | WebKit/android/nav/SelectText.cpp | 88 | ||||
| -rw-r--r-- | WebKit/android/nav/SelectText.h | 4 | ||||
| -rw-r--r-- | WebKit/android/nav/WebView.cpp | 136 |
3 files changed, 124 insertions, 104 deletions
diff --git a/WebKit/android/nav/SelectText.cpp b/WebKit/android/nav/SelectText.cpp index 9a9f8d2..d8b184a 100644 --- a/WebKit/android/nav/SelectText.cpp +++ b/WebKit/android/nav/SelectText.cpp @@ -35,14 +35,17 @@ #include "SkPoint.h" #include "SkRect.h" #include "SkRegion.h" +#include "SkUtils.h" class CommonCheck : public SkBounder { public: CommonCheck() : mMatrix(NULL), mPaint(NULL) {} - virtual void setUp(const SkPaint& paint, const SkMatrix& matrix, SkScalar y) { + virtual void setUp(const SkPaint& paint, const SkMatrix& matrix, SkScalar y, + const void* text) { mMatrix = &matrix; mPaint = &paint; + mText = static_cast<const uint16_t*>(text); mY = y; mBase = mBottom = mTop = INT_MAX; } @@ -81,10 +84,11 @@ public: protected: const SkMatrix* mMatrix; const SkPaint* mPaint; + const uint16_t* mText; + SkScalar mY; int mBase; int mBottom; int mTop; - SkScalar mY; }; class FirstCheck : public CommonCheck { @@ -162,6 +166,8 @@ public: full.fRight = mLast.fLeft; } mSelectRegion->op(full, SkRegion::kUnion_Op); + DBG_NAV_LOGD("MultilineBuilder full=(%d,%d,r=%d,b=%d)", + full.fLeft, full.fTop, full.fRight, full.fBottom); mLast = full; mLastBase = base(); if (mStart == mEnd) @@ -178,6 +184,66 @@ protected: bool mCapture; }; +class TextExtractor : public CommonCheck { +public: + TextExtractor(const SkRegion& region) : mSelectRegion(region), + mSkipFirstSpace(true) { // don't start with a space + } + + virtual void setUp(const SkPaint& paint, const SkMatrix& matrix, SkScalar y, + const void* text) { + INHERITED::setUp(paint, matrix, y, text); + SkPaint charPaint = paint; + charPaint.setTextEncoding(SkPaint::kUTF8_TextEncoding); + mMinSpaceWidth = charPaint.measureText(" ", 1) * 3 / 4; + } + + virtual bool onIRect(const SkIRect& rect, uint16_t glyphID) { + SkIRect full; + full.set(rect.fLeft, top(), rect.fRight, bottom()); + if (mSelectRegion.contains(full)) { + if (!mSkipFirstSpace + && ((mLast.fTop < top() && mLast.fBottom < top() + 2) + || (mLast.fLeft < rect.fLeft // glyphs are LTR + && mLast.fRight + mMinSpaceWidth < rect.fLeft))) { + DBG_NAV_LOGD("TextExtractor [%02x] append space", glyphID); + *mSelectText.append() = ' '; + } else + mSkipFirstSpace = false; + DBG_NAV_LOGD("TextExtractor [%02x] append full=(%d,%d,r=%d,b=%d)", + glyphID, full.fLeft, full.fTop, full.fRight, full.fBottom); + SkUnichar uni; + SkPaint utfPaint = *mPaint; + utfPaint.setTextEncoding(SkPaint::kUTF16_TextEncoding); + utfPaint.glyphsToUnichars(&glyphID, 1, &uni); + if (uni) { + uint16_t chars[2]; + size_t count = SkUTF16_FromUnichar(uni, chars); + *mSelectText.append() = chars[0]; + if (count == 2) + *mSelectText.append() = chars[1]; + } + mLast = full; + } else + DBG_NAV_LOGD("TextExtractor [%02x] skip full=(%d,%d,r=%d,b=%d)", + glyphID, full.fLeft, full.fTop, full.fRight, full.fBottom); + return false; + } + + WebCore::String text() { + return WebCore::String(mSelectText.begin(), mSelectText.count()); + } + +protected: + const SkRegion& mSelectRegion; + SkTDArray<uint16_t> mSelectText; + SkIRect mLast; + SkScalar mMinSpaceWidth; + bool mSkipFirstSpace; +private: + typedef CommonCheck INHERITED; +}; + class TextCanvas : public SkCanvas { public: @@ -218,14 +284,14 @@ public: virtual void drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y, const SkPaint& paint) { - mBounder.setUp(paint, getTotalMatrix(), y); + mBounder.setUp(paint, getTotalMatrix(), y, text); SkCanvas::drawText(text, byteLength, x, y, paint); } virtual void drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], SkScalar constY, const SkPaint& paint) { - mBounder.setUp(paint, getTotalMatrix(), constY); + mBounder.setUp(paint, getTotalMatrix(), constY, text); SkCanvas::drawPosTextH(text, byteLength, xpos, constY, paint); } @@ -262,3 +328,17 @@ SkIRect CopyPaste::findClosest(const SkPicture& picture, const SkIRect& area, _check.offsetBounds(area.fLeft, area.fTop); return _check.bestBounds(); } + +WebCore::String CopyPaste::text(const SkPicture& picture, const SkIRect& area, + const SkRegion& region) { + SkRegion copy = region; + copy.translate(-area.fLeft, -area.fTop); + const SkIRect& bounds = copy.getBounds(); + DBG_NAV_LOGD("area=(%d, %d, %d, %d) region=(%d, %d, %d, %d)", + area.fLeft, area.fTop, area.fRight, area.fBottom, + bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom); + TextExtractor extractor(copy); + TextCanvas checker(&extractor, picture, area); + checker.drawPicture(const_cast<SkPicture&>(picture)); + return extractor.text(); +} diff --git a/WebKit/android/nav/SelectText.h b/WebKit/android/nav/SelectText.h index 3365816..32d8311 100644 --- a/WebKit/android/nav/SelectText.h +++ b/WebKit/android/nav/SelectText.h @@ -26,6 +26,8 @@ #ifndef SELECT_TEXT_H #define SELECT_TEXT_H +#include "PlatformString.h" + class SkPicture; struct SkIRect; struct SkIPoint; @@ -37,6 +39,8 @@ public: const SkIRect& selStart, const SkIRect& selEnd, SkRegion* region); static SkIRect findClosest(const SkPicture& , const SkIRect& area, int x, int y); + static WebCore::String text(const SkPicture& , const SkIRect& area, + const SkRegion& ); }; #endif diff --git a/WebKit/android/nav/WebView.cpp b/WebKit/android/nav/WebView.cpp index fd6a1da..cd767e2 100644 --- a/WebKit/android/nav/WebView.cpp +++ b/WebKit/android/nav/WebView.cpp @@ -34,6 +34,7 @@ #include "CachedFrame.h" #include "CachedNode.h" #include "CachedRoot.h" +#include "CString.h" #include "FindCanvas.h" #include "Frame.h" #include "GraphicsJNI.h" @@ -98,7 +99,7 @@ enum FrameCachePermission { }; struct JavaGlue { - jobject m_obj; + jweak m_obj; jmethodID m_clearTextEntry; jmethodID m_overrideLoading; jmethodID m_scrollBy; @@ -128,7 +129,7 @@ WebView(JNIEnv* env, jobject javaWebView, int viewImpl) { jclass clazz = env->FindClass("android/webkit/WebView"); // m_javaGlue = new JavaGlue; - m_javaGlue.m_obj = adoptGlobalRef(env, javaWebView); + m_javaGlue.m_obj = env->NewWeakGlobalRef(javaWebView); m_javaGlue.m_scrollBy = GetJMethod(env, clazz, "setContentScrollBy", "(IIZ)Z"); m_javaGlue.m_clearTextEntry = GetJMethod(env, clazz, "clearTextEntry", "()V"); m_javaGlue.m_overrideLoading = GetJMethod(env, clazz, "overrideLoading", "(Ljava/lang/String;)V"); @@ -175,7 +176,7 @@ WebView(JNIEnv* env, jobject javaWebView, int viewImpl) if (m_javaGlue.m_obj) { JNIEnv* env = JSC::Bindings::getJNIEnv(); - env->DeleteGlobalRef(m_javaGlue.m_obj); + env->DeleteWeakGlobalRef(m_javaGlue.m_obj); m_javaGlue.m_obj = 0; } delete m_frameCacheUI; @@ -216,12 +217,7 @@ void clearTextEntry() { DEBUG_NAV_UI_LOGD("%s", __FUNCTION__); JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue.object(env); - // if it is called during or after DESTROY is handled, the real object of - // WebView can be gone. Check before using it. - if (!obj.get()) - return; - env->CallVoidMethod(obj.get(), m_javaGlue.m_clearTextEntry); + env->CallVoidMethod(m_javaGlue.object(env).get(), m_javaGlue.m_clearTextEntry); checkException(env); } @@ -648,12 +644,7 @@ int getScaledMaxXScroll() { LOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!"); JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue.object(env); - // if it is called during or after DESTROY is handled, the real object of - // WebView can be gone. Check before using it. - if (!obj.get()) - return 0; - int result = env->CallIntMethod(obj.get(), m_javaGlue.m_getScaledMaxXScroll); + int result = env->CallIntMethod(m_javaGlue.object(env).get(), m_javaGlue.m_getScaledMaxXScroll); checkException(env); return result; } @@ -662,12 +653,7 @@ int getScaledMaxYScroll() { LOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!"); JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue.object(env); - // if it is called during or after DESTROY is handled, the real object of - // WebView can be gone. Check before using it. - if (!obj.get()) - return 0; - int result = env->CallIntMethod(obj.get(), m_javaGlue.m_getScaledMaxYScroll); + int result = env->CallIntMethod(m_javaGlue.object(env).get(), m_javaGlue.m_getScaledMaxYScroll); checkException(env); return result; } @@ -676,12 +662,7 @@ void getVisibleRect(WebCore::IntRect* rect) { LOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!"); JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue.object(env); - // if it is called during or after DESTROY is handled, the real object of - // WebView can be gone. Check before using it. - if (!obj.get()) - return; - jobject jRect = env->CallObjectMethod(obj.get(), m_javaGlue.m_getVisibleRect); + jobject jRect = env->CallObjectMethod(m_javaGlue.object(env).get(), m_javaGlue.m_getVisibleRect); checkException(env); int left = (int) env->GetIntField(jRect, m_javaGlue.m_rectLeft); checkException(env); @@ -1003,13 +984,9 @@ int getBlockLeftEdge(int x, int y, float scale) void overrideUrlLoading(const WebCore::String& url) { JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue.object(env); - // if it is called during or after DESTROY is handled, the real object of - // WebView can be gone. Check before using it. - if (!obj.get()) - return; jstring jName = env->NewString((jchar*) url.characters(), url.length()); - env->CallVoidMethod(obj.get(), m_javaGlue.m_overrideLoading, jName); + env->CallVoidMethod(m_javaGlue.object(env).get(), + m_javaGlue.m_overrideLoading, jName); env->DeleteLocalRef(jName); } @@ -1056,9 +1033,15 @@ void moveSelection(int x, int y, bool extendSelection) m_selEnd.fLeft, m_selEnd.fTop, m_selEnd.fRight, m_selEnd.fBottom); } -const SkRegion& getSelection() +const String getSelection() { - return m_selRegion; + WebCore::IntRect r; + getVisibleRect(&r); + SkIRect area; + area.set(r.x(), r.y(), r.right(), r.bottom()); + String result = CopyPaste::text(*m_navPictureUI, area, m_selRegion); + DBG_NAV_LOGD("text=%s", result.latin1().data()); + return result; } void drawSelectionRegion(SkCanvas* canvas) @@ -1133,15 +1116,10 @@ void getSelectionCaret(SkPath* path) void sendMoveFocus(WebCore::Frame* framePtr, WebCore::Node* nodePtr) { - DBG_NAV_LOGD("framePtr=%p nodePtr=%p x=%d y=%d", framePtr, nodePtr, x, y); + DBG_NAV_LOGD("framePtr=%p nodePtr=%p", framePtr, nodePtr); JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue.object(env); - // if it is called during or after DESTROY is handled, the real object of - // WebView can be gone. Check before using it. - if (!obj.get()) - return; - env->CallVoidMethod(obj.get(), m_javaGlue.m_sendMoveFocus, (jint) framePtr, - (jint) nodePtr); + env->CallVoidMethod(m_javaGlue.object(env).get(), + m_javaGlue.m_sendMoveFocus, (jint) framePtr, (jint) nodePtr); checkException(env); } @@ -1149,12 +1127,7 @@ void sendMoveMouse(WebCore::Frame* framePtr, WebCore::Node* nodePtr, int x, int { DBG_NAV_LOGD("framePtr=%p nodePtr=%p x=%d y=%d", framePtr, nodePtr, x, y); JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue.object(env); - // if it is called during or after DESTROY is handled, the real object of - // WebView can be gone. Check before using it. - if (!obj.get()) - return; - env->CallVoidMethod(obj.get(), m_javaGlue.m_sendMoveMouse, + env->CallVoidMethod(m_javaGlue.object(env).get(), m_javaGlue.m_sendMoveMouse, (jint) framePtr, (jint) nodePtr, x, y); checkException(env); } @@ -1163,12 +1136,8 @@ void sendMoveMouseIfLatest(bool disableFocusController) { LOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!"); JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue.object(env); - // if it is called during or after DESTROY is handled, the real object of - // WebView can be gone. Check before using it. - if (!obj.get()) - return; - env->CallVoidMethod(obj.get(), m_javaGlue.m_sendMoveMouseIfLatest, disableFocusController); + env->CallVoidMethod(m_javaGlue.object(env).get(), + m_javaGlue.m_sendMoveMouseIfLatest, disableFocusController); checkException(env); } @@ -1180,12 +1149,7 @@ void sendMotionUp( m_generation, framePtr, nodePtr, x, y); LOG_ASSERT(m_javaGlue.m_obj, "A WebView was not associated with this WebViewNative!"); JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue.object(env); - // if it is called during or after DESTROY is handled, the real object of - // WebView can be gone. Check before using it. - if (!obj.get()) - return; - env->CallVoidMethod(obj.get(), m_javaGlue.m_sendMotionUp, + env->CallVoidMethod(m_javaGlue.object(env).get(), m_javaGlue.m_sendMotionUp, m_generation, (jint) framePtr, (jint) nodePtr, x, y); checkException(env); } @@ -1254,12 +1218,7 @@ bool scrollBy(int dx, int dy) LOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!"); JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue.object(env); - // if it is called during or after DESTROY is handled, the real object of - // WebView can be gone. Check before using it. - if (!obj.get()) - return false; - bool result = env->CallBooleanMethod(obj.get(), + bool result = env->CallBooleanMethod(m_javaGlue.object(env).get(), m_javaGlue.m_scrollBy, dx, dy, true); checkException(env); return result; @@ -1296,24 +1255,15 @@ bool hasFocusNode() void rebuildWebTextView() { JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue.object(env); - // if it is called during or after DESTROY is handled, the real object of - // WebView can be gone. Check before using it. - if (!obj.get()) - return; - env->CallVoidMethod(obj.get(), m_javaGlue.m_rebuildWebTextView); + env->CallVoidMethod(m_javaGlue.object(env).get(), + m_javaGlue.m_rebuildWebTextView); checkException(env); } void displaySoftKeyboard(bool isTextView) { JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue.object(env); - // if it is called during or after DESTROY is handled, the real object of - // WebView can be gone. Check before using it. - if (!obj.get()) - return; - env->CallVoidMethod(obj.get(), + env->CallVoidMethod(m_javaGlue.object(env).get(), m_javaGlue.m_displaySoftKeyboard, isTextView); checkException(env); } @@ -1321,37 +1271,22 @@ void displaySoftKeyboard(bool isTextView) void viewInvalidate() { JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue.object(env); - // if it is called during or after DESTROY is handled, the real object of - // WebView can be gone. Check before using it. - if (!obj.get()) - return; - env->CallVoidMethod(obj.get(), m_javaGlue.m_viewInvalidate); + env->CallVoidMethod(m_javaGlue.object(env).get(), m_javaGlue.m_viewInvalidate); checkException(env); } void viewInvalidateRect(int l, int t, int r, int b) { JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue.object(env); - // if it is called during or after DESTROY is handled, the real object of - // WebView can be gone. Check before using it. - if (!obj.get()) - return; - env->CallVoidMethod(obj.get(), m_javaGlue.m_viewInvalidateRect, l, r, t, b); + env->CallVoidMethod(m_javaGlue.object(env).get(), m_javaGlue.m_viewInvalidateRect, l, r, t, b); checkException(env); } void postInvalidateDelayed(int64_t delay, const WebCore::IntRect& bounds) { JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue.object(env); - // if it is called during or after DESTROY is handled, the real object of - // WebView can be gone. Check before using it. - if (!obj.get()) - return; - env->CallVoidMethod(obj.get(), m_javaGlue.m_postInvalidateDelayed, - delay, bounds.x(), bounds.y(), bounds.right(), bounds.bottom()); + env->CallVoidMethod(m_javaGlue.object(env).get(), m_javaGlue.m_postInvalidateDelayed, + delay, bounds.x(), bounds.y(), bounds.right(), bounds.bottom()); checkException(env); } @@ -2152,7 +2087,8 @@ static jobject nativeGetSelection(JNIEnv *env, jobject obj) { WebView* view = GET_NATIVE_VIEW(env, obj); LOG_ASSERT(view, "view not set in %s", __FUNCTION__); - return GraphicsJNI::createRegion(env, new SkRegion(view->getSelection())); + String selection = view->getSelection(); + return env->NewString((jchar*)selection.characters(), selection.length()); } #ifdef ANDROID_DUMP_DISPLAY_TREE @@ -2288,7 +2224,7 @@ static JNINativeMethod gJavaWebViewMethods[] = { (void*) nativeFocusNodePointer }, { "nativeGetCursorRingBounds", "()Landroid/graphics/Rect;", (void*) nativeGetCursorRingBounds }, - { "nativeGetSelection", "()Landroid/graphics/Region;", + { "nativeGetSelection", "()Ljava/lang/String;", (void*) nativeGetSelection }, { "nativeHasCursorNode", "()Z", (void*) nativeHasCursorNode }, |
