diff options
Diffstat (limited to 'WebKit/android/nav')
-rw-r--r-- | WebKit/android/nav/CacheBuilder.cpp | 47 | ||||
-rw-r--r-- | WebKit/android/nav/CacheBuilder.h | 4 | ||||
-rw-r--r-- | WebKit/android/nav/FindCanvas.cpp | 197 | ||||
-rw-r--r-- | WebKit/android/nav/FindCanvas.h | 65 | ||||
-rw-r--r-- | WebKit/android/nav/WebView.cpp | 111 |
5 files changed, 242 insertions, 182 deletions
diff --git a/WebKit/android/nav/CacheBuilder.cpp b/WebKit/android/nav/CacheBuilder.cpp index da32898..69d0a06 100644 --- a/WebKit/android/nav/CacheBuilder.cpp +++ b/WebKit/android/nav/CacheBuilder.cpp @@ -27,6 +27,7 @@ #include "HTMLAreaElement.h" #include "HTMLImageElement.h" #include "HTMLInputElement.h" +#include "HTMLMapElement.h" #include "HTMLNames.h" #include "HTMLOptionElement.h" #include "HTMLSelectElement.h" @@ -398,7 +399,7 @@ void CacheBuilder::Debug::groups() { properties.truncate(properties.length() - 3); IntRect rect = node->getRect(); if (node->hasTagName(HTMLNames::areaTag)) - rect = static_cast<HTMLAreaElement*>(node)->getAreaRect(); + rect = Builder(frame)->getAreaRect(static_cast<HTMLAreaElement*>(node)); char buffer[DEBUG_BUFFER_SIZE]; memset(buffer, 0, sizeof(buffer)); mBuffer = buffer; @@ -1004,12 +1005,20 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame, RenderStyle* style = nodeRenderer->style(); if (style->visibility() == HIDDEN) continue; -#ifdef ANDROID_NAVIGATE_AREAMAPS if (nodeRenderer->isImage()) { // set all the area elements to have a link to their images RenderImage* image = static_cast<RenderImage*>(nodeRenderer); - image->setImageForAreaElements(); + HTMLMapElement* map = image->imageMap(); + if (map) { + Node* node; + for (node = map->firstChild(); node; + node = node->traverseNextNode(map)) { + if (!node->hasTagName(HTMLNames::areaTag)) + continue; + HTMLAreaElement* area = static_cast<HTMLAreaElement*>(node); + m_areaBoundsMap.set(area, image); + } + } } -#endif isTransparent = style->hasBackground() == false; #ifdef ANDROID_CSS_TAP_HIGHLIGHT_COLOR hasFocusRing = style->tapHighlightColor().alpha() > 0; @@ -1043,10 +1052,9 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame, IntRect absBounds; Node* lastChild = node->lastChild(); WTF::Vector<IntRect>* columns = NULL; -#ifdef ANDROID_NAVIGATE_AREAMAPS if (isArea) { HTMLAreaElement* area = static_cast<HTMLAreaElement*>(node); - bounds = area->getAreaRect(); + bounds = getAreaRect(area); bounds.move(globalOffsetX, globalOffsetY); absBounds = bounds; isUnclipped = true; // FIXME: areamaps require more effort to detect @@ -1054,7 +1062,6 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame, takesFocus = true; goto keepNode; } -#endif if (nodeRenderer == NULL) continue; @@ -1183,6 +1190,9 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame, if (isFocusable == false) { if (node->isEventTargetNode() == false) continue; + EventTargetNode* eventTargetNode = (EventTargetNode*) node; + if (eventTargetNode->disabled()) + continue; bool overOrOut = HasOverOrOut(node); bool hasTrigger = HasTriggerEvent(node); if (overOrOut == false && hasTrigger == false) @@ -1233,9 +1243,6 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame, else clip.intersect(parentClip); hasClip = true; - DBG_NAV_LOGD("absBounds={%d,%d,%d,%d} parentClip={%d,%d,%d,%d}\n", - absBounds.x(), absBounds.y(), absBounds.width(), absBounds.height(), - parentClip.x(), parentClip.y(), parentClip.width(), parentClip.height()); } if (hasClip && cachedNode.clip(clip) == false) { cachedNode.setBounds(clip); @@ -2365,6 +2372,16 @@ void CacheBuilder::FindResetNumber(FindState* state) state->mStorePtr = state->mStore; } +IntRect CacheBuilder::getAreaRect(const HTMLAreaElement* area) const +{ + RenderImage* map = m_areaBoundsMap.get(area); + if (!map) + return IntRect(); + if (area->isDefault()) + return map->absoluteBoundingBoxRect(); + return area->getRect(map); +} + void CacheBuilder::GetGlobalOffset(Node* node, int* x, int * y) { GetGlobalOffset(node->document()->frame(), x, y); @@ -2459,13 +2476,11 @@ Node* CacheBuilder::findByCenter(int x, int y) const if (node->isTextNode()) continue; IntRect bounds; -#ifdef ANDROID_NAVIGATE_AREAMAPS if (node->hasTagName(HTMLNames::areaTag)) { HTMLAreaElement* area = static_cast<HTMLAreaElement*>(node); - bounds = area->getAreaRect(); + bounds = getAreaRect(area); bounds.move(globalOffsetX, globalOffsetY); } else -#endif bounds = node->getRect(); if (bounds.isEmpty()) continue; @@ -2775,12 +2790,8 @@ bool CacheBuilder::validNode(void* matchFrame, void* matchNode) const Node* node = frame->document(); while (node != NULL) { if (node == matchNode) { -#ifdef ANDROID_NAVIGATE_AREAMAPS const IntRect& rect = node->hasTagName(HTMLNames::areaTag) ? - static_cast<HTMLAreaElement*>(node)->getAreaRect() : node->getRect(); -#else - const IntRect& rect = node->getRect(); -#endif + getAreaRect(static_cast<HTMLAreaElement*>(node)) : node->getRect(); // Consider nodes with empty rects that are not at the origin // to be valid, since news.google.com has valid nodes like this if (rect.x() == 0 && rect.y() == 0 && rect.isEmpty()) diff --git a/WebKit/android/nav/CacheBuilder.h b/WebKit/android/nav/CacheBuilder.h index 075042e..4a424a9 100644 --- a/WebKit/android/nav/CacheBuilder.h +++ b/WebKit/android/nav/CacheBuilder.h @@ -37,10 +37,12 @@ namespace WebCore { class Document; class Frame; +class HTMLAreaElement; class InlineTextBox; class Node; class PlatformGraphicsContext; class RenderFlow; +class RenderImage; class RenderObject; class RenderLayer; class Text; @@ -193,6 +195,7 @@ private: static Frame* FrameAnd(CacheBuilder* focusNav); static Frame* FrameAnd(const CacheBuilder* focusNav); static CacheBuilder* Builder(Frame* ); + IntRect getAreaRect(const HTMLAreaElement* area) const; static Frame* HasFrame(Node* ); static bool HasOverOrOut(Node* ); static bool HasTriggerEvent(Node* ); @@ -208,6 +211,7 @@ private: Node* mLastKnownFocus; IntRect mLastKnownFocusBounds; android::CachedNodeType mAllowableTypes; + WTF::HashMap<const HTMLAreaElement* , RenderImage* > m_areaBoundsMap; #if DUMP_NAV_CACHE public: class Debug { diff --git a/WebKit/android/nav/FindCanvas.cpp b/WebKit/android/nav/FindCanvas.cpp index 5b6978c..60a7486 100644 --- a/WebKit/android/nav/FindCanvas.cpp +++ b/WebKit/android/nav/FindCanvas.cpp @@ -19,6 +19,31 @@ #include "SkRect.h" +// MatchInfo methods +//////////////////////////////////////////////////////////////////////////////// + +MatchInfo::MatchInfo() { + m_picture = 0; +} + +MatchInfo::~MatchInfo() { + m_picture->safeUnref(); +} + +MatchInfo::MatchInfo(const MatchInfo& src) { + m_location = src.m_location; + m_picture = src.m_picture; + m_picture->safeRef(); +} + +void MatchInfo::set(const SkRegion& region, SkPicture* pic) { + m_picture->safeUnref(); + m_location = region; + m_picture = pic; + SkASSERT(pic); + pic->ref(); +} + // GlyphSet methods //////////////////////////////////////////////////////////////////////////////// @@ -81,33 +106,17 @@ FindCanvas::FindCanvas(int width, int height, const UChar* lower, setBounder(&mBounder); mOutset = -SkIntToScalar(2); - mRegions = new WTF::Vector<SkRegion>(); -#if RECORD_MATCHES - mPicture = new SkPicture(); - mRecordingCanvas = mPicture->beginRecording(width, height); -#endif + mMatches = new WTF::Vector<MatchInfo>(); mWorkingIndex = 0; + mWorkingCanvas = 0; + mWorkingPicture = 0; } FindCanvas::~FindCanvas() { setBounder(NULL); /* Just in case getAndClear was not called. */ - delete mRegions; -#if RECORD_MATCHES - mPicture->unref(); -#endif -} - -// SkPaint.measureText is used to get a rectangle surrounding the specified -// text. It is a tighter bounds than we want. We want the height to account -// for the ascent and descent of the font, so that the rectangles will line up, -// regardless of the characters contained in them. -static void correctSize(const SkPaint& paint, SkRect& rect) -{ - SkPaint::FontMetrics fontMetrics; - paint.getFontMetrics(&fontMetrics); - rect.fTop = fontMetrics.fAscent; - rect.fBottom = fontMetrics.fDescent; + delete mMatches; + mWorkingPicture->safeUnref(); } // Each version of addMatch returns a rectangle for a match. @@ -117,21 +126,24 @@ SkRect FindCanvas::addMatchNormal(int index, 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), - NULL); + SkScalar before = paint.measureText(lineStart, index * sizeof(uint16_t), 0); SkRect rect; - int countInBytes = count << 1; - paint.measureText(glyphs, countInBytes, &rect); - correctSize(paint, rect); - rect.offset(pos[0] + before, y); - getTotalMatrix().mapRect(&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. -#if RECORD_MATCHES - mRecordingCanvas->setMatrix(getTotalMatrix()); - SkPoint point; - matrix.mapXY(pos[0] + before, y, &point); - mRecordingCanvas->drawText(glyphs, countInBytes, point.fX, point.fY, paint); -#endif + SkCanvas* canvas = getWorkingCanvas(); + int saveCount = canvas->save(); + canvas->concat(matrix); + canvas->drawText(glyphs, countInBytes, pos[0] + before, y, paint); + canvas->restoreToCount(saveCount); return rect; } @@ -140,27 +152,31 @@ SkRect FindCanvas::addMatchPos(int index, const SkScalar xPos[], SkScalar /* y */) { SkRect r; r.setEmpty(); - const SkScalar* pos = &xPos[index << 1]; - int countInBytes = count << 1; + 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); - for (int j = 0; j < countInBytes; j += 2) { + // Need to check each character individually, since the heights may be + // different. + for (int j = 0; j < count; j++) { SkRect bounds; - paint.getTextWidths(&(glyphs[j >> 1]), 2, NULL, &bounds); - bounds.fTop = fontMetrics.fAscent; - bounds.fBottom = fontMetrics.fDescent; - bounds.offset(pos[j], pos[j+1]); - /* Accumulate and then add the resulting rect to mRegions */ + 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); } - getTotalMatrix().mapRect(&r); - // Add the text to our picture. -#if RECORD_MATCHES - mRecordingCanvas->setMatrix(getTotalMatrix()); - // FIXME: Need to do more work to get xPos and constY in the proper - // coordinates. - //mRecordingCanvas->drawPosText(glyphs, countInBytes, positions, paint); -#endif + 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; } @@ -168,24 +184,28 @@ SkRect FindCanvas::addMatchPosH(int index, const SkPaint& paint, int count, const uint16_t* glyphs, const SkScalar position[], SkScalar constY) { SkRect r; - r.setEmpty(); + // We only care about the positions starting at the index of our match const SkScalar* xPos = &position[index]; - for (int j = 0; j < count; j++) { - SkRect bounds; - paint.getTextWidths(&glyphs[j], 1, NULL, &bounds); - bounds.offset(xPos[j], constY); - /* Accumulate and then add the resulting rect to mRegions */ - r.join(bounds); - } - correctSize(paint, r); - getTotalMatrix().mapRect(&r); - // Add the text to our picture. -#if RECORD_MATCHES - mRecordingCanvas->setMatrix(getTotalMatrix()); - // FIXME: Need to do more work to get xPos and constY in the proper - // coordinates. - //mRecordingCanvas->drawPosTextH(glyphs, count << 1, xPos, constY, paint); -#endif + // 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; } @@ -236,10 +256,7 @@ void FindCanvas::findHelper(const void* text, size_t byteLength, const uint16_t* glyphs, const SkScalar positions[], SkScalar y)) { SkASSERT(paint.getTextEncoding() == SkPaint::kGlyphID_TextEncoding); - SkASSERT(mRegions); -#if RECORD_MATCHES - SkASSERT(mRecordingCanvas); -#endif + SkASSERT(mMatches); GlyphSet* glyphSet = getGlyphs(paint); const int count = glyphSet->getCount(); int numCharacters = byteLength >> 1; @@ -249,7 +266,8 @@ void FindCanvas::findHelper(const void* text, size_t byteLength, if (mWorkingIndex) { SkPoint newY; getTotalMatrix().mapXY(0, y, &newY); - if (mWorkingRegion.getBounds().fBottom < SkScalarRound(newY.fY)) { + SkIRect bounds = mWorkingRegion.getBounds(); + if (bounds.fBottom < SkScalarRound(newY.fY)) { // Now we know that this line is lower than our partial match. SkPaint clonePaint(paint); clonePaint.setTextEncoding(SkPaint::kUTF8_TextEncoding); @@ -260,14 +278,16 @@ void FindCanvas::findHelper(const void* text, size_t byteLength, if (mWorkingIndex == count) { // We already know that it is not clipped out because we // checked for that before saving the working region. - mNumFound++; - mRegions->append(mWorkingRegion); + 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(); } @@ -288,7 +308,6 @@ void FindCanvas::findHelper(const void* text, size_t byteLength, } // The last count characters match, so we found the entire // search string. - mNumFound++; int remaining = count - mWorkingIndex; int matchIndex = index - remaining + 1; // Set up a pointer to the matching text in 'chars'. @@ -325,7 +344,7 @@ void FindCanvas::findHelper(const void* text, size_t byteLength, // the previous line(s). regionToAdd.op(mWorkingRegion, SkRegion::kUnion_Op); } - mRegions->append(regionToAdd); + 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 @@ -338,6 +357,9 @@ void FindCanvas::findHelper(const void* text, size_t byteLength, // character from our hidden match index = matchIndex; } + // 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 @@ -389,6 +411,14 @@ void FindCanvas::findHelper(const void* text, size_t byteLength, 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(); @@ -402,3 +432,18 @@ GlyphSet* FindCanvas::getGlyphs(const SkPaint& paint) { *mGlyphSets.append() = set; return &(mGlyphSets.top()); } + +void FindCanvas::insertMatchInfo(const SkRegion& region) { + mNumFound++; + mWorkingPicture->endRecording(); + MatchInfo matchInfo; + mMatches->append(matchInfo); + mMatches->last().set(region, mWorkingPicture); +} + +void FindCanvas::resetWorkingCanvas() { + mWorkingPicture->unref(); + mWorkingPicture = 0; + // Do not need to reset mWorkingCanvas itself because we only access it via + // getWorkingCanvas. +} diff --git a/WebKit/android/nav/FindCanvas.h b/WebKit/android/nav/FindCanvas.h index fe1e3d2..5558c8b 100644 --- a/WebKit/android/nav/FindCanvas.h +++ b/WebKit/android/nav/FindCanvas.h @@ -17,23 +17,37 @@ #ifndef Find_Canvas_h #define Find_Canvas_h -// The code marked with this is used to record the draw calls into an SkPicture, -// which is passed to the caller to draw the matches on top of the opaque green -// rectangles. The code is a checkpoint. -#define RECORD_MATCHES 0 - #include "SkBounder.h" #include "SkCanvas.h" +#include "SkPicture.h" #include "SkRegion.h" #include "SkTDArray.h" #include "icu/unicode/umachine.h" -#if RECORD_MATCHES -class SkPicture; -#endif class SkRect; class SkTypeface; +// 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); +private: + MatchInfo& operator=(MatchInfo& src); + SkRegion m_location; + SkPicture* m_picture; +}; + // A class containing a typeface for reference, the length in glyphs, and // the upper and lower case representations of the search string. class GlyphSet { @@ -113,20 +127,14 @@ public: int found() const { return mNumFound; } - // This method detaches our array of regions and passes ownership to + // This method detaches our array of matches and passes ownership to // the caller, who is then responsible for deleting them. - WTF::Vector<SkRegion>* detachRegions() { - WTF::Vector<SkRegion>* array = mRegions; - mRegions = NULL; + WTF::Vector<MatchInfo>* detachMatches() { + WTF::Vector<MatchInfo>* array = mMatches; + mMatches = NULL; return array; } -#if RECORD_MATCHES - // This SkPicture contains only draw calls for the drawn text. This is - // used to draw over the highlight rectangle so that it can be seen. - SkPicture* getDrawnMatches() const { return mPicture; } -#endif - 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 @@ -144,7 +152,7 @@ private: 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, @@ -152,14 +160,25 @@ private: 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<SkRegion>* mRegions; + WTF::Vector<MatchInfo>* mMatches; const UChar* mLowerText; const UChar* mUpperText; size_t mLength; @@ -167,11 +186,9 @@ private: int mNumFound; SkScalar mOutset; SkTDArray<GlyphSet> mGlyphSets; -#if RECORD_MATCHES - SkPicture* mPicture; - SkCanvas* mRecordingCanvas; -#endif + SkPicture* mWorkingPicture; + SkCanvas* mWorkingCanvas; SkRegion mWorkingRegion; int mWorkingIndex; }; diff --git a/WebKit/android/nav/WebView.cpp b/WebKit/android/nav/WebView.cpp index 7af96d7..63c6aeb 100644 --- a/WebKit/android/nav/WebView.cpp +++ b/WebKit/android/nav/WebView.cpp @@ -419,10 +419,6 @@ WebView(JNIEnv* env, jobject javaWebView, int viewImpl) m_matches = 0; m_hasCurrentLocation = false; m_isFindPaintSetUp = false; -// RECORD_MATCHES is defined in FindCanvas.h -#if RECORD_MATCHES - m_matchesPicture = 0; -#endif } ~WebView() @@ -437,10 +433,6 @@ WebView(JNIEnv* env, jobject javaWebView, int viewImpl) delete m_navPictureUI; if (m_matches) delete m_matches; -// RECORD_MATCHES is defined in FindCanvas.h -#if RECORD_MATCHES - m_matchesPicture->safeUnref(); -#endif } void clearFocus(int x, int y, bool inval) @@ -548,9 +540,7 @@ void setUpFindPaint() const SkScalar roundiness = SkIntToScalar(2); SkCornerPathEffect* cornerEffect = new SkCornerPathEffect(roundiness); m_findPaint.setPathEffect(cornerEffect); - // FIXME: Would like this to be opaque, but then the user cannot see the - // text behind it. We will then need to redraw the text on top of it. - m_findPaint.setARGB(204, 132, 190, 0); + m_findPaint.setARGB(255, 132, 190, 0); // Set up the background blur paint. m_findBlurPaint.setAntiAlias(true); @@ -583,26 +573,34 @@ void drawMatch(const SkRegion& region, SkCanvas* canvas, bool focused) // 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); } +// 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 drawMatches(SkCanvas* canvas) { - if (!m_matches || !m_matches->size() -// RECORD_MATCHES is defined in FindCanvas.h -#if RECORD_MATCHES - || !m_matchesPicture -#endif - ) { + if (!m_matches || !m_matches->size()) { return; } if (m_findIndex >= m_matches->size()) { m_findIndex = 0; } - const SkRegion& currentMatchRegion = (*m_matches)[m_findIndex]; + const MatchInfo& matchInfo = (*m_matches)[m_findIndex]; + const SkRegion& currentMatchRegion = matchInfo.getLocation(); const SkIRect& currentMatchBounds = currentMatchRegion.getBounds(); int left = currentMatchBounds.fLeft; int top = currentMatchBounds.fTop; @@ -636,36 +634,29 @@ void drawMatches(SkCanvas* canvas) setUpFindPaint(); // Draw the current match - drawMatch(currentMatchRegion, canvas, true); + drawMatch(currentMatchRegion, canvas, true); + // Now draw the picture, so that it shows up on top of the rectangle + canvas->drawPicture(*matchInfo.getPicture()); // Draw the rest unsigned numberOfMatches = m_matches->size(); - int saveCount = 0; - if (numberOfMatches > 1) { + if (numberOfMatches > 1 + && numberOfMatches < MAX_NUMBER_OF_MATCHES_TO_DRAW) { + SkIRect visibleIRect; + android_setrect(&visibleIRect, visible); for(unsigned i = 0; i < numberOfMatches; i++) { // The current match has already been drawn if (i == m_findIndex) continue; - const SkRegion& region = (*m_matches)[i]; - // Do not draw matches which intersect the current one - if (currentMatchRegion.intersects(region)) + 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) + || !region.intersects(visibleIRect)) continue; drawMatch(region, canvas, false); } -// RECORD_MATCHES is defined in FindCanvas.h -#if RECORD_MATCHES - // Set a clip so we do not draw the text for the other matches. - saveCount = canvas->save(SkCanvas::kClip_SaveFlag); - canvas->clipRect(currentMatch); -#endif } -// RECORD_MATCHES is defined in FindCanvas.h -#if RECORD_MATCHES - canvas->drawPicture(*m_matchesPicture); - if (numberOfMatches > 1) { - canvas->restoreToCount(saveCount); - } -#endif } void drawFocusRing(SkCanvas* canvas) @@ -1112,6 +1103,18 @@ bool moveFocus(int keyCode, int count, bool ignoreScroll, bool inval, void notifyFocusSet(FrameCachePermission inEditingMode) { + CachedRoot* root = getFrameCache(DontAllowNewer); + if (root) { + // make sure the mFocusData in WebView.java is in sync with WebView.cpp + const CachedFrame* frame = 0; + const CachedNode* node = root->currentFocus(&frame); + const WebCore::IntPoint& focusLocation = root->focusLocation(); + setFocusData(root->generation(), + frame ? (WebCore::Frame*) frame->framePointer() : 0, + node ? (WebCore::Node*) node->nodePointer() : 0, + focusLocation.x(), focusLocation.y(), false); + } + if (focusIsTextArea(inEditingMode)) updateTextEntry(); else if (inEditingMode) @@ -1608,8 +1611,8 @@ void setFocusData(int buildGeneration, WebCore::Frame* framePtr, // m_currentMatchLocation. void inline storeCurrentMatchLocation() { - SkASSERT(m_findIndex < m_matches->size() && m_findIndex >= 0); - const SkIRect& bounds = (*m_matches)[m_findIndex].getBounds(); + 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; } @@ -1635,12 +1638,7 @@ void findNext(bool forward) // With this call, WebView takes ownership of matches, and is responsible for // deleting it. -void setMatches(WTF::Vector<SkRegion>* matches -// RECORD_MATCHES is defined in FindCanvas.h -#if RECORD_MATCHES - , SkPicture* pic -#endif - ) +void setMatches(WTF::Vector<MatchInfo>* matches) { if (m_matches) delete m_matches; @@ -1648,7 +1646,7 @@ void setMatches(WTF::Vector<SkRegion>* matches if (m_matches->size()) { if (m_hasCurrentLocation) { for (unsigned i = 0; i < m_matches->size(); i++) { - const SkIRect& rect = (*m_matches)[i].getBounds(); + const SkIRect& rect = (*m_matches)[i].getLocation().getBounds(); if (rect.fLeft == m_currentMatchLocation.fX && rect.fTop == m_currentMatchLocation.fY) { m_findIndex = i; @@ -1664,12 +1662,6 @@ void setMatches(WTF::Vector<SkRegion>* matches } else { m_hasCurrentLocation = false; } -// RECORD_MATCHES is defined in FindCanvas.h -#if RECORD_MATCHES - m_matchesPicture->safeUnref(); - m_matchesPicture = pic; - m_matchesPicture->ref(); -#endif viewInvalidate(); } @@ -1778,7 +1770,7 @@ private: // local state for WebView bool m_heightCanMeasure; int m_lastDx; SkMSec m_lastDxTime; - WTF::Vector<SkRegion>* m_matches; + WTF::Vector<MatchInfo>* m_matches; // Stores the location of the current match. SkIPoint m_currentMatchLocation; // Tells whether the value in m_currentMatchLocation is valid. @@ -1789,10 +1781,6 @@ private: // local state for WebView SkPaint m_findPaint; // Paint used for the background of our Find matches. SkPaint m_findBlurPaint; -// RECORD_MATCHES is defined in FindCanvas.h -#if RECORD_MATCHES - SkPicture* m_matchesPicture; -#endif unsigned m_findIndex; }; // end of WebView class @@ -2096,14 +2084,9 @@ static int nativeFindAll(JNIEnv *env, jobject obj, jstring findLower, bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height); canvas.setBitmapDevice(bitmap); canvas.drawPicture(*(root->getPicture())); - WTF::Vector<SkRegion>* matches = canvas.detachRegions(); + WTF::Vector<MatchInfo>* matches = canvas.detachMatches(); // With setMatches, the WebView takes ownership of matches - view->setMatches(matches -// RECORD_MATCHES is defined in FindCanvas.h -#if RECORD_MATCHES - , canvas.getDrawnMatches() -#endif - ); + view->setMatches(matches); env->ReleaseStringChars(findLower, findLowerChars); env->ReleaseStringChars(findUpper, findUpperChars); |