diff options
author | John Reck <jreck@google.com> | 2011-10-07 13:10:24 -0700 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2011-10-07 13:10:24 -0700 |
commit | a89682c27396480357a4db6e362cafaa54168a09 (patch) | |
tree | ff660d2cca96a4cfa1def5610f3cf31a26f82f50 /Source/WebCore/platform/graphics/android | |
parent | 63147313cabd16f95cd018f8b5ecc5070a985fe5 (diff) | |
parent | fcb01cd64de0a1d6f8f8c897d16cc2628be53960 (diff) | |
download | external_webkit-a89682c27396480357a4db6e362cafaa54168a09.zip external_webkit-a89682c27396480357a4db6e362cafaa54168a09.tar.gz external_webkit-a89682c27396480357a4db6e362cafaa54168a09.tar.bz2 |
Merge "Switch find on page to GL"
Diffstat (limited to 'Source/WebCore/platform/graphics/android')
5 files changed, 297 insertions, 155 deletions
diff --git a/Source/WebCore/platform/graphics/android/GLExtras.cpp b/Source/WebCore/platform/graphics/android/GLExtras.cpp new file mode 100644 index 0000000..540ca16 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/GLExtras.cpp @@ -0,0 +1,222 @@ +/* + * Copyright 2011, 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. + */ + +#include "config.h" + +#include "DrawExtra.h" +#include "FindCanvas.h" +#include "GLExtras.h" +#include "IntRect.h" +#include "TilesManager.h" +#include "android_graphics.h" + +#include <cutils/log.h> +#include <wtf/text/CString.h> + +#undef XLOGC +#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "GLExtras", __VA_ARGS__) + +#ifdef DEBUG + +#undef XLOG +#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "GLExtras", __VA_ARGS__) + +#else + +#undef XLOG +#define XLOG(...) + +#endif // DEBUG + +// Touch ring border width. This is doubled if the ring is not pressed +#define RING_BORDER_WIDTH 1 +// Color of the ring is 0x6633b5e5 (copied from framework's holo_light) +#define COLOR_HOLO_LIGHT &m_lightRingTexture, 0x33, 0xb5, 0xe5, 0.4f +// Color of the ring is 0x660099cc (copied from framework's holo_dark) +#define COLOR_HOLO_DARK &m_darkRingTexture, 0x00, 0x99, 0xcc, 0.6f +// Put a cap on the number of matches to draw. If the current page has more +// matches than this, only draw the focused match. This both prevents clutter +// on the page and keeps the performance happy +#define MAX_NUMBER_OF_MATCHES_TO_DRAW 101 + +GLExtras::GLExtras() + : m_findOnPage(0) + , m_ring(0) + , m_drawExtra(0) + , m_lightRingTexture(-1) + , m_darkRingTexture(-1) +{ +} + +GLExtras::~GLExtras() +{ +} + +void GLExtras::drawRing(SkRect& srcRect, int* texture, int r, int g, int b, float a) +{ + if (*texture == -1) + *texture = GLUtils::createSampleColorTexture(r, g, b); + + if (srcRect.fRight <= srcRect.fLeft || srcRect.fBottom <= srcRect.fTop) { + // Invalid rect, reject it + return; + } + XLOG("drawQuad [%fx%f, %f, %f]", srcRect.fLeft, srcRect.fTop, + srcRect.width(), srcRect.height()); + TilesManager::instance()->shader()->drawQuad(srcRect, *texture, a); +} + +void GLExtras::drawRegion(const SkRegion& region, bool fill, + bool drawBorder, bool useDark) +{ + if (region.isEmpty()) + return; + if (fill) { + SkRegion::Iterator rgnIter(region); + while (!rgnIter.done()) { + const SkIRect& ir = rgnIter.rect(); + SkRect r; + r.set(ir.fLeft, ir.fTop, ir.fRight, ir.fBottom); + if (useDark) + drawRing(r, COLOR_HOLO_DARK); + else + drawRing(r, COLOR_HOLO_LIGHT); + rgnIter.next(); + } + } + if (fill && !drawBorder) + return; + SkPath path; + if (!region.getBoundaryPath(&path)) + return; + SkPath::Iter iter(path, true); + SkPath::Verb verb; + SkPoint pts[4]; + SkRegion clip; + SkIRect startRect; + while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { + if (verb == SkPath::kLine_Verb) { + SkRect r; + r.set(pts, 2); + SkIRect line; + int borderWidth = RING_BORDER_WIDTH; + if (!fill) + borderWidth *= 2; + line.fLeft = r.fLeft - borderWidth; + line.fRight = r.fRight + borderWidth; + line.fTop = r.fTop - borderWidth; + line.fBottom = r.fBottom + borderWidth; + if (clip.intersects(line)) { + clip.op(line, SkRegion::kReverseDifference_Op); + if (clip.isEmpty()) + continue; // Nothing to draw, continue + line = clip.getBounds(); + if (SkIRect::Intersects(startRect, line)) { + clip.op(startRect, SkRegion::kDifference_Op); + if (clip.isEmpty()) + continue; // Nothing to draw, continue + line = clip.getBounds(); + } + } else { + clip.setRect(line); + } + r.set(line.fLeft, line.fTop, line.fRight, line.fBottom); + if (useDark) + drawRing(r, COLOR_HOLO_DARK); + else + drawRing(r, COLOR_HOLO_LIGHT); + if (startRect.isEmpty()) { + startRect.set(line.fLeft, line.fTop, line.fRight, line.fBottom); + } + } + if (verb == SkPath::kMove_Verb) { + startRect.setEmpty(); + } + } +} + +void GLExtras::drawCursorRings() +{ + SkRegion region; + for (size_t i = 0; i < m_ring->rings().size(); i++) { + IntRect rect = m_ring->rings().at(i); + if (i == 0) + region.setRect(rect); + else + region.op(rect, SkRegion::kUnion_Op); + } + drawRegion(region, m_ring->m_isPressed, !m_ring->m_isButton, false); +} + +void GLExtras::drawFindOnPage(SkRect& viewport) +{ + WTF::Vector<MatchInfo>* matches = m_findOnPage->matches(); + XLOG("drawFindOnPage, matches: %p", matches); + if (!matches || !m_findOnPage->isCurrentLocationValid()) + return; + int count = matches->size(); + int current = m_findOnPage->currentMatchIndex(); + XLOG("match count: %d", count); + if (count < MAX_NUMBER_OF_MATCHES_TO_DRAW) + for (int i = 0; i < count; i++) { + MatchInfo& info = matches->at(i); + const SkRegion& region = info.getLocation(); + SkIRect rect = region.getBounds(); + if (rect.intersect(viewport.fLeft, viewport.fTop, + viewport.fRight, viewport.fBottom)) + drawRegion(region, i == current, false, true); +#ifdef DEBUG + else + XLOG("Quick rejecting [%dx%d, %d, %d", rect.fLeft, rect.fTop, + rect.width(), rect.height()); +#endif // DEBUG + } + else { + MatchInfo& info = matches->at(current); + drawRegion(info.getLocation(), true, false, true); + } +} + +void GLExtras::drawGL(IntRect& webViewRect, SkRect& viewport, int titleBarHeight) +{ + if (m_drawExtra) { + // Update the clip. We want to use the screen clip + FloatRect glclip; + glclip.setX(webViewRect.x()); + glclip.setY(webViewRect.y() + titleBarHeight); + glclip.setWidth(webViewRect.width()); + glclip.setHeight(webViewRect.height()); + XLOG("Setting clip [%fx%f, %f, %f]", glclip.x(), glclip.y(), + glclip.width(), glclip.height()); + TilesManager::instance()->shader()->clip(glclip); + if (m_drawExtra == m_ring) + drawCursorRings(); + else if (m_drawExtra == m_findOnPage) + drawFindOnPage(viewport); + else + XLOGC("m_drawExtra %p is unknown! (cursor: %p, find: %p", + m_drawExtra, m_ring, m_findOnPage); + } +} diff --git a/Source/WebCore/platform/graphics/android/GLExtras.h b/Source/WebCore/platform/graphics/android/GLExtras.h new file mode 100644 index 0000000..c52e951 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/GLExtras.h @@ -0,0 +1,68 @@ +/* + * Copyright 2011, 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 GLExtras_h +#define GLExtras_h + +#include "SkRect.h" +#include "SkRegion.h" + +namespace android { + class FindOnPage; + class CursorRing; + class DrawExtra; +} + +namespace WebCore { + +class GLExtras { +public: + GLExtras(); + virtual ~GLExtras(); + + void drawGL(IntRect& webViewRect, SkRect& viewport, int titleBarHeight); + void setFindOnPageExtra(android::FindOnPage* findOnPage) { + m_findOnPage = findOnPage; + } + void setCursorRingExtra(android::CursorRing* ring) { m_ring = ring; } + void setDrawExtra(android::DrawExtra* extra) { m_drawExtra = extra; } + +private: + void drawRing(SkRect& srcRect, int* texture, int r, int g, int b, float a); + void drawRegion(const SkRegion& region, bool fill, bool drawBorder, + bool useDark = false); + void drawCursorRings(); + void drawFindOnPage(SkRect& viewport); + + android::FindOnPage* m_findOnPage; + android::CursorRing* m_ring; + android::DrawExtra* m_drawExtra; + int m_lightRingTexture; + int m_darkRingTexture; +}; + +} // namespace WebCore + +#endif // GLExtras_h diff --git a/Source/WebCore/platform/graphics/android/GLWebViewState.cpp b/Source/WebCore/platform/graphics/android/GLWebViewState.cpp index c273c5c..9f266d2 100644 --- a/Source/WebCore/platform/graphics/android/GLWebViewState.cpp +++ b/Source/WebCore/platform/graphics/android/GLWebViewState.cpp @@ -60,14 +60,6 @@ #define FRAMERATE_CAP 0.01666 // We cap at 60 fps -// Touch ring border width. This is doubled if the ring is not pressed -#define RING_BORDER_WIDTH 1 -// Color of the ring is 0x6633b5e5 (copied from framework) -#define RING_COLOR_ALPHA 0.4 -#define RING_COLOR_R 0x33 -#define RING_COLOR_G 0xb5 -#define RING_COLOR_B 0xe5 - // log warnings if scale goes outside this range #define MIN_SCALE_WARNING 0.1 #define MAX_SCALE_WARNING 10 @@ -88,8 +80,6 @@ GLWebViewState::GLWebViewState(android::Mutex* buttonMutex) , m_globalButtonMutex(buttonMutex) , m_baseLayerUpdate(true) , m_backgroundColor(SK_ColorWHITE) - , m_displayRings(false) - , m_focusRingTexture(-1) , m_isScrolling(false) , m_goingDown(true) , m_goingLeft(false) @@ -171,7 +161,7 @@ void GLWebViewState::setBaseLayer(BaseLayerAndroid* layer, const SkRegion& inval SkSafeUnref(m_currentBaseLayer); m_currentBaseLayer = layer; } - m_displayRings = false; + m_glExtras.setDrawExtra(0); invalRegion(inval); #ifdef MEASURES_PERF @@ -183,21 +173,6 @@ void GLWebViewState::setBaseLayer(BaseLayerAndroid* layer, const SkRegion& inval TilesManager::instance()->setShowVisualIndicator(showVisualIndicator); } -void GLWebViewState::setRings(Vector<IntRect>& rings, bool isPressed, bool isButton) -{ - android::Mutex::Autolock lock(m_baseLayerLock); - m_displayRings = true; - m_rings.setEmpty(); - for (size_t i = 0; i < rings.size(); i++) { - if (i == 0) - m_rings.setRect(rings.at(i)); - else - m_rings.op(rings.at(i), SkRegion::kUnion_Op); - } - m_ringsIsPressed = isPressed; - m_ringsIsButton = isButton; -} - void GLWebViewState::invalRegion(const SkRegion& region) { SkRegion::Iterator iterator(region); @@ -223,26 +198,6 @@ void GLWebViewState::unlockBaseLayerUpdate() { m_invalidateRegion.setEmpty(); } -void GLWebViewState::setExtra(BaseLayerAndroid* layer, SkPicture& picture, - const IntRect& rect, bool allowSame) -{ - android::Mutex::Autolock lock(m_baseLayerLock); - if (!m_baseLayerUpdate) - return; - - layer->setExtra(picture); - - if (!allowSame && m_lastInval == rect) - return; - - if (!rect.isEmpty()) - inval(rect); - if (!m_lastInval.isEmpty()) - inval(m_lastInval); - m_lastInval = rect; - m_displayRings = false; -} - void GLWebViewState::inval(const IntRect& rect) { if (m_baseLayerUpdate) { @@ -266,105 +221,6 @@ void GLWebViewState::inval(const IntRect& rect) TilesManager::instance()->getProfiler()->nextInval(rect, zoomManager()->currentScale()); } -void GLWebViewState::resetRings() -{ - m_displayRings = false; -} - -void GLWebViewState::drawFocusRing(SkRect& srcRect) -{ - if (m_focusRingTexture == -1) - m_focusRingTexture = GLUtils::createSampleColorTexture(RING_COLOR_R, - RING_COLOR_G, - RING_COLOR_B); - - if (srcRect.fRight <= srcRect.fLeft || srcRect.fBottom <= srcRect.fTop) { - // Invalid rect, reject it - return; - } - TilesManager::instance()->shader()->drawQuad(srcRect, m_focusRingTexture, - RING_COLOR_ALPHA); -} - -void GLWebViewState::paintExtras() -{ - if (m_displayRings && !m_rings.isEmpty()) { - // Update the clip - SkIRect skbounds = m_rings.getBounds(); - if (skbounds.isEmpty()) - return; - FloatRect glclip; - glclip.setX(skbounds.fLeft); - glclip.setY(skbounds.fTop); - glclip.setWidth(skbounds.fRight - skbounds.fLeft); - glclip.setHeight(skbounds.fBottom - skbounds.fTop); - TilesManager::instance()->shader()->clip(glclip); - if (m_ringsIsPressed) { - SkRegion::Iterator rgnIter(m_rings); - while (!rgnIter.done()) { - SkIRect ir = rgnIter.rect(); - SkRect r; - r.set(ir.fLeft, ir.fTop, ir.fRight, ir.fBottom); - drawFocusRing(r); - rgnIter.next(); - } - } - if (m_ringsIsButton && m_ringsIsPressed) - return; - SkPath path; - if (!m_rings.getBoundaryPath(&path)) - return; - SkPath::Iter iter(path, true); - SkPath::Verb verb; - SkPoint pts[4]; - SkRegion clip; - SkIRect startRect; - while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { - if (verb == SkPath::kLine_Verb) { - SkRect r; - r.set(pts, 2); - SkIRect line; - int borderWidth = RING_BORDER_WIDTH; - if (!m_ringsIsPressed) - borderWidth *= 2; - line.fLeft = r.fLeft - borderWidth; - line.fRight = r.fRight + borderWidth; - line.fTop = r.fTop - borderWidth; - line.fBottom = r.fBottom + borderWidth; - if (clip.intersects(line)) { - clip.op(line, SkRegion::kReverseDifference_Op); - if (clip.isEmpty()) - continue; // Nothing to draw, continue - line = clip.getBounds(); - if (SkIRect::Intersects(startRect, line)) { - clip.op(startRect, SkRegion::kDifference_Op); - if (clip.isEmpty()) - continue; // Nothing to draw, continue - line = clip.getBounds(); - } - } else { - clip.setRect(line); - } - r.set(line.fLeft, line.fTop, line.fRight, line.fBottom); - drawFocusRing(r); - if (!m_ringsIsPressed) { - r.fLeft += RING_BORDER_WIDTH; - r.fRight -= RING_BORDER_WIDTH; - r.fTop += RING_BORDER_WIDTH; - r.fBottom -= RING_BORDER_WIDTH; - drawFocusRing(r); - } - if (startRect.isEmpty()) { - startRect.set(line.fLeft, line.fTop, line.fRight, line.fBottom); - } - } - if (verb == SkPath::kMove_Verb) { - startRect.setEmpty(); - } - } - } -} - unsigned int GLWebViewState::paintBaseLayerContent(SkCanvas* canvas) { android::Mutex::Autolock lock(m_baseLayerLock); @@ -604,7 +460,7 @@ bool GLWebViewState::drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect, double currentTime = setupDrawing(rect, viewport, webViewRect, titleBarHeight, clip, scale); bool ret = baseLayer->drawGL(currentTime, compositedRoot, rect, viewport, scale, buffersSwappedPtr); - paintExtras(); + m_glExtras.drawGL(webViewRect, viewport, titleBarHeight); glBindBuffer(GL_ARRAY_BUFFER, 0); diff --git a/Source/WebCore/platform/graphics/android/GLWebViewState.h b/Source/WebCore/platform/graphics/android/GLWebViewState.h index 27e8148..23d7de2 100644 --- a/Source/WebCore/platform/graphics/android/GLWebViewState.h +++ b/Source/WebCore/platform/graphics/android/GLWebViewState.h @@ -30,6 +30,7 @@ #include "Color.h" #include "DrawExtra.h" +#include "GLExtras.h" #include "IntRect.h" #include "SkCanvas.h" #include "SkRect.h" @@ -174,12 +175,9 @@ public: unsigned int paintBaseLayerContent(SkCanvas* canvas); void setBaseLayer(BaseLayerAndroid* layer, const SkRegion& inval, bool showVisualIndicator, bool isPictureAfterFirstLayout); - void setExtra(BaseLayerAndroid*, SkPicture&, const IntRect&, bool allowSame); void paintExtras(); - void setRings(Vector<IntRect>& rings, bool isPressed, bool isButton); - void resetRings(); - void drawFocusRing(SkRect& rect); + GLExtras* glExtras() { return &m_glExtras; } TiledPage* sibling(TiledPage* page); TiledPage* frontPage(); @@ -268,11 +266,7 @@ private: double m_delayTimes[MAX_MEASURES_PERF]; bool m_measurePerfs; #endif - bool m_displayRings; - SkRegion m_rings; - bool m_ringsIsPressed; - bool m_ringsIsButton; - int m_focusRingTexture; + GLExtras m_glExtras; bool m_isScrolling; bool m_goingDown; diff --git a/Source/WebCore/platform/graphics/android/android_graphics.h b/Source/WebCore/platform/graphics/android/android_graphics.h index 89312b5..60ac115 100644 --- a/Source/WebCore/platform/graphics/android/android_graphics.h +++ b/Source/WebCore/platform/graphics/android/android_graphics.h @@ -33,6 +33,7 @@ namespace WebCore { class GraphicsContext; + class GLExtras; } SkCanvas* android_gc2canvas(GraphicsContext* gc); @@ -59,6 +60,7 @@ public: WTF::Vector<IntRect>& rings() { return m_rings; } private: friend class WebView; + friend class WebCore::GLExtras; WebViewCore* m_viewImpl; // copy for convenience WTF::Vector<IntRect> m_rings; IntRect m_bounds; |