diff options
author | Cary Clark <cary@android.com> | 2010-11-01 17:25:39 -0400 |
---|---|---|
committer | Cary Clark <cary@android.com> | 2010-11-04 15:24:24 -0400 |
commit | 527fb7b2ce688a9d6731ecee454005918a4b966e (patch) | |
tree | 7df367117785882d78091e90affa77dd72a7a0bf | |
parent | 6be0d5f748267d7691c09a458651f0a2d8f9affc (diff) | |
download | external_webkit-527fb7b2ce688a9d6731ecee454005918a4b966e.zip external_webkit-527fb7b2ce688a9d6731ecee454005918a4b966e.tar.gz external_webkit-527fb7b2ce688a9d6731ecee454005918a4b966e.tar.bz2 |
Adjust layers when parent layer scrolls
When a page has layers, it causes the main body of the
page to become a layer as well. The scroll position
of the WebView must be applied to the layer to
translate the cursor rings correctly for hit-testing.
Today, applying the scroll position of the WebView
screws up overflow scrolling. Until this gets figured
out, skip using the scroll position in CacheFrame
adjust() and unadjust().
The position of the layer, and all of its parent layers,
should be considered when adjusting the rectangle
bounds contained by that layer. Before, only the
child layer's position was considered.
The clip used by scrollable divs may be initialized
but never set. If it is empty, ignore it, rather than
clipping out all content.
In CacheBuilder, remove a couple of unnecessary
lines -- the CacheInput initialization clears all
members.
In SelectText, reverse the order of the xfer mode
and paint objects to remove a Skia ref count assert.
In CachedInput, make the debug printout current.
Overall, added more debugging output (turned
off by default).
bug:3030370
Change-Id: Ic19c24b3bf33d081a1d0c1f8c06601dcb56ae881
-rw-r--r-- | WebCore/platform/graphics/android/LayerAndroid.cpp | 25 | ||||
-rw-r--r-- | WebKit/android/nav/CacheBuilder.cpp | 2 | ||||
-rw-r--r-- | WebKit/android/nav/CachedFrame.cpp | 53 | ||||
-rw-r--r-- | WebKit/android/nav/CachedInput.cpp | 7 | ||||
-rw-r--r-- | WebKit/android/nav/CachedLayer.cpp | 96 | ||||
-rw-r--r-- | WebKit/android/nav/CachedLayer.h | 2 | ||||
-rw-r--r-- | WebKit/android/nav/CachedRoot.cpp | 11 | ||||
-rw-r--r-- | WebKit/android/nav/SelectText.cpp | 2 |
8 files changed, 154 insertions, 44 deletions
diff --git a/WebCore/platform/graphics/android/LayerAndroid.cpp b/WebCore/platform/graphics/android/LayerAndroid.cpp index 5210171..f88401c 100644 --- a/WebCore/platform/graphics/android/LayerAndroid.cpp +++ b/WebCore/platform/graphics/android/LayerAndroid.cpp @@ -342,10 +342,12 @@ void LayerAndroid::findInner(LayerAndroidFindState& state) const bounds(&localBounds); if (!localBounds.contains(x, y)) return; - if (!m_recordingPicture) - return; - if (!state.drew(m_recordingPicture, localBounds)) - return; + if (!m_foregroundPicture) { + if (!m_recordingPicture) + return; + if (!state.drew(m_recordingPicture, localBounds)) + return; + } state.setBest(this); // set last match (presumably on top) } @@ -688,8 +690,19 @@ void LayerAndroid::dumpLayers(FILE* file, int indentLevel) const } if (m_recordingPicture) { - writeIntVal(file, indentLevel + 1, "picture width", m_recordingPicture->width()); - writeIntVal(file, indentLevel + 1, "picture height", m_recordingPicture->height()); + writeIntVal(file, indentLevel + 1, "m_recordingPicture.width", m_recordingPicture->width()); + writeIntVal(file, indentLevel + 1, "m_recordingPicture.height", m_recordingPicture->height()); + } + + if (m_foregroundPicture) { + writeIntVal(file, indentLevel + 1, "m_foregroundPicture.width", m_foregroundPicture->width()); + writeIntVal(file, indentLevel + 1, "m_foregroundPicture.height", m_foregroundPicture->height()); + writeFloatVal(file, indentLevel + 1, "m_foregroundClip.fLeft", m_foregroundClip.fLeft); + writeFloatVal(file, indentLevel + 1, "m_foregroundClip.fTop", m_foregroundClip.fTop); + writeFloatVal(file, indentLevel + 1, "m_foregroundClip.fRight", m_foregroundClip.fRight); + writeFloatVal(file, indentLevel + 1, "m_foregroundClip.fBottom", m_foregroundClip.fBottom); + writeFloatVal(file, indentLevel + 1, "m_foregroundLocation.fX", m_foregroundLocation.fX); + writeFloatVal(file, indentLevel + 1, "m_foregroundLocation.fY", m_foregroundLocation.fY); } if (countChildren()) { diff --git a/WebKit/android/nav/CacheBuilder.cpp b/WebKit/android/nav/CacheBuilder.cpp index 42a4b53..a7015e7 100644 --- a/WebKit/android/nav/CacheBuilder.cpp +++ b/WebKit/android/nav/CacheBuilder.cpp @@ -1265,7 +1265,6 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame, cachedInput.init(); cachedInput.setFormPointer(input->form()); cachedInput.setIsTextField(true); - cachedInput.setIsTextArea(false); exported = input->value().threadsafeCopy(); cachedInput.setMaxLength(input->maxLength()); cachedInput.setTypeFromElement(input); @@ -1282,7 +1281,6 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame, HTMLTextAreaElement* area = static_cast<HTMLTextAreaElement*>(node); cachedInput.setFormPointer(area->form()); cachedInput.setIsTextArea(true); - cachedInput.setIsTextField(false); exported = area->value().threadsafeCopy(); } else if (node->hasTagName(HTMLNames::aTag)) { const HTMLAnchorElement* anchorNode = diff --git a/WebKit/android/nav/CachedFrame.cpp b/WebKit/android/nav/CachedFrame.cpp index ced87e0..e331464 100644 --- a/WebKit/android/nav/CachedFrame.cpp +++ b/WebKit/android/nav/CachedFrame.cpp @@ -27,6 +27,7 @@ #include "CachedHistory.h" #include "CachedNode.h" #include "CachedRoot.h" +#include "LayerAndroid.h" #include "CachedFrame.h" @@ -39,10 +40,22 @@ namespace android { WebCore::IntRect CachedFrame::adjustBounds(const CachedNode* node, const WebCore::IntRect& rect) const { - DBG_NAV_LOGD("node=%p [%d] rect=(%d,%d,w=%d,h=%d)", - node, node->index(), rect.x(), rect.y(), rect.width(), rect.height()); + DBG_NAV_LOGV("node=%p [%d] rect=(%d,%d,w=%d,h=%d) view=(%d,%d,w=%d,h=%d)" + " local=(%d,%d,w=%d,h=%d) root=(%d,%d,w=%d,h=%d)", + node, node->index(), rect.x(), rect.y(), rect.width(), rect.height(), + mViewBounds.x(), mViewBounds.y(), + mViewBounds.width(), mViewBounds.height(), + mLocalViewBounds.x(), mLocalViewBounds.y(), + mLocalViewBounds.width(), mLocalViewBounds.height(), + mRoot->mViewBounds.x(), mRoot->mViewBounds.y(), + mRoot->mViewBounds.width(), mRoot->mViewBounds.height()); #if USE(ACCELERATED_COMPOSITING) - return layer(node)->adjustBounds(mRoot->rootLayer(), rect); + const CachedLayer* cachedLayer = layer(node); + const WebCore::LayerAndroid* rootLayer = mRoot->rootLayer(); + IntRect rrect = cachedLayer->adjustBounds(rootLayer, rect); + if (!cachedLayer->layer(rootLayer)->contentIsScrollable()) + rrect.move(-mViewBounds.x(), -mViewBounds.y()); + return rrect; #else return rect; #endif @@ -55,8 +68,14 @@ WebCore::IntRect CachedFrame::unadjustBounds(const CachedNode* node, const WebCore::IntRect& rect) const { #if USE(ACCELERATED_COMPOSITING) - if (node->isInLayer()) - return layer(node)->unadjustBounds(mRoot->rootLayer(), rect); + if (node->isInLayer()) { + const CachedLayer* cachedLayer = layer(node); + const WebCore::LayerAndroid* rootLayer = mRoot->rootLayer(); + IntRect rrect = cachedLayer->unadjustBounds(rootLayer, rect); + if (!cachedLayer->layer(rootLayer)->contentIsScrollable()) + rrect.move(mViewBounds.x(), mViewBounds.y()); + return rrect; + } #endif return rect; } @@ -391,21 +410,27 @@ const CachedNode* CachedFrame::findBestAt(const WebCore::IntRect& rect, bool checkForHidden = checkForHiddenStart; for (size_t part = 0; part < parts; part++) { WebCore::IntRect testRect = test->ring(this, part); - if (test->isInLayer()) { - DBG_NAV_LOGD("[%d] intersects=%ss testRect=(%d,%d,w=%d,h=%d)" - " rect=(%d,%d,w=%d,h=%d)", test->index(), - testRect.intersects(rect) ? "true" : "false", - testRect.x(), testRect.y(), testRect.width(), testRect.height(), - rect.x(), rect.y(), rect.width(), rect.height()); - } if (testRect.intersects(rect)) { - if (checkForHidden && mRoot->maskIfHidden(&testData) == true) +#if DEBUG_NAV_UI + if (test->isInLayer()) { + DBG_NAV_LOGD("[%d] intersects=%s testRect=(%d,%d,w=%d,h=%d)" + " rect=(%d,%d,w=%d,h=%d)", test->index(), + testRect.intersects(rect) ? "true" : "false", + testRect.x(), testRect.y(), + testRect.width(), testRect.height(), + rect.x(), rect.y(), rect.width(), rect.height()); + } +#endif + if (checkForHidden && mRoot->maskIfHidden(&testData) == true) { + DBG_NAV_LOGD("hidden [%d]", test->index()); break; + } checkForHidden = false; testRect.intersect(testData.mouseBounds()); if (testRect.contains(center)) { // We have a direct hit. if (*directHit == NULL) { + DBG_NAV_LOGD("direct hit 1 [%d]", test->index()); *directHit = test; *directHitFramePtr = this; IntRect r(center, IntSize(0, 0)); @@ -413,6 +438,7 @@ const CachedNode* CachedFrame::findBestAt(const WebCore::IntRect& rect, *x = r.x(); *y = r.y(); } else { + DBG_NAV_LOGD("direct hit 2 [%d]", test->index()); // We have hit another one before const CachedNode* d = *directHit; if (d->bounds(this).contains(testRect)) { @@ -428,6 +454,7 @@ const CachedNode* CachedFrame::findBestAt(const WebCore::IntRect& rect, // calculate the distances, or check the other parts break; } + DBG_NAV_LOGD("indirect hit [%d]", test->index()); WebCore::IntRect both = rect; int smaller = testRect.width() < testRect.height() ? testRect.width() : testRect.height(); diff --git a/WebKit/android/nav/CachedInput.cpp b/WebKit/android/nav/CachedInput.cpp index 45172fb..6ba3f2e 100644 --- a/WebKit/android/nav/CachedInput.cpp +++ b/WebKit/android/nav/CachedInput.cpp @@ -79,17 +79,18 @@ static void printWebCoreString(const char* label, void CachedInput::Debug::print() const { CachedInput* b = base(); - printWebCoreString("// char* mName=\"", b->mName); DUMP_NAV_LOGD("// void* mForm=%p;\n", b->mForm); + printWebCoreString("// char* mName=\"", b->mName); DUMP_NAV_LOGD("// int mMaxLength=%d;\n", b->mMaxLength); - DUMP_NAV_LOGD("// int mTextSize=%d;\n", b->mTextSize); - DUMP_NAV_LOGD("// int mInputType=%d;\n", b->mInputType); DUMP_NAV_LOGD("// int mPaddingLeft=%d;\n", b->mPaddingLeft); DUMP_NAV_LOGD("// int mPaddingTop=%d;\n", b->mPaddingTop); DUMP_NAV_LOGD("// int mPaddingRight=%d;\n", b->mPaddingRight); DUMP_NAV_LOGD("// int mPaddingBottom=%d;\n", b->mPaddingBottom); + DUMP_NAV_LOGD("// int mTextSize=%d;\n", b->mTextSize); + DUMP_NAV_LOGD("// Type mType=%d;\n", b->mType); DEBUG_PRINT_BOOL(mIsRtlText); DEBUG_PRINT_BOOL(mIsTextField); + DEBUG_PRINT_BOOL(mIsTextArea); } #endif diff --git a/WebKit/android/nav/CachedLayer.cpp b/WebKit/android/nav/CachedLayer.cpp index f6b1859..5ad5c8b 100644 --- a/WebKit/android/nav/CachedLayer.cpp +++ b/WebKit/android/nav/CachedLayer.cpp @@ -55,7 +55,7 @@ IntRect CachedLayer::adjustBounds(const LayerAndroid* root, // Next, add in the new position of the layer (could be different due to a // fixed position layer). - const FloatPoint& position = aLayer->getPosition(); + FloatPoint position = getGlobalPosition(aLayer); temp.move(position.x(), position.y()); // Add in any layer translation. @@ -71,12 +71,13 @@ IntRect CachedLayer::adjustBounds(const LayerAndroid* root, // Finally, clip the result to the foreground (this includes the object's // border which does not scroll). IntRect clip(aLayer->foregroundClip()); - clip.move(position.x(), position.y()); - result.intersect(clip); + if (!clip.isEmpty()) { + clip.move(position.x(), position.y()); + result.intersect(clip); + } - DBG_NAV_LOGD("root=%p aLayer=%p [%d]" - " bounds=(%d,%d,w=%d,h=%d) trans=(%g,%g)" - " pos=(%f,%f)" + DBG_NAV_LOGV("root=%p aLayer=%p [%d]" + " bounds=(%d,%d,w=%d,h=%d) trans=(%g,%g) pos=(%f,%f)" " offset=(%d,%d) clip=(%d,%d,w=%d,h=%d)" " scroll=(%d,%d) origScroll=(%d,%d)" " result=(%d,%d,w=%d,h=%d)", @@ -100,7 +101,8 @@ IntRect CachedLayer::unadjustBounds(const LayerAndroid* root, IntRect temp = bounds; // Remove the new position (i.e. fixed position elements). - const FloatPoint& position = aLayer->getPosition(); + FloatPoint position = getGlobalPosition(aLayer); + temp.move(-position.x(), -position.y()); // Remove any layer translation. @@ -116,9 +118,34 @@ IntRect CachedLayer::unadjustBounds(const LayerAndroid* root, // Move the bounds by the original scroll. temp.move(-mScrollOffset.x(), -mScrollOffset.y()); + DBG_NAV_LOGD("root=%p aLayer=%p [%d]" + " bounds=(%d,%d,w=%d,h=%d) trans=(%g,%g) pos=(%f,%f)" + " offset=(%d,%d)" + " scroll=(%d,%d) origScroll=(%d,%d)" + " result=(%d,%d,w=%d,h=%d)", + root, aLayer, aLayer->uniqueId(), + bounds.x(), bounds.y(), bounds.width(), bounds.height(), + translation.x(), translation.y(), position.x(), position.y(), + mOffset.x(), mOffset.y(), + SkScalarRound(scroll.fX), SkScalarRound(scroll.fY), + mScrollOffset.x(), mScrollOffset.y(), + temp.x(), temp.y(), temp.width(), temp.height()); return temp; } +FloatPoint CachedLayer::getGlobalPosition(const LayerAndroid* aLayer) const +{ + SkPoint result = aLayer->getPosition(); + const SkLayer* parent = aLayer->getParent(); + while (parent) { + result += parent->getPosition(); + DBG_NAV_LOGV("result=(%g,%g) parent=%p [%d]", result.fX, result.fY, + parent, ((LayerAndroid*) parent)->uniqueId()); + parent = parent->getParent(); + } + return result; +} + const LayerAndroid* CachedLayer::layer(const LayerAndroid* root) const { if (!root || mLayer) @@ -139,7 +166,14 @@ IntRect CachedLayer::localBounds(const LayerAndroid* root, temp.move(mScrollOffset.x(), mScrollOffset.y()); const LayerAndroid* aLayer = layer(root); + FloatPoint position; if (aLayer) { + const LayerAndroid* parent = static_cast<const LayerAndroid*> + (aLayer->getParent()); + if (parent) { + position = getGlobalPosition(parent); + temp.move(-position.x(), -position.y()); + } // Move the bounds by the scroll position of the layer. const SkPoint& scroll = aLayer->scrollPosition(); temp.move(SkScalarToFloat(-scroll.fX), SkScalarToFloat(-scroll.fY)); @@ -147,13 +181,26 @@ IntRect CachedLayer::localBounds(const LayerAndroid* root, // Clip by the layer's foreground bounds. Since the bounds have // already be moved local to the layer, no need to move the foreground // clip. - temp.intersect(IntRect(aLayer->foregroundClip())); + IntRect foregroundClip(aLayer->foregroundClip()); + if (!foregroundClip.isEmpty()) + temp.intersect(foregroundClip); } - DBG_NAV_LOGD("bounds=(%d,%d,w=%d,h=%d) offset=(%d,%d)" - " result=(%d,%d,w=%d,h=%d)", bounds.x(), bounds.y(), - bounds.width(), bounds.height(), mOffset.x(), mOffset.y(), - temp.x(), temp.y(), temp.width(), temp.height()); +#if DEBUG_NAV_UI + const FloatPoint& translation = aLayer->translation(); + SkPoint scroll = SkPoint::Make(0,0); + if (aLayer) scroll = aLayer->scrollPosition(); + DBG_NAV_LOGD("aLayer=%p [%d] bounds=(%d,%d,w=%d,h=%d) offset=(%d,%d)" + " scrollOffset=(%d,%d) position=(%g,%g) result=(%d,%d,w=%d,h=%d)" + " scroll=(%d,%d) trans=(%g,%g)", + aLayer, aLayer ? aLayer->uniqueId() : 0, + bounds.x(), bounds.y(), bounds.width(), bounds.height(), + mOffset.x(), mOffset.y(), + mScrollOffset.x(), mScrollOffset.y(), position.x(), position.y(), + temp.x(), temp.y(), temp.width(), temp.height(), + scroll.fX, scroll.fY, + translation.x(), translation.y()); +#endif return temp; } @@ -189,10 +236,14 @@ CachedLayer* CachedLayer::Debug::base() const { void CachedLayer::Debug::print() const { CachedLayer* b = base(); - DUMP_NAV_LOGD(" // int mCachedNodeIndex=%d;", b->mCachedNodeIndex); - DUMP_NAV_LOGD(" LayerAndroid* mLayer=%p;", b->mLayer); - DUMP_NAV_LOGD(" int mOffset=(%d, %d);", b->mOffset.x(), b->mOffset.y()); - DUMP_NAV_LOGD(" int mUniqueId=%p;\n", b->mUniqueId); + DUMP_NAV_LOGD(" // int mCachedNodeIndex=%d;\n", b->mCachedNodeIndex); + DUMP_NAV_LOGD(" // LayerAndroid* mLayer=%p;\n", b->mLayer); + DUMP_NAV_LOGD(" // int mOffset=(%d, %d);\n", + b->mOffset.x(), b->mOffset.y()); + DUMP_NAV_LOGD(" // int mScrollOffset=(%d, %d);\n", + b->mScrollOffset.x(), b->mScrollOffset.y()); + DUMP_NAV_LOGD(" // int mUniqueId=%p;\n", b->mUniqueId); + DUMP_NAV_LOGD("%s\n", ""); } #endif @@ -206,9 +257,20 @@ void CachedLayer::Debug::printLayerAndroid(const LayerAndroid* layer) ++spaces; SkRect bounds; layer->bounds(&bounds); - DUMP_NAV_LOGX("%.*s layer=%p [%d] (%g,%g,%g,%g) picture=%p clipped=%s", + DUMP_NAV_LOGD("%.*s layer=%p [%d] (%g,%g,%g,%g)" + " position=(%g,%g) translation=(%g,%g) anchor=(%g,%g)" + " matrix=(%g,%g) childMatrix=(%g,%g)" + " foregroundLocation=(%g,%g)" + " picture=%p clipped=%s\n", spaces, " ", layer, layer->uniqueId(), bounds.fLeft, bounds.fTop, bounds.width(), bounds.height(), + layer->getPosition().fX, layer->getPosition().fY, + layer->translation().fX, layer->translation().fY, + layer->getAnchorPoint().fX, layer->getAnchorPoint().fY, + layer->getMatrix().getTranslateX(), layer->getMatrix().getTranslateY(), + layer->getChildrenMatrix().getTranslateX(), + layer->getChildrenMatrix().getTranslateY(), + layer->scrollPosition().fX, layer->scrollPosition().fY, layer->picture(), layer->m_haveClip ? "true" : "false"); for (int i = 0; i < layer->countChildren(); i++) printLayerAndroid(layer->getChild(i)); diff --git a/WebKit/android/nav/CachedLayer.h b/WebKit/android/nav/CachedLayer.h index a6e4e89..fd5f4a0 100644 --- a/WebKit/android/nav/CachedLayer.h +++ b/WebKit/android/nav/CachedLayer.h @@ -32,6 +32,7 @@ class SkPicture; namespace WebCore { + class FloatPoint; class LayerAndroid; } @@ -52,6 +53,7 @@ public: IntRect unadjustBounds(const LayerAndroid* root, const IntRect& bounds) const; int cachedNodeIndex() const { return mCachedNodeIndex; } + FloatPoint getGlobalPosition(const LayerAndroid* ) const; const LayerAndroid* layer(const LayerAndroid* root) const; IntRect localBounds(const LayerAndroid* root, const IntRect& bounds) const; SkPicture* picture(const LayerAndroid* root) const; diff --git a/WebKit/android/nav/CachedRoot.cpp b/WebKit/android/nav/CachedRoot.cpp index 1897cc0..813357c 100644 --- a/WebKit/android/nav/CachedRoot.cpp +++ b/WebKit/android/nav/CachedRoot.cpp @@ -27,6 +27,7 @@ #include "android_graphics.h" #include "CachedHistory.h" #include "CachedInput.h" +#include "CachedLayer.h" #include "CachedNode.h" #include "FindCanvas.h" #include "FloatRect.h" @@ -1205,6 +1206,11 @@ void CachedRoot::draw(FindCanvas& canvas) const const CachedNode* CachedRoot::findAt(const WebCore::IntRect& rect, const CachedFrame** framePtr, int* x, int* y, bool checkForHidden) const { +#if DEBUG_NAV_UI + DBG_NAV_LOGD("rect=(%d,%d,w=%d,h=%d) xy=(%d,%d)", rect.x(), rect.y(), + rect.width(), rect.height(), *x, *y); + if (mRootLayer) CachedLayer::Debug::printRootLayerAndroid(mRootLayer); +#endif int best = INT_MAX; bool inside = false; (const_cast<CachedRoot*>(this))->resetClippedOut(); @@ -1212,8 +1218,8 @@ const CachedNode* CachedRoot::findAt(const WebCore::IntRect& rect, const CachedNode* directHit = NULL; const CachedNode* node = findBestAt(rect, &best, &inside, &directHit, &directHitFramePtr, framePtr, x, y, checkForHidden); - DBG_NAV_LOGD("node=%d (%p)", node == NULL ? 0 : node->index(), - node == NULL ? NULL : node->nodePointer()); + DBG_NAV_LOGD("node=%d (%p) xy=(%d,%d)", node == NULL ? 0 : node->index(), + node == NULL ? NULL : node->nodePointer(), *x, *y); if (node == NULL) { node = findBestHitAt(rect, framePtr, x, y); DBG_NAV_LOGD("node=%d (%p)", node == NULL ? 0 : node->index(), @@ -1840,6 +1846,7 @@ void CachedRoot::Debug::print() const b->mHistory->mDebug.print(b); DUMP_NAV_LOGD("// int mMaxXScroll=%d, mMaxYScroll=%d;\n", b->mMaxXScroll, b->mMaxYScroll); + CachedLayer::Debug::printRootLayerAndroid(b->mRootLayer); #ifdef DUMP_NAV_CACHE_USING_PRINTF if (gNavCacheLogFile) fclose(gNavCacheLogFile); diff --git a/WebKit/android/nav/SelectText.cpp b/WebKit/android/nav/SelectText.cpp index d1f8274..4af9521 100644 --- a/WebKit/android/nav/SelectText.cpp +++ b/WebKit/android/nav/SelectText.cpp @@ -1305,11 +1305,11 @@ void SelectText::drawSelectionPointer(SkCanvas* canvas) getSelectionCaret(&path); else getSelectionArrow(&path); + SkPixelXorXfermode xorMode(SK_ColorWHITE); SkPaint paint; paint.setAntiAlias(true); paint.setStyle(SkPaint::kStroke_Style); paint.setColor(SK_ColorBLACK); - SkPixelXorXfermode xorMode(SK_ColorWHITE); if (m_extendSelection) paint.setXfermode(&xorMode); else |