diff options
author | Cary Clark <cary@android.com> | 2010-02-23 10:46:08 -0500 |
---|---|---|
committer | Cary Clark <cary@android.com> | 2010-02-24 16:04:13 -0500 |
commit | 87962ce00229855c098ba12cee8d5c015a835289 (patch) | |
tree | c6e9990575cad9cc687cf0c79573c13ac4d02f1b /WebCore/platform | |
parent | 4175d59b46f96005f0c64978b1a94e3fe60f1e8e (diff) | |
download | external_webkit-87962ce00229855c098ba12cee8d5c015a835289.zip external_webkit-87962ce00229855c098ba12cee8d5c015a835289.tar.gz external_webkit-87962ce00229855c098ba12cee8d5c015a835289.tar.bz2 |
refactor drawing to support layers
Drawing elements that appear atop or below layers need to be
drawn both in the proper order and with the correct canvas to
respect clipping and the matrix.
Drawing the find results, text selection, or the cursor ring,
interleaves with any layers that may be drawn. The main picture
is treated as owned by a LayerAndroid so each component can
decide when to draw.
This change leave the main picture in WebViewCore.cpp, and
draws everything else in WebView.cpp -- in the future, additional
refactoring can put all drawing in one place.
The logic of what to draw is still in WebView.java, but the
actual drawing calls are now triggered inside the layer code.
Android.mk
- Add rule to trigger building without layers from buildspec.mk.
LayerAndroid.*
- Replace FindOnPage reference with abstract DrawExtra class to
draw adornments in the layers' canvas context.
- Add a LayerAndroid constructor to create a dummy layer with a
SkPicture* and a uniqueId==-1 so that extras can detect when
they are drawn by the main picture.
android_graphics.*
- Move cursor ring drawing out of WebView.cpp to here.
- Separate cursor ring setup from actual drawing.
- Get the cursor ring metrics in local coordinates.
ChromeClientAndroid.cpp
- Fix compiler warnings.
WebViewCore.*
- Move updateCursorBounds from WebView.cpp. This permits it to
be called from CursorRing::setup.
CachedFrame.*
CachedNode.*
CachedLayer.*
- Add local bounds getters.
CachedRoot.h
- Move class FindCanvas to the android namespace.
DrawExtra.h
- Add an abstract class called by LayerAndroid to optionally
draw extra elements in its canvas context.
FindCanvas.*
SelectText.*
- Refactor drawing to draw in layers context.
WebView.cpp
- Move drawing from WebView.java.
- Remove selection code to SelectText.cpp.
- Use inverseScale to simplify viewPort metrics.
- Simplify layer root so java doesn't need to know about it.
Requires companion change in frameworks/base
http://b/2457316
http://b/2454127
http://b/2454149
Diffstat (limited to 'WebCore/platform')
-rw-r--r-- | WebCore/platform/graphics/android/LayerAndroid.cpp | 37 | ||||
-rw-r--r-- | WebCore/platform/graphics/android/LayerAndroid.h | 33 | ||||
-rw-r--r-- | WebCore/platform/graphics/android/android_graphics.cpp | 99 | ||||
-rw-r--r-- | WebCore/platform/graphics/android/android_graphics.h | 38 |
4 files changed, 178 insertions, 29 deletions
diff --git a/WebCore/platform/graphics/android/LayerAndroid.cpp b/WebCore/platform/graphics/android/LayerAndroid.cpp index 2dc8a05..59533be 100644 --- a/WebCore/platform/graphics/android/LayerAndroid.cpp +++ b/WebCore/platform/graphics/android/LayerAndroid.cpp @@ -4,8 +4,11 @@ #if USE(ACCELERATED_COMPOSITING) #include "AndroidAnimation.h" -#include "FindCanvas.h" +#include "DrawExtra.h" +#include "SkCanvas.h" #include "SkDrawFilter.h" +#include "SkPaint.h" +#include "SkPicture.h" #include <wtf/CurrentTime.h> #define LAYER_DEBUG // Add diagonals for debugging @@ -50,7 +53,7 @@ LayerAndroid::LayerAndroid(bool isRootLayer) : SkLayer(), m_doRotation(false), m_isFixed(false), m_recordingPicture(0), - m_findOnPage(0), + m_extra(0), m_uniqueId(++gUniqueId) { m_angleTransform = 0; @@ -67,7 +70,7 @@ LayerAndroid::LayerAndroid(const LayerAndroid& layer) : SkLayer(layer), m_drawsContent(layer.m_drawsContent), m_haveImage(layer.m_haveImage), m_haveClip(layer.m_haveClip), - m_findOnPage(0), + m_extra(0), // deliberately not copied m_uniqueId(layer.m_uniqueId) { m_doRotation = layer.m_doRotation; @@ -96,6 +99,26 @@ LayerAndroid::LayerAndroid(const LayerAndroid& layer) : SkLayer(layer), gDebugLayerAndroidInstances++; } +LayerAndroid::LayerAndroid(SkPicture* picture) : SkLayer(), + m_isRootLayer(true), + m_haveContents(false), + m_drawsContent(true), + m_haveImage(false), + m_haveClip(false), + m_doRotation(false), + m_isFixed(false), + m_recordingPicture(picture), + m_extra(0), + m_uniqueId(-1) +{ + m_angleTransform = 0; + m_translation.set(0, 0); + m_scale.set(1, 1); + m_backgroundColor = 0; + SkSafeRef(m_recordingPicture); + gDebugLayerAndroidInstances++; +} + LayerAndroid::~LayerAndroid() { removeChildren(); @@ -314,6 +337,8 @@ void LayerAndroid::onDraw(SkCanvas* canvas, SkScalar opacity) { canvas->setDrawFilter(new OpacityDrawFilter(canvasOpacity)); m_recordingPicture->draw(canvas); + if (m_extra) + m_extra->draw(canvas, this); #ifdef LAYER_DEBUG float w = getSize().width(); @@ -487,11 +512,11 @@ const LayerAndroid* LayerAndroid::findById(int match) const return 0; } -void LayerAndroid::setFindOnPage(FindOnPage* findOnPage) +void LayerAndroid::setExtra(DrawExtra* extra) { - m_findOnPage = findOnPage; + m_extra = extra; for (int i = 0; i < countChildren(); i++) - getChild(i)->setFindOnPage(findOnPage); + getChild(i)->setExtra(extra); } } // namespace WebCore diff --git a/WebCore/platform/graphics/android/LayerAndroid.h b/WebCore/platform/graphics/android/LayerAndroid.h index d3f2357..23c785f 100644 --- a/WebCore/platform/graphics/android/LayerAndroid.h +++ b/WebCore/platform/graphics/android/LayerAndroid.h @@ -25,11 +25,16 @@ #include "StringHash.h" #include <wtf/HashMap.h> -class FindOnPage; class SkCanvas; class SkMatrix; class SkPicture; +namespace android { +class DrawExtra; +} + +using namespace android; + struct SkLength { enum SkLengthType { Undefined, Auto, Relative, Percent, Fixed, Static, Intrinsic, MinIntrinsic }; SkLengthType type; @@ -64,6 +69,7 @@ class LayerAndroid : public SkLayer { public: LayerAndroid(bool isRootLayer); LayerAndroid(const LayerAndroid& layer); + LayerAndroid(SkPicture* ); virtual ~LayerAndroid(); static int instancesCount(); @@ -94,7 +100,6 @@ public: void setHaveContents(bool haveContents) { m_haveContents = haveContents; } void setHaveImage(bool haveImage) { m_haveImage = haveImage; } void setDrawsContent(bool drawsContent); - void setFindOnPage(FindOnPage* findOnPage); void setMaskLayer(LayerAndroid*); void setMasksToBounds(bool); void setIsRootLayer(bool isRootLayer) { m_isRootLayer = isRootLayer; } @@ -132,6 +137,7 @@ public: return static_cast<LayerAndroid*>(this->INHERITED::getChild(index)); } bool haveClip() const { return m_haveClip; } + void setExtra(DrawExtra* extra); // does not assign ownership int uniqueId() const { return m_uniqueId; } protected: @@ -163,7 +169,7 @@ private: typedef HashMap<String, RefPtr<AndroidAnimation> > KeyframesMap; KeyframesMap m_animations; - FindOnPage* m_findOnPage; + DrawExtra* m_extra; int m_uniqueId; typedef SkLayer INHERITED; @@ -171,6 +177,27 @@ private: } +#else + +class SkPicture; + +namespace WebCore { + +class LayerAndroid { +public: + LayerAndroid(SkPicture* picture) : + m_recordingPicture(picture), // does not assign ownership + m_uniqueId(-1) + {} + SkPicture* picture() const { return m_recordingPicture; } + int uniqueId() const { return m_uniqueId; } +private: + SkPicture* m_recordingPicture; + int m_uniqueId; +}; + +} + #endif // USE(ACCELERATED_COMPOSITING) #endif // LayerAndroid_h diff --git a/WebCore/platform/graphics/android/android_graphics.cpp b/WebCore/platform/graphics/android/android_graphics.cpp index af88b8c..fafd3df 100644 --- a/WebCore/platform/graphics/android/android_graphics.cpp +++ b/WebCore/platform/graphics/android/android_graphics.cpp @@ -23,13 +23,18 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "config.h" +#include "CachedPrefix.h" #include "android_graphics.h" +#include "CachedRoot.h" #include "IntRect.h" +#include "LayerAndroid.h" #include "SkCanvas.h" #include "SkCornerPathEffect.h" #include "SkPath.h" #include "SkRegion.h" +#include "WebViewCore.h" + +namespace android { /////////////////////////////////////////////////////////////////////////////// @@ -56,15 +61,26 @@ const static SkColor cursorPressedColors[] = { #define CURSOR_RING_INNER_DIAMETER SkFixedToScalar(SkIntToFixed(3)>>1) // 3/2 == 1.5 #define CURSOR_RING_OUTER_OUTSET 2 // used to inflate rects added to region -void CursorRing::DrawRing(SkCanvas* canvas, - const Vector<WebCore::IntRect>& rects, Flavor flavor) +void CursorRing::draw(SkCanvas* canvas, LayerAndroid* layer) { - unsigned rectCount = rects.size(); - SkRegion rgn; - SkPath path; +#if USE(ACCELERATED_COMPOSITING) + int layerId = m_node->isInLayer() ? m_frame->layer(m_node)->uniqueId() : -1; + if (layer->uniqueId() != layerId) + return; +#endif + if (canvas->quickReject(m_bounds, SkCanvas::kAA_EdgeType)) { + DBG_NAV_LOGD("canvas->quickReject cursorNode=%d (nodePointer=%p)" + " bounds=(%d,%d,w=%d,h=%d)", m_node->index(), m_node->nodePointer(), + m_bounds.x(), m_bounds.y(), m_bounds.width(), m_bounds.height()); + m_followedLink = false; + return; + } + unsigned rectCount = m_rings.size(); + SkRegion rgn; + SkPath path; for (unsigned i = 0; i < rectCount; i++) { - SkRect r(rects[i]); + SkRect r(m_rings[i]); SkIRect ir; r.round(&ir); @@ -76,15 +92,76 @@ void CursorRing::DrawRing(SkCanvas* canvas, SkPaint paint; paint.setAntiAlias(true); paint.setPathEffect(new SkCornerPathEffect(CURSOR_RING_ROUNDEDNESS))->unref(); - if (flavor >= NORMAL_ANIMATING) { // pressed - paint.setColor(cursorPressedColors[flavor - NORMAL_ANIMATING]); + if (m_flavor >= NORMAL_ANIMATING) { // pressed + paint.setColor(cursorPressedColors[m_flavor - NORMAL_ANIMATING]); canvas->drawPath(path, paint); } paint.setStyle(SkPaint::kStroke_Style); paint.setStrokeWidth(CURSOR_RING_OUTER_DIAMETER); - paint.setColor(cursorOuterColors[flavor]); + paint.setColor(cursorOuterColors[m_flavor]); canvas->drawPath(path, paint); paint.setStrokeWidth(CURSOR_RING_INNER_DIAMETER); - paint.setColor(cursorInnerColors[flavor]); + paint.setColor(cursorInnerColors[m_flavor]); canvas->drawPath(path, paint); } + +bool CursorRing::setup() +{ + m_node->localCursorRings(m_frame, &m_rings); + if (!m_rings.size()) { + DBG_NAV_LOG("!rings.size()"); + m_viewImpl->m_hasCursorBounds = false; + return false; + } + m_isButton = false; + m_viewImpl->gButtonMutex.lock(); + // If this is a button drawn by us (rather than webkit) do not draw the + // cursor ring, since its cursor will be shown by a change in what we draw. + // Should be in sync with recordButtons, since that will be called + // before this. + if (m_viewImpl->m_buttons.size() > 0) { + WebCore::Node* cursorPointer = (WebCore::Node*) m_node->nodePointer(); + Container* end = m_viewImpl->m_buttons.end(); + for (Container* ptr = m_viewImpl->m_buttons.begin(); ptr != end; ptr++) { + if (ptr->matches(cursorPointer)) { + m_isButton = true; + break; + } + } + } + m_viewImpl->gButtonMutex.unlock(); + m_bounds = m_node->localBounds(m_frame); + m_viewImpl->updateCursorBounds(m_root, m_frame, m_node); + + bool useHitBounds = m_node->useHitBounds(); + if (useHitBounds) + m_bounds = m_node->localHitBounds(m_frame); + if (useHitBounds || m_node->useBounds()) { + m_rings.clear(); + m_rings.append(m_bounds); + } + m_bounds.inflate(SkScalarCeil(CURSOR_RING_OUTER_DIAMETER)); + if (!m_node->hasCursorRing() || (m_node->isPlugin() && m_node->isFocus())) + return false; + m_flavor = NORMAL_FLAVOR; + if (!m_isButton) { + m_flavor = m_node->isSyntheticLink() ? FAKE_FLAVOR : NORMAL_FLAVOR; + if (m_followedLink) { + m_flavor = static_cast<Flavor>(m_flavor + NORMAL_ANIMATING); + } +#if DEBUG_NAV_UI + const WebCore::IntRect& ring = m_rings[0]; + DBG_NAV_LOGD("cursorNode=%d (nodePointer=%p) flavor=%s rings=%d" + " (%d, %d, %d, %d) isPlugin=%s", + m_node->index(), m_node->nodePointer(), + m_flavor == FAKE_FLAVOR ? "FAKE_FLAVOR" : + m_flavor == NORMAL_ANIMATING ? "NORMAL_ANIMATING" : + m_flavor == FAKE_ANIMATING ? "FAKE_ANIMATING" : "NORMAL_FLAVOR", + m_rings.size(), ring.x(), ring.y(), ring.width(), ring.height(), + m_node->isPlugin() ? "true" : "false"); +#endif + } + return true; +} + +} diff --git a/WebCore/platform/graphics/android/android_graphics.h b/WebCore/platform/graphics/android/android_graphics.h index a286e3a..dbf1978 100644 --- a/WebCore/platform/graphics/android/android_graphics.h +++ b/WebCore/platform/graphics/android/android_graphics.h @@ -26,18 +26,23 @@ #ifndef android_graphics_DEFINED #define android_graphics_DEFINED -#include "wtf/Vector.h" - +#include "DrawExtra.h" +#include "IntRect.h" #include "SkTypes.h" - -class SkCanvas; +#include "wtf/Vector.h" namespace WebCore { - class IntRect; class GraphicsContext; } -SkCanvas* android_gc2canvas(WebCore::GraphicsContext* gc); +SkCanvas* android_gc2canvas(GraphicsContext* gc); + +namespace android { + +class CachedFrame; +class CachedNode; +class CachedRoot; +class WebViewCore; // Data and methods for cursor rings @@ -47,7 +52,7 @@ SkCanvas* android_gc2canvas(WebCore::GraphicsContext* gc); // used to inval rectangle enclosing pressed state of ring #define CURSOR_RING_OUTER_DIAMETER SkFixedToScalar(SkIntToFixed(13)>>2) // 13/4 == 3.25 -struct CursorRing { +class CursorRing : public DrawExtra { public: enum Flavor { NORMAL_FLAVOR, @@ -57,8 +62,23 @@ public: ANIMATING_COUNT = 2 }; - static void DrawRing(SkCanvas* , - const Vector<WebCore::IntRect>& rects, Flavor ); + CursorRing(WebViewCore* core) : m_viewImpl(core) {} + virtual ~CursorRing() {} + virtual void draw(SkCanvas* , LayerAndroid* ); + bool setup(); +private: + friend class WebView; + WebViewCore* m_viewImpl; // copy for convenience + WTF::Vector<IntRect> m_rings; + IntRect m_bounds; + const CachedRoot* m_root; + const CachedFrame* m_frame; + const CachedNode* m_node; + Flavor m_flavor; + bool m_followedLink; + bool m_isButton; }; +} + #endif |