summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
authorVictoria Lease <violets@google.com>2012-02-13 15:46:16 -0800
committerVictoria Lease <violets@google.com>2012-02-21 11:08:13 -0800
commit66c40fc863939bd103a5256eb48e944508725c53 (patch)
treec6e64c85ff11af2c1a45533fb8fc562c78d08314 /Source
parenta54eb7fa1e850d7096f97065f35ed00bcb5384d3 (diff)
downloadexternal_webkit-66c40fc863939bd103a5256eb48e944508725c53.zip
external_webkit-66c40fc863939bd103a5256eb48e944508725c53.tar.gz
external_webkit-66c40fc863939bd103a5256eb48e944508725c53.tar.bz2
async find-on-page implementation via WebKit
Change-Id: I5804c865f4bce6452213dc89337ff6a5e6100c9e
Diffstat (limited to 'Source')
-rw-r--r--Source/WebCore/platform/android/RenderThemeAndroid.cpp10
-rw-r--r--Source/WebCore/platform/android/RenderThemeAndroid.h3
-rw-r--r--Source/WebCore/platform/graphics/android/GLExtras.cpp51
-rw-r--r--Source/WebCore/platform/graphics/android/GLExtras.h6
-rw-r--r--Source/WebKit/Android.mk1
-rw-r--r--Source/WebKit/android/jni/WebViewCore.cpp139
-rw-r--r--Source/WebKit/android/jni/WebViewCore.h12
-rw-r--r--Source/WebKit/android/nav/FindCanvas.cpp715
-rw-r--r--Source/WebKit/android/nav/FindCanvas.h268
-rw-r--r--Source/WebKit/android/nav/WebView.cpp216
10 files changed, 157 insertions, 1264 deletions
diff --git a/Source/WebCore/platform/android/RenderThemeAndroid.cpp b/Source/WebCore/platform/android/RenderThemeAndroid.cpp
index b570d0e..97110ee 100644
--- a/Source/WebCore/platform/android/RenderThemeAndroid.cpp
+++ b/Source/WebCore/platform/android/RenderThemeAndroid.cpp
@@ -181,6 +181,16 @@ Color RenderThemeAndroid::platformInactiveListBoxSelectionForegroundColor() cons
return Color(Color::transparent);
}
+Color RenderThemeAndroid::platformActiveTextSearchHighlightColor() const
+{
+ return Color(0x00, 0x99, 0xcc, 0x99); // HOLO_DARK
+}
+
+Color RenderThemeAndroid::platformInactiveTextSearchHighlightColor() const
+{
+ return Color(0x33, 0xb5, 0xe5, 0x66); // HOLO_LIGHT
+}
+
int RenderThemeAndroid::baselinePosition(const RenderObject* obj) const
{
// From the description of this function in RenderTheme.h:
diff --git a/Source/WebCore/platform/android/RenderThemeAndroid.h b/Source/WebCore/platform/android/RenderThemeAndroid.h
index 802d3c3..165abf8 100644
--- a/Source/WebCore/platform/android/RenderThemeAndroid.h
+++ b/Source/WebCore/platform/android/RenderThemeAndroid.h
@@ -67,6 +67,9 @@ public:
virtual Color platformActiveListBoxSelectionForegroundColor() const;
virtual Color platformInactiveListBoxSelectionForegroundColor() const;
+ virtual Color platformActiveTextSearchHighlightColor() const;
+ virtual Color platformInactiveTextSearchHighlightColor() const;
+
virtual void systemFont(int, WebCore::FontDescription&) const {}
virtual int minimumMenuListSize(RenderStyle*) const { return 0; }
diff --git a/Source/WebCore/platform/graphics/android/GLExtras.cpp b/Source/WebCore/platform/graphics/android/GLExtras.cpp
index b872951..8a1d2fa 100644
--- a/Source/WebCore/platform/graphics/android/GLExtras.cpp
+++ b/Source/WebCore/platform/graphics/android/GLExtras.cpp
@@ -26,7 +26,6 @@
#include "config.h"
#include "DrawExtra.h"
-#include "FindCanvas.h"
#include "GLExtras.h"
#include "IntRect.h"
#include "TilesManager.h"
@@ -58,8 +57,7 @@
#define MAX_NUMBER_OF_MATCHES_TO_DRAW 101
GLExtras::GLExtras()
- : m_findOnPage(0)
- , m_ring(0)
+ : m_ring(0)
, m_drawExtra(0)
, m_viewport()
{
@@ -170,58 +168,11 @@ void GLExtras::drawCursorRings(const LayerAndroid* layer)
layer ? layer->drawTransform() : 0);
}
-void GLExtras::drawFindOnPage(const LayerAndroid* layer)
-{
- WTF::Vector<MatchInfo>* matches = m_findOnPage->matches();
- XLOG("drawFindOnPage, matches: %p", matches);
- if (!matches || !m_findOnPage->isCurrentLocationValid())
- return;
- std::pair<unsigned, unsigned> matchRange =
- m_findOnPage->getLayerMatchRange(layer ? layer->uniqueId() : -1);
- if (matchRange.first >= matchRange.second)
- return;
-
- int count = matches->size();
- unsigned current = m_findOnPage->currentMatchIndex();
- XLOG("match count: %d", count);
- const TransformationMatrix* drawTransform =
- layer ? layer->drawTransform() : 0;
- if (count < MAX_NUMBER_OF_MATCHES_TO_DRAW)
- for (unsigned i = matchRange.first; i < matchRange.second; i++) {
- MatchInfo& info = matches->at(i);
- const SkRegion& region = info.getLocation();
- SkIRect rect = region.getBounds();
- if (drawTransform) {
- IntRect intRect(rect.fLeft, rect.fTop, rect.width(),
- rect.height());
- IntRect transformedRect = drawTransform->mapRect(intRect);
- rect.setXYWH(transformedRect.x(), transformedRect.y(),
- transformedRect.width(), transformedRect.height());
- }
- if (rect.intersect(m_viewport.fLeft, m_viewport.fTop,
- m_viewport.fRight, m_viewport.fBottom))
- drawRegion(region, i == current, false, drawTransform, COLOR_HOLO_DARK);
-#ifdef DEBUG
- else
- XLOG("Quick rejecting [%dx%d, %d, %d", rect.fLeft, rect.fTop,
- rect.width(), rect.height());
-#endif // DEBUG
- }
- else {
- if (matchRange.first <= current && current < matchRange.second) {
- MatchInfo& info = matches->at(current);
- drawRegion(info.getLocation(), true, false, drawTransform, COLOR_HOLO_DARK);
- }
- }
-}
-
void GLExtras::drawGL(const LayerAndroid* layer)
{
if (m_drawExtra) {
if (m_drawExtra == m_ring)
drawCursorRings(layer);
- else if (m_drawExtra == m_findOnPage)
- drawFindOnPage(layer);
else
m_drawExtra->drawGL(this, layer);
}
diff --git a/Source/WebCore/platform/graphics/android/GLExtras.h b/Source/WebCore/platform/graphics/android/GLExtras.h
index 51ad8d8..72ee41c 100644
--- a/Source/WebCore/platform/graphics/android/GLExtras.h
+++ b/Source/WebCore/platform/graphics/android/GLExtras.h
@@ -32,7 +32,6 @@
#include "SkRegion.h"
namespace android {
- class FindOnPage;
class CursorRing;
}
@@ -47,9 +46,6 @@ public:
virtual ~GLExtras();
void drawGL(const LayerAndroid* layer);
- void setFindOnPageExtra(android::FindOnPage* findOnPage) {
- m_findOnPage = findOnPage;
- }
void setCursorRingExtra(android::CursorRing* ring) { m_ring = ring; }
void setDrawExtra(android::DrawExtra* extra) { m_drawExtra = extra; }
void setViewport(const SkRect & viewport) { m_viewport = viewport; }
@@ -60,9 +56,7 @@ public:
private:
void drawRing(SkRect& srcRect, Color color, const TransformationMatrix* drawMat);
void drawCursorRings(const LayerAndroid* layer);
- void drawFindOnPage(const LayerAndroid* layer);
- android::FindOnPage* m_findOnPage;
android::CursorRing* m_ring;
android::DrawExtra* m_drawExtra;
SkRect m_viewport;
diff --git a/Source/WebKit/Android.mk b/Source/WebKit/Android.mk
index ee7f3ce..68ba036 100644
--- a/Source/WebKit/Android.mk
+++ b/Source/WebKit/Android.mk
@@ -89,7 +89,6 @@ LOCAL_SRC_FILES += \
android/nav/CachedNode.cpp \
android/nav/CachedRoot.cpp \
android/nav/DrawExtra.cpp \
- android/nav/FindCanvas.cpp \
android/nav/SelectText.cpp \
android/nav/WebView.cpp \
\
diff --git a/Source/WebKit/android/jni/WebViewCore.cpp b/Source/WebKit/android/jni/WebViewCore.cpp
index 8d819b2..a8b8499 100644
--- a/Source/WebKit/android/jni/WebViewCore.cpp
+++ b/Source/WebKit/android/jni/WebViewCore.cpp
@@ -44,6 +44,7 @@
#include "CSSValueKeywords.h"
#include "DatabaseTracker.h"
#include "Document.h"
+#include "DocumentMarkerController.h"
#include "DOMWindow.h"
#include "DOMSelection.h"
#include "Element.h"
@@ -296,7 +297,6 @@ struct WebViewCore::JavaGlue {
jmethodID m_destroySurface;
jmethodID m_getContext;
jmethodID m_keepScreenOn;
- jmethodID m_sendFindAgain;
jmethodID m_showRect;
jmethodID m_centerFitRect;
jmethodID m_setScrollbarModes;
@@ -306,6 +306,7 @@ struct WebViewCore::JavaGlue {
jmethodID m_setWebTextViewAutoFillable;
jmethodID m_selectAt;
jmethodID m_initEditField;
+ jmethodID m_updateMatchCount;
AutoJObject object(JNIEnv* env) {
// We hold a weak reference to the Java WebViewCore to avoid memeory
// leaks due to circular references when WebView.destroy() is not
@@ -374,6 +375,9 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m
, m_isPaused(false)
, m_cacheMode(0)
, m_fullscreenVideoMode(false)
+ , m_matchCount(0)
+ , m_activeMatchIndex(0)
+ , m_activeMatch(0)
, m_pluginInvalTimer(this, &WebViewCore::pluginInvalTimerFired)
, m_screenOnCounter(0)
, m_currentNodeDomNavigationAxis(0)
@@ -429,7 +433,6 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m
m_javaGlue->m_destroySurface = GetJMethod(env, clazz, "destroySurface", "(Landroid/webkit/ViewManager$ChildView;)V");
m_javaGlue->m_getContext = GetJMethod(env, clazz, "getContext", "()Landroid/content/Context;");
m_javaGlue->m_keepScreenOn = GetJMethod(env, clazz, "keepScreenOn", "(Z)V");
- m_javaGlue->m_sendFindAgain = GetJMethod(env, clazz, "sendFindAgain", "()V");
m_javaGlue->m_showRect = GetJMethod(env, clazz, "showRect", "(IIIIIIFFFF)V");
m_javaGlue->m_centerFitRect = GetJMethod(env, clazz, "centerFitRect", "(IIII)V");
m_javaGlue->m_setScrollbarModes = GetJMethod(env, clazz, "setScrollbarModes", "(II)V");
@@ -441,6 +444,7 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m
m_javaGlue->m_setWebTextViewAutoFillable = GetJMethod(env, clazz, "setWebTextViewAutoFillable", "(ILjava/lang/String;)V");
m_javaGlue->m_selectAt = GetJMethod(env, clazz, "selectAt", "(II)V");
m_javaGlue->m_initEditField = GetJMethod(env, clazz, "initEditField", "(ILjava/lang/String;II)V");
+ m_javaGlue->m_updateMatchCount = GetJMethod(env, clazz, "updateMatchCount", "(IILjava/lang/String;)V");
env->DeleteLocalRef(clazz);
env->SetIntField(javaWebViewCore, gWebViewCoreFields.m_nativeClass, (jint)this);
@@ -748,15 +752,6 @@ void WebViewCore::recordPictureSet(PictureSet* content)
DBG_NAV_LOG("call updateFrameCache");
updateFrameCache();
#endif
- if (m_findIsUp) {
- ALOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");
- JNIEnv* env = JSC::Bindings::getJNIEnv();
- AutoJObject javaObject = m_javaGlue->object(env);
- if (javaObject.get()) {
- env->CallVoidMethod(javaObject.get(), m_javaGlue->m_sendFindAgain);
- checkException(env);
- }
- }
}
// note: updateCursorBounds is called directly by the WebView thread
@@ -4357,6 +4352,109 @@ void WebViewCore::insertText(const WTF::String &text)
client->setUiGeneratedSelectionChange(false);
}
+void WebViewCore::resetFindOnPage()
+{
+ m_searchText.truncate(0);
+ m_matchCount = 0;
+ m_activeMatchIndex = 0;
+ m_activeMatch = 0;
+}
+
+int WebViewCore::findTextOnPage(const WTF::String &text)
+{
+ resetFindOnPage(); // reset even if parameters are bad
+
+ WebCore::Frame* frame = m_mainFrame;
+ if (!frame)
+ return 0;
+
+ m_searchText = text;
+ FindOptions findOptions = WebCore::CaseInsensitive;
+
+ do {
+ frame->document()->markers()->removeMarkers(DocumentMarker::TextMatch);
+ m_matchCount += frame->editor()->countMatchesForText(text, findOptions,
+ 0, true);
+ updateMatchCount();
+ frame->editor()->setMarkedTextMatchesAreHighlighted(true);
+ frame = frame->tree()->traverseNextWithWrap(false);
+ } while (frame);
+
+ m_activeMatchIndex = m_matchCount - 1; // prime first findNext
+ findNextOnPage(true);
+ return m_matchCount;
+}
+
+void WebViewCore::findNextOnPage(bool forward)
+{
+ if (!m_mainFrame)
+ return;
+ if (!m_matchCount)
+ return;
+
+ EditorClientAndroid* client = static_cast<EditorClientAndroid*>(
+ m_mainFrame->editor()->client());
+ client->setUiGeneratedSelectionChange(true);
+
+ // Clear previous active match.
+ if (m_activeMatch) {
+ m_mainFrame->document()->markers()->setMarkersActive(
+ m_activeMatch.get(), false);
+ }
+
+ FindOptions findOptions = WebCore::CaseInsensitive
+ | WebCore::StartInSelection | WebCore::WrapAround;
+ if (!forward)
+ findOptions |= WebCore::Backwards;
+
+ // Start from the previous active match.
+ if (m_activeMatch) {
+ m_mainFrame->selection()->setSelection(m_activeMatch.get());
+ }
+
+ bool found = m_mainFrame->editor()->findString(m_searchText, findOptions);
+ if (found) {
+ VisibleSelection selection(m_mainFrame->selection()->selection());
+ if (selection.isNone() || selection.start() == selection.end()) {
+ // Temporary workaround for findString() refusing to select text
+ // marked "-webkit-user-select: none".
+ m_activeMatchIndex = 0;
+ m_activeMatch = 0;
+ } else {
+ // Mark current match "active".
+ if (forward) {
+ ++m_activeMatchIndex;
+ if (m_activeMatchIndex == m_matchCount)
+ m_activeMatchIndex = 0;
+ } else {
+ if (m_activeMatchIndex == 0)
+ m_activeMatchIndex = m_matchCount;
+ --m_activeMatchIndex;
+ }
+ m_activeMatch = selection.firstRange();
+ m_mainFrame->document()->markers()->setMarkersActive(
+ m_activeMatch.get(), true);
+ }
+ updateMatchCount();
+ }
+
+ // Clear selection so it doesn't display.
+ m_mainFrame->selection()->clear();
+ client->setUiGeneratedSelectionChange(false);
+}
+
+void WebViewCore::updateMatchCount() const
+{
+ JNIEnv* env = JSC::Bindings::getJNIEnv();
+ AutoJObject javaObject = m_javaGlue->object(env);
+ if (!javaObject.get())
+ return;
+ jstring javaText = wtfStringToJstring(env, m_searchText, true);
+ env->CallVoidMethod(javaObject.get(), m_javaGlue->m_updateMatchCount,
+ m_activeMatchIndex, m_matchCount, javaText);
+ checkException(env);
+}
+
String WebViewCore::getText(int startX, int startY, int endX, int endY)
{
String text;
@@ -5056,6 +5154,21 @@ static void SelectAll(JNIEnv* env, jobject obj, jint nativeClass)
viewImpl->focusedFrame()->selection()->selectAll();
}
+static int FindAll(JNIEnv* env, jobject obj, jint nativeClass,
+ jstring text)
+{
+ WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
+ WTF::String wtfText = jstringToWtfString(env, text);
+ return viewImpl->findTextOnPage(wtfText);
+}
+
+static void FindNext(JNIEnv* env, jobject obj, jint nativeClass,
+ jboolean forward)
+{
+ WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
+ viewImpl->findNextOnPage(forward);
+}
+
// ----------------------------------------------------------------------------
/*
@@ -5186,6 +5299,10 @@ static JNINativeMethod gJavaWebViewCoreMethods[] = {
(void*) SelectAll },
{ "nativeCertTrustChanged","()V",
(void*) nativeCertTrustChanged },
+ { "nativeFindAll", "(ILjava/lang/String;)I",
+ (void*) FindAll },
+ { "nativeFindNext", "(IZ)V",
+ (void*) FindNext },
};
int registerWebViewCore(JNIEnv* env)
diff --git a/Source/WebKit/android/jni/WebViewCore.h b/Source/WebKit/android/jni/WebViewCore.h
index 952e39d..41e681e 100644
--- a/Source/WebKit/android/jni/WebViewCore.h
+++ b/Source/WebKit/android/jni/WebViewCore.h
@@ -560,6 +560,12 @@ namespace android {
WTF::String getText(int startX, int startY, int endX, int endY);
void insertText(const WTF::String &text);
+ // find on page
+ void resetFindOnPage();
+ int findTextOnPage(const WTF::String &text);
+ void findNextOnPage(bool forward);
+ void updateMatchCount() const;
+
#if ENABLE(VIDEO)
void enterFullscreenForVideoLayer(int layerId, const WTF::String& url);
void exitFullscreenVideo();
@@ -757,6 +763,12 @@ namespace android {
int m_cacheMode;
bool m_fullscreenVideoMode;
+ // find on page data
+ WTF::String m_searchText;
+ int m_matchCount;
+ int m_activeMatchIndex;
+ RefPtr<WebCore::Range> m_activeMatch;
+
SkTDArray<PluginWidgetAndroid*> m_plugins;
WebCore::Timer<WebViewCore> m_pluginInvalTimer;
void pluginInvalTimerFired(WebCore::Timer<WebViewCore>*) {
diff --git a/Source/WebKit/android/nav/FindCanvas.cpp b/Source/WebKit/android/nav/FindCanvas.cpp
deleted file mode 100644
index dca9a75..0000000
--- a/Source/WebKit/android/nav/FindCanvas.cpp
+++ /dev/null
@@ -1,715 +0,0 @@
-/*
- * Copyright 2008, 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 "webviewglue"
-
-#include "config.h"
-#include "FindCanvas.h"
-#include "LayerAndroid.h"
-#include "IntRect.h"
-#include "SelectText.h"
-#include "SkBlurMaskFilter.h"
-#include "SkCornerPathEffect.h"
-#include "SkRect.h"
-#include "SkUtils.h"
-
-#include <utils/Log.h>
-
-#define INTEGER_OUTSET 2
-
-namespace android {
-
-// MatchInfo methods
-////////////////////////////////////////////////////////////////////////////////
-
-MatchInfo::MatchInfo() {
- m_picture = 0;
-}
-
-MatchInfo::~MatchInfo() {
- SkSafeUnref(m_picture);
-}
-
-MatchInfo::MatchInfo(const MatchInfo& src) {
- m_layerId = src.m_layerId;
- m_location = src.m_location;
- m_picture = src.m_picture;
- SkSafeRef(m_picture);
-}
-
-void MatchInfo::set(const SkRegion& region, SkPicture* pic, int layerId) {
- SkSafeUnref(m_picture);
- m_layerId = layerId;
- m_location = region;
- m_picture = pic;
- SkASSERT(pic);
- pic->ref();
-}
-
-// GlyphSet methods
-////////////////////////////////////////////////////////////////////////////////
-
-GlyphSet::GlyphSet(const SkPaint& paint, const UChar* lower, const UChar* upper,
- size_t byteLength) {
- SkPaint clonePaint(paint);
- clonePaint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
- mTypeface = paint.getTypeface();
- mCount = clonePaint.textToGlyphs(lower, byteLength, NULL);
- if (mCount > MAX_STORAGE_COUNT) {
- mLowerGlyphs = new uint16_t[2*mCount];
- } else {
- mLowerGlyphs = &mStorage[0];
- }
- // Use one array, and have mUpperGlyphs point to a portion of it,
- // so that we can reduce the number of new/deletes
- mUpperGlyphs = mLowerGlyphs + mCount;
- int count2 = clonePaint.textToGlyphs(lower, byteLength, mLowerGlyphs);
- SkASSERT(mCount == count2);
- count2 = clonePaint.textToGlyphs(upper, byteLength, mUpperGlyphs);
- SkASSERT(mCount == count2);
-}
-
-GlyphSet::~GlyphSet() {
- // Do not need to delete mTypeface, which is not owned by us.
- if (mCount > MAX_STORAGE_COUNT) {
- delete[] mLowerGlyphs;
- } // Otherwise, we just used local storage space, so no need to delete
- // Also do not need to delete mUpperGlyphs, which simply points to a
- // part of mLowerGlyphs
-}
-
-GlyphSet& GlyphSet::operator=(GlyphSet& src) {
- mTypeface = src.mTypeface;
- mCount = src.mCount;
- if (mCount > MAX_STORAGE_COUNT) {
- mLowerGlyphs = new uint16_t[2*mCount];
- } else {
- mLowerGlyphs = &mStorage[0];
- }
- memcpy(mLowerGlyphs, src.mLowerGlyphs, 2*mCount*sizeof(uint16_t));
- mUpperGlyphs = mLowerGlyphs + mCount;
- return *this;
-}
-
-bool GlyphSet::characterMatches(uint16_t c, int index) {
- SkASSERT(index < mCount && index >= 0);
- return c == mLowerGlyphs[index] || c == mUpperGlyphs[index];
-}
-
-// FindCanvas methods
-////////////////////////////////////////////////////////////////////////////////
-
-FindCanvas::FindCanvas(int width, int height, const UChar* lower,
- const UChar* upper, size_t byteLength)
- : mLowerText(lower)
- , mUpperText(upper)
- , mLength(byteLength)
- , mNumFound(0) {
- // the text has been provided in read order. Reverse as needed so the
- // result contains left-to-right characters.
- const uint16_t* start = mLowerText;
- size_t count = byteLength >> 1;
- const uint16_t* end = mLowerText + count;
- while (start < end) {
- SkUnichar ch = SkUTF16_NextUnichar(&start);
- WTF::Unicode::Direction charDirection = WTF::Unicode::direction(ch);
- if (WTF::Unicode::RightToLeftArabic == charDirection
- || WTF::Unicode::RightToLeft == charDirection) {
- mLowerReversed.clear();
- mLowerReversed.append(mLowerText, count);
- WebCore::ReverseBidi(mLowerReversed.begin(), count);
- mLowerText = mLowerReversed.begin();
- mUpperReversed.clear();
- mUpperReversed.append(mUpperText, count);
- WebCore::ReverseBidi(mUpperReversed.begin(), count);
- mUpperText = mUpperReversed.begin();
- break;
- }
- }
-
- setBounder(&mBounder);
- mOutset = -SkIntToScalar(INTEGER_OUTSET);
- mMatches = new WTF::Vector<MatchInfo>();
- mWorkingIndex = 0;
- mWorkingCanvas = 0;
- mWorkingPicture = 0;
-}
-
-FindCanvas::~FindCanvas() {
- setBounder(NULL);
- /* Just in case getAndClear was not called. */
- delete mMatches;
- SkSafeUnref(mWorkingPicture);
-}
-
-// Each version of addMatch returns a rectangle for a match.
-// Not all of the parameters are used by each version.
-SkRect FindCanvas::addMatchNormal(int index,
- const SkPaint& paint, int count, const uint16_t* glyphs,
- const SkScalar pos[], SkScalar y) {
- const uint16_t* lineStart = glyphs - index;
- /* Use the original paint, since "text" is in glyphs */
- SkScalar before = paint.measureText(lineStart, index * sizeof(uint16_t), 0);
- SkRect rect;
- rect.fLeft = pos[0] + before;
- int countInBytes = count * sizeof(uint16_t);
- rect.fRight = paint.measureText(glyphs, countInBytes, 0) + rect.fLeft;
- SkPaint::FontMetrics fontMetrics;
- paint.getFontMetrics(&fontMetrics);
- SkScalar baseline = y;
- rect.fTop = baseline + fontMetrics.fAscent;
- rect.fBottom = baseline + fontMetrics.fDescent;
- const SkMatrix& matrix = getTotalMatrix();
- matrix.mapRect(&rect);
- // Add the text to our picture.
- SkCanvas* canvas = getWorkingCanvas();
- int saveCount = canvas->save();
- canvas->concat(matrix);
- canvas->drawText(glyphs, countInBytes, pos[0] + before, y, paint);
- canvas->restoreToCount(saveCount);
- return rect;
-}
-
-SkRect FindCanvas::addMatchPos(int index,
- const SkPaint& paint, int count, const uint16_t* glyphs,
- const SkScalar xPos[], SkScalar /* y */) {
- SkRect r;
- r.setEmpty();
- const SkPoint* temp = reinterpret_cast<const SkPoint*> (xPos);
- const SkPoint* points = &temp[index];
- int countInBytes = count * sizeof(uint16_t);
- SkPaint::FontMetrics fontMetrics;
- paint.getFontMetrics(&fontMetrics);
- // Need to check each character individually, since the heights may be
- // different.
- for (int j = 0; j < count; j++) {
- SkRect bounds;
- bounds.fLeft = points[j].fX;
- bounds.fRight = bounds.fLeft +
- paint.measureText(&glyphs[j], sizeof(uint16_t), 0);
- SkScalar baseline = points[j].fY;
- bounds.fTop = baseline + fontMetrics.fAscent;
- bounds.fBottom = baseline + fontMetrics.fDescent;
- /* Accumulate and then add the resulting rect to mMatches */
- r.join(bounds);
- }
- SkMatrix matrix = getTotalMatrix();
- matrix.mapRect(&r);
- SkCanvas* canvas = getWorkingCanvas();
- int saveCount = canvas->save();
- canvas->concat(matrix);
- canvas->drawPosText(glyphs, countInBytes, points, paint);
- canvas->restoreToCount(saveCount);
- return r;
-}
-
-SkRect FindCanvas::addMatchPosH(int index,
- const SkPaint& paint, int count, const uint16_t* glyphs,
- const SkScalar position[], SkScalar constY) {
- SkRect r;
- // We only care about the positions starting at the index of our match
- const SkScalar* xPos = &position[index];
- // This assumes that the position array is monotonic increasing
- // The left bounds will be the position of the left most character
- r.fLeft = xPos[0];
- // The right bounds will be the position of the last character plus its
- // width
- int lastIndex = count - 1;
- r.fRight = paint.measureText(&glyphs[lastIndex], sizeof(uint16_t), 0)
- + xPos[lastIndex];
- // Grab font metrics to determine the top and bottom of the bounds
- SkPaint::FontMetrics fontMetrics;
- paint.getFontMetrics(&fontMetrics);
- r.fTop = constY + fontMetrics.fAscent;
- r.fBottom = constY + fontMetrics.fDescent;
- const SkMatrix& matrix = getTotalMatrix();
- matrix.mapRect(&r);
- SkCanvas* canvas = getWorkingCanvas();
- int saveCount = canvas->save();
- canvas->concat(matrix);
- canvas->drawPosTextH(glyphs, count * sizeof(uint16_t), xPos, constY, paint);
- canvas->restoreToCount(saveCount);
- return r;
-}
-
-void FindCanvas::drawLayers(LayerAndroid* layer, FindOnPage& findOnPage) {
-#if USE(ACCELERATED_COMPOSITING)
- int layerId = layer->uniqueId();
- unsigned matchesBegin = found();
- SkPicture* picture = layer->picture();
- if (picture) {
- setLayerId(layerId);
- drawPicture(*picture);
- }
- findOnPage.setLayerMatchRange(layerId,
- std::pair<unsigned, unsigned>(matchesBegin, found()));
- for (int i = 0; i < layer->countChildren(); i++)
- drawLayers(layer->getChild(i), findOnPage);
-#endif
-}
-
-void FindCanvas::drawText(const void* text, size_t byteLength, SkScalar x,
- SkScalar y, const SkPaint& paint) {
- findHelper(text, byteLength, paint, &x, y, &FindCanvas::addMatchNormal);
-}
-
-void FindCanvas::drawPosText(const void* text, size_t byteLength,
- const SkPoint pos[], const SkPaint& paint) {
- // Pass in the first y coordinate for y so that we can check to see whether
- // it is lower than the last draw call (to check if we are continuing to
- // another line).
- findHelper(text, byteLength, paint, (const SkScalar*) pos, pos[0].fY,
- &FindCanvas::addMatchPos);
-}
-
-void FindCanvas::drawPosTextH(const void* text, size_t byteLength,
- const SkScalar xpos[], SkScalar constY,
- const SkPaint& paint) {
- findHelper(text, byteLength, paint, xpos, constY,
- &FindCanvas::addMatchPosH);
-}
-
-/* The current behavior is to skip substring matches. This means that in the
- * string
- * batbatbat
- * a search for
- * batbat
- * will return 1 match. If the desired behavior is to return 2 matches, define
- * INCLUDE_SUBSTRING_MATCHES to be 1.
- */
-#define INCLUDE_SUBSTRING_MATCHES 0
-
-// Need a quick way to know a maximum distance between drawText calls to know if
-// they are part of the same logical phrase when searching. By crude
-// inspection, half the point size seems a good guess at the width of a space
-// character.
-static inline SkScalar approximateSpaceWidth(const SkPaint& paint) {
- return SkScalarHalf(paint.getTextSize());
-}
-
-void FindCanvas::findHelper(const void* text, size_t byteLength,
- const SkPaint& paint, const SkScalar positions[],
- SkScalar y,
- SkRect (FindCanvas::*addMatch)(int index,
- const SkPaint& paint, int count,
- const uint16_t* glyphs,
- const SkScalar positions[], SkScalar y)) {
- SkASSERT(paint.getTextEncoding() == SkPaint::kGlyphID_TextEncoding);
- SkASSERT(mMatches);
- GlyphSet* glyphSet = getGlyphs(paint);
- const int count = glyphSet->getCount();
- int numCharacters = byteLength >> 1;
- const uint16_t* chars = (const uint16_t*) text;
- // This block will check to see if we are continuing from another line. If
- // so, the user needs to have added a space, which we do not draw.
- if (mWorkingIndex) {
- SkPoint newY;
- getTotalMatrix().mapXY(0, y, &newY);
- SkIRect workingBounds = mWorkingRegion.getBounds();
- int newYInt = SkScalarRound(newY.fY);
- if (workingBounds.fTop > newYInt) {
- // The new text is above the working region, so we know it's not
- // a continuation.
- resetWorkingCanvas();
- mWorkingIndex = 0;
- mWorkingRegion.setEmpty();
- } else if (workingBounds.fBottom < newYInt) {
- // Now we know that this line is lower than our partial match.
- SkPaint clonePaint(paint);
- clonePaint.setTextEncoding(SkPaint::kUTF8_TextEncoding);
- uint16_t space;
- clonePaint.textToGlyphs(" ", 1, &space);
- if (glyphSet->characterMatches(space, mWorkingIndex)) {
- mWorkingIndex++;
- if (mWorkingIndex == count) {
- // We already know that it is not clipped out because we
- // checked for that before saving the working region.
- insertMatchInfo(mWorkingRegion);
-
- resetWorkingCanvas();
- mWorkingIndex = 0;
- mWorkingRegion.setEmpty();
- // We have found a match, so continue on this line from
- // scratch.
- }
- } else {
- resetWorkingCanvas();
- mWorkingIndex = 0;
- mWorkingRegion.setEmpty();
- }
- }
- // If neither one is true, then we are likely continuing on the same
- // line, but are in a new draw call because the paint has changed. In
- // this case, we can continue without adding a space.
- }
- // j is the position in the search text
- // Start off with mWorkingIndex in case we are continuing from a prior call
- int j = mWorkingIndex;
- // index is the position in the drawn text
- int index = 0;
- for ( ; index != numCharacters; index++) {
- if (glyphSet->characterMatches(chars[index], j)) {
- // The jth character in the search text matches the indexth position
- // in the drawn text, so increase j.
- j++;
- if (j != count) {
- continue;
- }
- // The last count characters match, so we found the entire
- // search string.
- int remaining = count - mWorkingIndex;
- int matchIndex = index - remaining + 1;
- // Set up a pointer to the matching text in 'chars'.
- const uint16_t* glyphs = chars + matchIndex;
- SkRect rect = (this->*addMatch)(matchIndex, paint,
- remaining, glyphs, positions, y);
- // We need an SkIRect for SkRegion operations.
- SkIRect iRect;
- rect.roundOut(&iRect);
- // Want to outset the drawn rectangle by the same amount as
- // mOutset
- iRect.inset(-INTEGER_OUTSET, -INTEGER_OUTSET);
- SkRegion regionToAdd(iRect);
- if (!mWorkingRegion.isEmpty()) {
- // If this is on the same line as our working region, make
- // sure that they are close enough together that they are
- // supposed to be part of the same text string.
- // The width of two spaces has arbitrarily been chosen.
- const SkIRect& workingBounds = mWorkingRegion.getBounds();
- if (workingBounds.fTop <= iRect.fBottom &&
- workingBounds.fBottom >= iRect.fTop &&
- SkIntToScalar(iRect.fLeft - workingBounds.fRight) >
- approximateSpaceWidth(paint)) {
- index = -1; // Will increase to 0 on next run
- // In this case, we need to start from the beginning of
- // the text being searched and our search term.
- j = 0;
- mWorkingIndex = 0;
- mWorkingRegion.setEmpty();
- continue;
- }
- // Add the mWorkingRegion, which contains rectangles from
- // the previous line(s).
- regionToAdd.op(mWorkingRegion, SkRegion::kUnion_Op);
- }
- insertMatchInfo(regionToAdd);
-#if INCLUDE_SUBSTRING_MATCHES
- // Reset index to the location of the match and reset j to the
- // beginning, so that on the next iteration of the loop, index
- // will advance by 1 and we will compare the next character in
- // chars to the first character in the GlyphSet.
- index = matchIndex;
-#endif
- // Whether the clip contained it or not, we need to start over
- // with our recording canvas
- resetWorkingCanvas();
- } else {
- // Index needs to be set to index - j + 1.
- // This is a ridiculous case, but imagine the situation where the
- // user is looking for the string "jjog" in the drawText call for
- // "jjjog". The first two letters match. However, when the index
- // is 2, and we discover that 'o' and 'j' do not match, we should go
- // back to 1, where we do, in fact, have a match
- // FIXME: This does not work if (as in our example) "jj" is in one
- // draw call and "jog" is in the next. Doing so would require a
- // stack, keeping track of multiple possible working indeces and
- // regions. This is likely an uncommon case.
- index = index - j; // index will be increased by one on the next
- // iteration
- }
- // We reach here in one of two cases:
- // 1) We just completed a match, so any working rectangle/index is no
- // longer needed, and we will start over from the beginning
- // 2) The glyphs do not match, so we start over at the beginning of
- // the search string.
- j = 0;
- mWorkingIndex = 0;
- mWorkingRegion.setEmpty();
- }
- // At this point, we have searched all of the text in the current drawText
- // call.
- // Keep track of a partial match that may start on this line.
- if (j > 0) { // if j is greater than 0, we have a partial match
- int relativeCount = j - mWorkingIndex; // Number of characters in this
- // part of the match.
- int partialIndex = index - relativeCount; // Index that starts our
- // partial match.
- const uint16_t* partialGlyphs = chars + partialIndex;
- SkRect partial = (this->*addMatch)(partialIndex, paint, relativeCount,
- partialGlyphs, positions, y);
- partial.inset(mOutset, mOutset);
- SkIRect dest;
- partial.roundOut(&dest);
- mWorkingRegion.op(dest, SkRegion::kUnion_Op);
- mWorkingIndex = j;
- return;
- }
- // This string doesn't go into the next drawText, so reset our working
- // variables
- mWorkingRegion.setEmpty();
- mWorkingIndex = 0;
-}
-
-SkCanvas* FindCanvas::getWorkingCanvas() {
- if (!mWorkingPicture) {
- mWorkingPicture = new SkPicture;
- mWorkingCanvas = mWorkingPicture->beginRecording(0,0);
- }
- return mWorkingCanvas;
-}
-
-GlyphSet* FindCanvas::getGlyphs(const SkPaint& paint) {
- SkTypeface* typeface = paint.getTypeface();
- GlyphSet* end = mGlyphSets.end();
- for (GlyphSet* ptr = mGlyphSets.begin();ptr != end; ptr++) {
- if (ptr->getTypeface() == typeface) {
- return ptr;
- }
- }
-
- GlyphSet set(paint, mLowerText, mUpperText, mLength);
- *mGlyphSets.append() = set;
- return &(mGlyphSets.top());
-}
-
-void FindCanvas::insertMatchInfo(const SkRegion& region) {
- mNumFound++;
- mWorkingPicture->endRecording();
- MatchInfo matchInfo;
- mMatches->append(matchInfo);
- ALOGD("%s region=%p pict=%p layer=%d", __FUNCTION__,
- &region, mWorkingPicture, mLayerId);
- mMatches->last().set(region, mWorkingPicture, mLayerId);
-}
-
-void FindCanvas::resetWorkingCanvas() {
- mWorkingPicture->unref();
- mWorkingPicture = 0;
- // Do not need to reset mWorkingCanvas itself because we only access it via
- // getWorkingCanvas.
-}
-
-// This function sets up the paints that are used to draw the matches.
-void FindOnPage::setUpFindPaint() {
- // Set up the foreground paint
- m_findPaint.setAntiAlias(true);
- const SkScalar roundiness = SkIntToScalar(2);
- SkCornerPathEffect* cornerEffect = new SkCornerPathEffect(roundiness);
- m_findPaint.setPathEffect(cornerEffect);
- m_findPaint.setARGB(255, 132, 190, 0);
-
- // Set up the background blur paint.
- m_findBlurPaint.setAntiAlias(true);
- m_findBlurPaint.setARGB(204, 0, 0, 0);
- m_findBlurPaint.setPathEffect(cornerEffect);
- cornerEffect->unref();
- SkMaskFilter* blurFilter = SkBlurMaskFilter::Create(SK_Scalar1,
- SkBlurMaskFilter::kNormal_BlurStyle);
- m_findBlurPaint.setMaskFilter(blurFilter)->unref();
- m_isFindPaintSetUp = true;
-}
-
-IntRect FindOnPage::currentMatchBounds() const {
- IntRect noBounds = IntRect(0, 0, 0, 0);
- if (!m_matches || !m_matches->size())
- return noBounds;
- MatchInfo& info = (*m_matches)[m_findIndex];
- return info.getLocation().getBounds();
-}
-
-bool FindOnPage::currentMatchIsInLayer() const {
- if (!m_matches || !m_matches->size())
- return false;
- MatchInfo& info = (*m_matches)[m_findIndex];
- return info.isInLayer();
-}
-
-int FindOnPage::currentMatchLayerId() const {
- return (*m_matches)[m_findIndex].layerId();
-}
-
-// This function is only used by findNext and setMatches. In it, we store
-// upper left corner of the match specified by m_findIndex in
-// m_currentMatchLocation.
-void FindOnPage::storeCurrentMatchLocation() {
- SkASSERT(m_findIndex < m_matches->size());
- const SkIRect& bounds = (*m_matches)[m_findIndex].getLocation().getBounds();
- m_currentMatchLocation.set(bounds.fLeft, bounds.fTop);
- m_hasCurrentLocation = true;
-}
-
-// Put a cap on the number of matches to draw. If the current page has more
-// matches than this, only draw the focused match.
-#define MAX_NUMBER_OF_MATCHES_TO_DRAW 101
-
-void FindOnPage::drawLegacy(SkCanvas* canvas, LayerAndroid* layer, IntRect* inval) {
- if (!m_lastBounds.isEmpty()) {
- inval->unite(m_lastBounds);
- m_lastBounds.setEmpty();
- }
- if (!m_hasCurrentLocation || !m_matches || !m_matches->size())
- return;
- int layerId = layer ? layer->uniqueId() : -1;
- if (m_findIndex >= m_matches->size())
- m_findIndex = 0;
- const MatchInfo& matchInfo = (*m_matches)[m_findIndex];
- const SkRegion& currentMatchRegion = matchInfo.getLocation();
-
- // Set up the paints used for drawing the matches
- if (!m_isFindPaintSetUp)
- setUpFindPaint();
-
- // Draw the current match
- if (matchInfo.layerId() == layerId) {
- drawMatch(currentMatchRegion, canvas, true);
- // Now draw the picture, so that it shows up on top of the rectangle
- int saveCount = canvas->save();
- SkPath matchPath;
- currentMatchRegion.getBoundaryPath(&matchPath);
- canvas->clipPath(matchPath);
- canvas->drawPicture(*matchInfo.getPicture());
- canvas->restoreToCount(saveCount);
- const SkMatrix& matrix = canvas->getTotalMatrix();
- const SkRect& localBounds = matchPath.getBounds();
- SkRect globalBounds;
- matrix.mapRect(&globalBounds, localBounds);
- globalBounds.round(&m_lastBounds);
- inval->unite(m_lastBounds);
- }
- // Draw the rest
- unsigned numberOfMatches = m_matches->size();
- if (numberOfMatches > 1
- && numberOfMatches < MAX_NUMBER_OF_MATCHES_TO_DRAW) {
- for (unsigned i = 0; i < numberOfMatches; i++) {
- // The current match has already been drawn
- if (i == m_findIndex)
- continue;
- if ((*m_matches)[i].layerId() != layerId)
- continue;
- const SkRegion& region = (*m_matches)[i].getLocation();
- // Do not draw matches which intersect the current one, or if it is
- // offscreen
- if (currentMatchRegion.intersects(region))
- continue;
- SkRect bounds;
- bounds.set(region.getBounds());
- if (canvas->quickReject(bounds, SkCanvas::kAA_EdgeType))
- continue;
- drawMatch(region, canvas, false);
- }
- }
-}
-
-// Draw the match specified by region to the canvas.
-void FindOnPage::drawMatch(const SkRegion& region, SkCanvas* canvas,
- bool focused)
-{
- // For the match which has focus, use a filled paint. For the others, use
- // a stroked paint.
- if (focused) {
- m_findPaint.setStyle(SkPaint::kFill_Style);
- m_findBlurPaint.setStyle(SkPaint::kFill_Style);
- } else {
- m_findPaint.setStyle(SkPaint::kStroke_Style);
- m_findPaint.setStrokeWidth(SK_Scalar1);
- m_findBlurPaint.setStyle(SkPaint::kStroke_Style);
- m_findBlurPaint.setStrokeWidth(SkIntToScalar(2));
- }
- // Find the path for the current match
- SkPath matchPath;
- region.getBoundaryPath(&matchPath);
- // Offset the path for a blurred shadow
- SkPath blurPath;
- matchPath.offset(SK_Scalar1, SkIntToScalar(2), &blurPath);
- int saveCount = 0;
- if (!focused) {
- saveCount = canvas->save();
- canvas->clipPath(matchPath, SkRegion::kDifference_Op);
- }
- // Draw the blurred background
- canvas->drawPath(blurPath, m_findBlurPaint);
- if (!focused)
- canvas->restoreToCount(saveCount);
- // Draw the foreground
- canvas->drawPath(matchPath, m_findPaint);
-}
-
-void FindOnPage::findNext(bool forward)
-{
- if (!m_matches || !m_matches->size() || !m_hasCurrentLocation)
- return;
- if (forward) {
- m_findIndex++;
- if (m_findIndex == m_matches->size())
- m_findIndex = 0;
- } else {
- if (m_findIndex == 0) {
- m_findIndex = m_matches->size() - 1;
- } else {
- m_findIndex--;
- }
- }
- storeCurrentMatchLocation();
-}
-
-// With this call, WebView takes ownership of matches, and is responsible for
-// deleting it.
-void FindOnPage::setMatches(WTF::Vector<MatchInfo>* matches)
-{
- if (m_matches)
- delete m_matches;
- m_matches = matches;
- if (m_matches->size()) {
- if (m_hasCurrentLocation) {
- for (unsigned i = 0; i < m_matches->size(); i++) {
- const SkIRect& rect = (*m_matches)[i].getLocation().getBounds();
- if (rect.fLeft == m_currentMatchLocation.fX
- && rect.fTop == m_currentMatchLocation.fY) {
- m_findIndex = i;
- return;
- }
- }
- }
- // If we did not have a stored location, or if we were unable to restore
- // it, store the new one.
- m_findIndex = 0;
- storeCurrentMatchLocation();
- } else {
- m_hasCurrentLocation = false;
- }
-}
-
-std::pair<unsigned, unsigned> FindOnPage::getLayerMatchRange(int layerId) const
-{
- return m_layerMatchRangeMap.get(layerId);
-}
-
-void FindOnPage::setLayerMatchRange(int layerId,
- const std::pair<unsigned, unsigned> range)
-{
- m_layerMatchRangeMap.set(layerId, range);
-}
-
-}
diff --git a/Source/WebKit/android/nav/FindCanvas.h b/Source/WebKit/android/nav/FindCanvas.h
deleted file mode 100644
index 1d81f9a..0000000
--- a/Source/WebKit/android/nav/FindCanvas.h
+++ /dev/null
@@ -1,268 +0,0 @@
-/*
- * Copyright 2008, 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 Find_Canvas_h
-#define Find_Canvas_h
-
-#include "DrawExtra.h"
-#include "IntRect.h"
-#include "SkBounder.h"
-#include "SkCanvas.h"
-#include "SkPicture.h"
-#include "SkRect.h"
-#include "SkRegion.h"
-#include "SkTDArray.h"
-
-#include <unicode/umachine.h>
-#include <wtf/Vector.h>
-#include <wtf/HashMap.h>
-
-namespace android {
-class FindOnPage;
-
-// Stores both region information and an SkPicture of the match, so that the
-// region can be drawn, followed by drawing the matching text on top of it.
-// This class owns its SkPicture
-class MatchInfo {
-public:
- MatchInfo();
- ~MatchInfo();
- MatchInfo(const MatchInfo& src);
- const SkRegion& getLocation() const { return m_location; }
- // Return a pointer to our picture, representing the matching text. Does
- // not transfer ownership of the picture.
- SkPicture* getPicture() const { return m_picture; }
- // This will make a copy of the region, and increase the ref count on the
- // SkPicture. If this MatchInfo already had one, unref it.
- void set(const SkRegion& region, SkPicture* pic, int layerId);
- bool isInLayer() const { return m_layerId >= 0; }
- int layerId() const { return m_layerId; }
-private:
- MatchInfo& operator=(MatchInfo& src);
- SkRegion m_location;
- SkPicture* m_picture;
- int m_layerId;
-};
-
-// A class containing a typeface for reference, the length in glyphs, and
-// the upper and lower case representations of the search string.
-class GlyphSet {
-public:
- GlyphSet(const SkPaint& paint, const UChar* lower, const UChar* upper,
- size_t byteLength);
- ~GlyphSet();
- GlyphSet& operator=(GlyphSet& src);
-
- // Return true iff c matches one of our glyph arrays at index
- bool characterMatches(uint16_t c, int index);
-
- int getCount() const { return mCount; }
-
- const SkTypeface* getTypeface() const { return mTypeface; }
-
-private:
- // Disallow copy constructor
- GlyphSet(GlyphSet& src) { }
-
- // mTypeface is used for comparison only
- const SkTypeface* mTypeface;
- // mLowerGlyphs points to all of our storage space: the lower set followed
- // by the upper set. mUpperGlyphs is purely a convenience pointer to the
- // start of the upper case glyphs.
- uint16_t* mLowerGlyphs;
- uint16_t* mUpperGlyphs;
- // mCount is the number of glyphs of the search string. Must be the same
- // for both the lower case set and the upper case set.
- int mCount;
-
- // Arbitrarily chose the maximum storage to use in the GlyphSet. This is
- // based on the length of the word being searched. If users are always
- // searching for 3 letter words (for example), an ideal number would be 3.
- // Each time the user searches for a word longer than (in this case, 3) that
- // will result in calling new/delete.
- enum Storage {
- MAX_STORAGE_COUNT = 16
- };
- // In order to eliminate new/deletes, create storage that will be enough
- // most of the time
- uint16_t mStorage[2*MAX_STORAGE_COUNT];
-};
-
-class FindBounder : public SkBounder {
-public:
- FindBounder() {}
- ~FindBounder() {}
-protected:
- virtual bool onIRect(const SkIRect&) { return false; }
-};
-
-class FindCanvas : public SkCanvas {
-public:
- FindCanvas(int width, int height, const UChar* , const UChar*,
- size_t byteLength);
-
- virtual ~FindCanvas();
-
- virtual void drawText(const void* text, size_t byteLength, SkScalar x,
- SkScalar y, const SkPaint& paint);
-
- /* FIXME: This path has not been tested. */
- virtual void drawPosText(const void* text, size_t byteLength,
- const SkPoint pos[], const SkPaint& paint);
-
- /* Also untested */
- virtual void drawPosTextH(const void* text, size_t byteLength,
- const SkScalar xpos[], SkScalar constY,
- const SkPaint& paint);
-
- /* Not sure what to do here or for drawTextOnPathHV */
- virtual void drawTextOnPath(const void* text, size_t byteLength,
- const SkPath& path, const SkMatrix* matrix,
- const SkPaint& paint) {
- }
-
- void drawLayers(LayerAndroid* rootLayer, FindOnPage& findOnPage);
- int found() const { return mNumFound; }
- void setLayerId(int layerId) { mLayerId = layerId; }
-
- // This method detaches our array of matches and passes ownership to
- // the caller, who is then responsible for deleting them.
- WTF::Vector<MatchInfo>* detachMatches() {
- WTF::Vector<MatchInfo>* array = mMatches;
- mMatches = NULL;
- return array;
- }
-
-private:
- // These calls are made by findHelper to store information about each match
- // that is found. They return a rectangle which is used to highlight the
- // match. They also add to our SkPicture (which can be accessed with
- // getDrawnMatches) a draw of each match. This way it can be drawn after
- // the rectangle. The rect that is returned is in device coordinates.
- SkRect addMatchNormal(int index,
- const SkPaint& paint, int count, const uint16_t* glyphs,
- const SkScalar pos[], SkScalar y);
-
- SkRect addMatchPos(int index,
- const SkPaint& paint, int count, const uint16_t* glyphs,
- const SkScalar xPos[], SkScalar /* y */);
-
- SkRect addMatchPosH(int index,
- const SkPaint& paint, int count, const uint16_t* glyphs,
- const SkScalar position[], SkScalar constY);
-
- // Helper for each of our draw calls
- void findHelper(const void* text, size_t byteLength, const SkPaint& paint,
- const SkScalar xPos[], SkScalar y,
- SkRect (FindCanvas::*addMatch)(int index,
- const SkPaint& paint, int count, const uint16_t* glyphs,
- const SkScalar pos[], SkScalar y));
-
- // If we already have a working canvas, grab it. Otherwise, create a new
- // one.
- SkCanvas* getWorkingCanvas();
-
- // Return the set of glyphs and its count for the text being searched for
- // and the parameter paint. If one has already been created and cached
- // for this paint, use it. If not, create a new one and cache it.
- GlyphSet* getGlyphs(const SkPaint& paint);
-
- // Store all the accumulated info about a match in our vector.
- void insertMatchInfo(const SkRegion& region);
-
- // Throw away our cumulative information about our working SkCanvas. After
- // this call, next call to getWorkingCanvas will create a new one.
- void resetWorkingCanvas();
-
- // Since we may transfer ownership of this array (see detachRects()), we
- // hold a pointer to the array instead of just the array itself.
- WTF::Vector<MatchInfo>* mMatches;
- const UChar* mLowerText;
- const UChar* mUpperText;
- Vector<UChar> mLowerReversed;
- Vector<UChar> mUpperReversed;
- size_t mLength;
- FindBounder mBounder;
- int mNumFound;
- SkScalar mOutset;
- SkTDArray<GlyphSet> mGlyphSets;
-
- SkPicture* mWorkingPicture;
- SkCanvas* mWorkingCanvas;
- SkRegion mWorkingRegion;
- int mWorkingIndex;
- int mLayerId;
-};
-
-class FindOnPage : public DrawExtra {
-public:
- FindOnPage() {
- m_matches = 0;
- m_hasCurrentLocation = false;
- m_isFindPaintSetUp = false;
- m_lastBounds.setEmpty();
- }
- virtual ~FindOnPage() { if (m_matches) delete m_matches; }
- void clearCurrentLocation() { m_hasCurrentLocation = false; }
- IntRect currentMatchBounds() const;
- int currentMatchIndex() const { return m_findIndex; }
- bool currentMatchIsInLayer() const;
- // This requires the current match to be in a layer. See
- // currentMatchIsInLayer().
- int currentMatchLayerId() const;
- virtual void drawLegacy(SkCanvas* , LayerAndroid* , IntRect* );
- void findNext(bool forward);
- bool isCurrentLocationValid() { return m_hasCurrentLocation; }
- void setMatches(WTF::Vector<MatchInfo>* matches);
- WTF::Vector<MatchInfo>* matches() { return m_matches; }
-
- // Some functions to determine which matches belong to which layers.
- std::pair<unsigned, unsigned> getLayerMatchRange(int layerId) const;
- void setLayerMatchRange(int layerId,
- const std::pair<unsigned, unsigned> range);
-
-private:
- void drawMatch(const SkRegion& region, SkCanvas* canvas, bool focused);
- void setUpFindPaint();
- void storeCurrentMatchLocation();
- WTF::Vector<MatchInfo>* m_matches;
- WTF::HashMap< int, std::pair<unsigned, unsigned> > m_layerMatchRangeMap;
- // Stores the location of the current match.
- SkIPoint m_currentMatchLocation;
- // Tells whether the value in m_currentMatchLocation is valid.
- bool m_hasCurrentLocation;
- // Tells whether we have done the setup to draw the Find matches.
- bool m_isFindPaintSetUp;
- // Paint used to draw our Find matches.
- SkPaint m_findPaint;
- // Paint used for the background of our Find matches.
- SkPaint m_findBlurPaint;
- unsigned m_findIndex;
- SkIRect m_lastBounds;
-};
-
-}
-
-#endif // Find_Canvas_h
diff --git a/Source/WebKit/android/nav/WebView.cpp b/Source/WebKit/android/nav/WebView.cpp
index d2d1321..a63675c 100644
--- a/Source/WebKit/android/nav/WebView.cpp
+++ b/Source/WebKit/android/nav/WebView.cpp
@@ -34,7 +34,6 @@
#include "CachedNode.h"
#include "CachedRoot.h"
#include "DrawExtra.h"
-#include "FindCanvas.h"
#include "Frame.h"
#include "GraphicsJNI.h"
#include "HTMLInputElement.h"
@@ -107,12 +106,11 @@ enum FrameCachePermission {
AllowNewer
};
-#define DRAW_EXTRAS_SIZE 3
+#define DRAW_EXTRAS_SIZE 2
enum DrawExtras { // keep this in sync with WebView.java
DrawExtrasNone = 0,
- DrawExtrasFind = 1,
- DrawExtrasSelection = 2,
- DrawExtrasCursorRing = 3
+ DrawExtrasSelection = 1,
+ DrawExtrasCursorRing = 2
};
struct JavaGlue {
@@ -243,9 +241,6 @@ DrawExtra* getDrawExtraLegacy(DrawExtras extras)
DrawExtra* extra = getDrawExtra(extras);
if (!extra) {
switch (extras) {
- case DrawExtrasFind:
- extra = &m_findOnPage;
- break;
case DrawExtrasCursorRing:
if (drawCursorPreamble(root) && m_ring.setup()) {
if (m_ring.m_isPressed || m_ringAnimationEnd == UINT_MAX)
@@ -313,71 +308,6 @@ void debugDump()
}
#endif
-void scrollToCurrentMatch()
-{
- if (!m_findOnPage.currentMatchIsInLayer()) {
- scrollRectOnScreen(m_findOnPage.currentMatchBounds());
- return;
- }
-
- SkRect matchBounds = m_findOnPage.currentMatchBounds();
- LayerAndroid* rootLayer = compositeRoot();
- if (!rootLayer)
- return;
-
- Layer* layerContainingMatch = rootLayer->findById(m_findOnPage.currentMatchLayerId());
- if (!layerContainingMatch)
- return;
-
- // If the match is in a fixed position layer, there's nothing to do.
- if (layerContainingMatch->shouldInheritFromRootTransform())
- return;
-
- // If the match is in a scrollable layer or a descendant of such a layer,
- // there may be a range of of scroll configurations that will make the
- // current match visible. Our approach is the simplest possible. Starting at
- // the layer in which the match is found, we move up the layer tree,
- // scrolling any scrollable layers as little as possible to make sure that
- // the current match is in view. This approach has the disadvantage that we
- // may end up scrolling a larger number of elements than is necessary, which
- // may be visually jarring. However, minimising the number of layers
- // scrolled would complicate the code significantly.
-
- bool didScrollLayer = false;
- for (Layer* layer = layerContainingMatch; layer; layer = layer->getParent()) {
- ASSERT(layer->getParent() || layer == rootLayer);
-
- if (layer->contentIsScrollable()) {
- // Convert the match location to layer's local space and scroll it.
- // Repeatedly calling Layer::localToAncestor() is inefficient as
- // each call repeats part of the calculation. It would be more
- // efficient to maintain the transform here and update it on each
- // iteration, but that would mean duplicating logic from
- // Layer::localToAncestor() and would complicate things.
- SkMatrix transform;
- layerContainingMatch->localToAncestor(layer, &transform);
- SkRect transformedMatchBounds;
- transform.mapRect(&transformedMatchBounds, matchBounds);
- SkIRect roundedTransformedMatchBounds;
- transformedMatchBounds.roundOut(&roundedTransformedMatchBounds);
- // Only ScrollableLayerAndroid returns true for contentIsScrollable().
- didScrollLayer |= static_cast<ScrollableLayerAndroid*>(layer)->scrollRectIntoView(roundedTransformedMatchBounds);
- }
- }
- // Invalidate, as the call below to scroll the main page may be a no-op.
- if (didScrollLayer)
- viewInvalidate();
-
- // Convert matchBounds to the global space so we can scroll the main page.
- SkMatrix transform;
- layerContainingMatch->localToGlobal(&transform);
- SkRect transformedMatchBounds;
- transform.mapRect(&transformedMatchBounds, matchBounds);
- SkIRect roundedTransformedMatchBounds;
- transformedMatchBounds.roundOut(&roundedTransformedMatchBounds);
- scrollRectOnScreen(roundedTransformedMatchBounds);
-}
-
void scrollRectOnScreen(const IntRect& rect)
{
if (rect.isEmpty())
@@ -471,7 +401,6 @@ bool drawGL(WebCore::IntRect& viewRect, WebCore::IntRect* invalRect,
TilesManager::instance()->setHighEndGfx(m_isHighEndGfx);
m_glWebViewState = new GLWebViewState();
m_glWebViewState->glExtras()->setCursorRingExtra(&m_ring);
- m_glWebViewState->glExtras()->setFindOnPageExtra(&m_findOnPage);
if (m_baseLayer->content()) {
SkRegion region;
SkIRect rect;
@@ -1083,12 +1012,6 @@ void setFindIsUp(bool up)
m_viewImpl->m_findIsUp = up;
}
-void setFindIsEmpty()
-{
- DBG_NAV_LOG("");
- m_findOnPage.clearCurrentLocation();
-}
-
void showCursorTimed()
{
DBG_NAV_LOG("");
@@ -1165,39 +1088,6 @@ void sendMotionUp(WebCore::Frame* framePtr, WebCore::Node* nodePtr, int x, int y
checkException(env);
}
-void findNext(bool forward)
-{
- m_findOnPage.findNext(forward);
- scrollToCurrentMatch();
- viewInvalidate();
-}
-
-// With this call, WebView takes ownership of matches, and is responsible for
-// deleting it.
-void setMatches(WTF::Vector<MatchInfo>* matches, jboolean sameAsLastSearch)
-{
- // If this search is the same as the last one, check against the old
- // location to determine whether to scroll. If the same word is found
- // in the same place, then do not scroll.
- IntRect oldLocation;
- bool checkAgainstOldLocation = false;
- if (sameAsLastSearch && m_findOnPage.isCurrentLocationValid()) {
- oldLocation = m_findOnPage.currentMatchBounds();
- checkAgainstOldLocation = true;
- }
-
- m_findOnPage.setMatches(matches);
-
- if (!checkAgainstOldLocation || oldLocation != m_findOnPage.currentMatchBounds())
- scrollToCurrentMatch();
- viewInvalidate();
-}
-
-int currentMatchIndex()
-{
- return m_findOnPage.currentMatchIndex();
-}
-
bool scrollBy(int dx, int dy)
{
ALOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!");
@@ -1394,10 +1284,6 @@ void setVisibleRect(SkRect& visibleRect) {
m_visibleRect = visibleRect;
}
-FindOnPage& findOnPage() {
- return m_findOnPage;
-}
-
void setDrawExtra(DrawExtra *extra, DrawExtras type)
{
if (type == DrawExtrasNone)
@@ -1442,7 +1328,6 @@ private: // local state for WebView
bool m_heightCanMeasure;
int m_lastDx;
SkMSec m_lastDxTime;
- FindOnPage m_findOnPage;
CursorRing m_ring;
DrawExtra* m_extras[DRAW_EXTRAS_SIZE];
BaseLayerAndroid* m_baseLayer;
@@ -2163,11 +2048,6 @@ static void nativeSetFindIsUp(JNIEnv *env, jobject obj, jboolean isUp)
view->setFindIsUp(isUp);
}
-static void nativeSetFindIsEmpty(JNIEnv *env, jobject obj)
-{
- GET_NATIVE_VIEW(env, obj)->setFindIsEmpty();
-}
-
static void nativeShowCursorTimed(JNIEnv *env, jobject obj)
{
GET_NATIVE_VIEW(env, obj)->showCursorTimed();
@@ -2196,88 +2076,6 @@ static jobject nativeGetCursorRingBounds(JNIEnv *env, jobject obj)
return rect;
}
-static int nativeFindAll(JNIEnv *env, jobject obj, jstring findLower,
- jstring findUpper, jboolean sameAsLastSearch)
-{
- // If one or the other is null, do not search.
- if (!(findLower && findUpper))
- return 0;
- // Obtain the characters for both the lower case string and the upper case
- // string representing the same word.
- const jchar* findLowerChars = env->GetStringChars(findLower, 0);
- const jchar* findUpperChars = env->GetStringChars(findUpper, 0);
- // If one or the other is null, do not search.
- if (!(findLowerChars && findUpperChars)) {
- if (findLowerChars)
- env->ReleaseStringChars(findLower, findLowerChars);
- if (findUpperChars)
- env->ReleaseStringChars(findUpper, findUpperChars);
- checkException(env);
- return 0;
- }
- WebView* view = GET_NATIVE_VIEW(env, obj);
- ALOG_ASSERT(view, "view not set in nativeFindAll");
- BaseLayerAndroid* baseLayer = view->getBaseLayer();
- android::PictureSet* pictureSet = baseLayer ? baseLayer->content() : 0;
- if (!pictureSet) {
- env->ReleaseStringChars(findLower, findLowerChars);
- env->ReleaseStringChars(findUpper, findUpperChars);
- checkException(env);
- return 0;
- }
- int length = env->GetStringLength(findLower);
- // If the lengths of the strings do not match, then they are not the same
- // word, so do not search.
- if (!length || env->GetStringLength(findUpper) != length) {
- env->ReleaseStringChars(findLower, findLowerChars);
- env->ReleaseStringChars(findUpper, findUpperChars);
- checkException(env);
- return 0;
- }
- int width = pictureSet->width();
- int height = pictureSet->height();
- // Create a FindCanvas, which allows us to fake draw into it so we can
- // figure out where our search string is rendered (and how many times).
- FindCanvas canvas(width, height, (const UChar*) findLowerChars,
- (const UChar*) findUpperChars, length << 1);
- SkBitmap bitmap;
- bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height);
- canvas.setBitmapDevice(bitmap);
- FindOnPage& findOnPage = view->findOnPage();
- canvas.setLayerId(-1);
- unsigned matchesBegin = canvas.found();
- baseLayer->drawCanvas(&canvas);
- findOnPage.setLayerMatchRange(-1,
- std::pair<unsigned, unsigned>(matchesBegin, canvas.found()));
-#if USE(ACCELERATED_COMPOSITING)
- LayerAndroid* compositeLayer = view->compositeRoot();
- if (compositeLayer)
- canvas.drawLayers(compositeLayer, findOnPage);
-#endif
- WTF::Vector<MatchInfo>* matches = canvas.detachMatches();
- // With setMatches, the WebView takes ownership of matches
- view->setMatches(matches, sameAsLastSearch);
-
- env->ReleaseStringChars(findLower, findLowerChars);
- env->ReleaseStringChars(findUpper, findUpperChars);
- checkException(env);
- return canvas.found();
-}
-
-static void nativeFindNext(JNIEnv *env, jobject obj, bool forward)
-{
- WebView* view = GET_NATIVE_VIEW(env, obj);
- ALOG_ASSERT(view, "view not set in nativeFindNext");
- view->findNext(forward);
-}
-
-static int nativeFindIndex(JNIEnv *env, jobject obj)
-{
- WebView* view = GET_NATIVE_VIEW(env, obj);
- ALOG_ASSERT(view, "view not set in nativeFindIndex");
- return view->currentMatchIndex();
-}
-
static void nativeUpdateCachedTextfield(JNIEnv *env, jobject obj, jstring updatedText, jint generation)
{
WebView* view = GET_NATIVE_VIEW(env, obj);
@@ -2677,12 +2475,6 @@ static JNINativeMethod gJavaWebViewMethods[] = {
(void*) nativeDumpDisplayTree },
{ "nativeEvaluateLayersAnimations", "(I)Z",
(void*) nativeEvaluateLayersAnimations },
- { "nativeFindAll", "(Ljava/lang/String;Ljava/lang/String;Z)I",
- (void*) nativeFindAll },
- { "nativeFindNext", "(Z)V",
- (void*) nativeFindNext },
- { "nativeFindIndex", "()I",
- (void*) nativeFindIndex},
{ "nativeFocusCandidateFramePointer", "()I",
(void*) nativeFocusCandidateFramePointer },
{ "nativeFocusCandidateHasNextTextfield", "()Z",
@@ -2751,8 +2543,6 @@ static JNINativeMethod gJavaWebViewMethods[] = {
(void*) nativeSelectBestAt },
{ "nativeSelectAt", "(II)V",
(void*) nativeSelectAt },
- { "nativeSetFindIsEmpty", "()V",
- (void*) nativeSetFindIsEmpty },
{ "nativeSetFindIsUp", "(Z)V",
(void*) nativeSetFindIsUp },
{ "nativeSetHeightCanMeasure", "(Z)V",