summaryrefslogtreecommitdiffstats
path: root/WebKit/android/nav/FindCanvas.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'WebKit/android/nav/FindCanvas.cpp')
-rw-r--r--WebKit/android/nav/FindCanvas.cpp187
1 files changed, 184 insertions, 3 deletions
diff --git a/WebKit/android/nav/FindCanvas.cpp b/WebKit/android/nav/FindCanvas.cpp
index 1465b91..15a8001 100644
--- a/WebKit/android/nav/FindCanvas.cpp
+++ b/WebKit/android/nav/FindCanvas.cpp
@@ -23,11 +23,18 @@
* 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 "SkBlurMaskFilter.h"
+#include "SkCornerPathEffect.h"
#include "SkRect.h"
+#include <utils/Log.h>
+
// MatchInfo methods
////////////////////////////////////////////////////////////////////////////////
@@ -40,13 +47,15 @@ MatchInfo::~MatchInfo() {
}
MatchInfo::MatchInfo(const MatchInfo& src) {
+ m_layerId = src.m_layerId;
m_location = src.m_location;
m_picture = src.m_picture;
m_picture->safeRef();
}
-void MatchInfo::set(const SkRegion& region, SkPicture* pic) {
+void MatchInfo::set(const SkRegion& region, SkPicture* pic, int layerId) {
m_picture->safeUnref();
+ m_layerId = layerId;
m_location = region;
m_picture = pic;
SkASSERT(pic);
@@ -218,6 +227,16 @@ SkRect FindCanvas::addMatchPosH(int index,
return r;
}
+void FindCanvas::drawLayers(WebCore::LayerAndroid* layer) {
+ SkPicture* picture = layer->picture();
+ if (picture) {
+ setLayerId(layer->uniqueId());
+ drawPicture(*picture);
+ }
+ for (int i = 0; i < layer->countChildren(); i++)
+ drawLayers(layer->getChild(i));
+}
+
void FindCanvas::drawText(const void* text, size_t byteLength, SkScalar x,
SkScalar y, const SkPaint& paint) {
findHelper(text, byteLength, paint, &x, y, &FindCanvas::addMatchNormal);
@@ -456,7 +475,9 @@ void FindCanvas::insertMatchInfo(const SkRegion& region) {
mWorkingPicture->endRecording();
MatchInfo matchInfo;
mMatches->append(matchInfo);
- mMatches->last().set(region, mWorkingPicture);
+ LOGD("%s region=%p pict=%p layer=%d", __FUNCTION__,
+ region, mWorkingPicture, mLayerId);
+ mMatches->last().set(region, mWorkingPicture, mLayerId);
}
void FindCanvas::resetWorkingCanvas() {
@@ -465,3 +486,163 @@ void FindCanvas::resetWorkingCanvas() {
// 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;
+}
+
+WebCore::IntRect FindOnPage::currentMatchBounds() const {
+ if (!m_matches || !m_matches->size())
+ return WebCore::IntRect(0, 0, 0, 0);
+ return (*m_matches)[m_findIndex].getLocation().getBounds();
+}
+
+// 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::drawLayer(SkCanvas* canvas, const WebCore::IntRect* visRect,
+ int layerId) {
+ if (!m_matches || !m_matches->size())
+ return;
+ 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
+ canvas->drawPicture(*matchInfo.getPicture());
+ }
+ // 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)
+ || (visRect && !region.intersects(*visRect)))
+ 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())
+ 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;
+ }
+}
+