diff options
Diffstat (limited to 'Source/WebCore/platform/graphics/android/GLExtras.cpp')
-rw-r--r-- | Source/WebCore/platform/graphics/android/GLExtras.cpp | 222 |
1 files changed, 222 insertions, 0 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); + } +} |