diff options
author | Teng-Hui Zhu <ztenghui@google.com> | 2010-09-30 15:32:21 -0700 |
---|---|---|
committer | Teng-Hui Zhu <ztenghui@google.com> | 2010-10-04 10:17:12 -0700 |
commit | 5abcebdcce80658b012cd1de400558035899457c (patch) | |
tree | d3289bf8e7d1fe66f5e963f9a7cbf97541ec128b /WebCore/platform/graphics/android/GraphicsContextAndroid.cpp | |
parent | 740f5071cda344b465351484f5362492fef31b5b (diff) | |
download | external_webkit-5abcebdcce80658b012cd1de400558035899457c.zip external_webkit-5abcebdcce80658b012cd1de400558035899457c.tar.gz external_webkit-5abcebdcce80658b012cd1de400558035899457c.tar.bz2 |
Add AA to the border radius
In order to enable AA for the border radius, add an extra layer for drawing and then clearing by using AA paint. The reason why clipping can't show AA is that it is 1-bit clip.
Change-Id: Ic9fa99915fb908e502dcb90cfe1428bb4d8e136b
http://b/3003023
Diffstat (limited to 'WebCore/platform/graphics/android/GraphicsContextAndroid.cpp')
-rw-r--r-- | WebCore/platform/graphics/android/GraphicsContextAndroid.cpp | 89 |
1 files changed, 75 insertions, 14 deletions
diff --git a/WebCore/platform/graphics/android/GraphicsContextAndroid.cpp b/WebCore/platform/graphics/android/GraphicsContextAndroid.cpp index 5371e60..9304c4d 100644 --- a/WebCore/platform/graphics/android/GraphicsContextAndroid.cpp +++ b/WebCore/platform/graphics/android/GraphicsContextAndroid.cpp @@ -22,7 +22,6 @@ * (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 "GraphicsContext.h" @@ -96,7 +95,10 @@ public: SkColor mFillColor; SkColor mStrokeColor; bool mUseAA; - + // This is a list of clipping paths which are currently active, in the + // order in which they were pushed. + WTF::Vector<SkPath> m_antiAliasClipPaths; + State() { mPath = NULL; // lazily allocated mPathEffect = 0; @@ -113,8 +115,20 @@ public: mStrokeColor = SK_ColorBLACK; } - State(const State& other) { - memcpy(this, &other, sizeof(State)); + State(const State& other) + : mPathEffect(other.mPathEffect) + , mMiterLimit(other.mMiterLimit) + , mAlpha(other.mAlpha) + , mStrokeThickness(other.mStrokeThickness) + , mLineCap(other.mLineCap) + , mLineJoin(other.mLineJoin) + , mMode(other.mMode) + , mDashRatio(other.mDashRatio) + , mShadow(other.mShadow) + , mFillColor(other.mFillColor) + , mStrokeColor(other.mStrokeColor) + , mUseAA(other.mUseAA) + { mPath = deepCopyPtr<SkPath>(other.mPath); mPathEffect->safeRef(); } @@ -180,14 +194,19 @@ public: while (mStateStack.count() > 0) this->restore(); } - - void save() { + + void save() + { State* newState = (State*)mStateStack.push_back(); new (newState) State(*mState); mState = newState; } - void restore() { + void restore() + { + if (!mState->m_antiAliasClipPaths.isEmpty()) + applyAntiAliasedClipPaths(mState->m_antiAliasClipPaths); + mState->~State(); mStateStack.pop_back(); mState = (State*)mStateStack.back(); @@ -308,6 +327,46 @@ public: return false; } + void clipPathAntiAliased(const SkPath& clipPath) + { + // If we are currently tracking any anti-alias clip paths, then we already + // have a layer in place and don't need to add another. + bool haveLayerOutstanding = mState->m_antiAliasClipPaths.size(); + + // See comments in applyAntiAliasedClipPaths about how this works. + mState->m_antiAliasClipPaths.append(clipPath); + if (!haveLayerOutstanding) { + SkRect bounds = clipPath.getBounds(); + if (mPgc && mPgc->mCanvas) { + mPgc->mCanvas->saveLayerAlpha(&bounds, 255, + static_cast<SkCanvas::SaveFlags>(SkCanvas::kHasAlphaLayer_SaveFlag + | SkCanvas::kFullColorLayer_SaveFlag + | SkCanvas::kClipToLayer_SaveFlag)); + } else + ASSERT(0); + } + } + + void applyAntiAliasedClipPaths(WTF::Vector<SkPath>& paths) + { + // Anti-aliased clipping: + // + // Refer to PlatformContextSkia.cpp's applyAntiAliasedClipPaths() for more details + SkPaint paint; + paint.setXfermodeMode(SkXfermode::kClear_Mode); + paint.setAntiAlias(true); + paint.setStyle(SkPaint::kFill_Style); + + if (mPgc && mPgc->mCanvas) { + for (size_t i = paths.size() - 1; i < paths.size(); --i) { + paths[i].setFillType(SkPath::kInverseWinding_FillType); + mPgc->mCanvas->drawPath(paths[i], paint); + } + mPgc->mCanvas->restore(); + } else + ASSERT(0); + } + private: // not supported yet State& operator=(const State&); @@ -385,10 +444,10 @@ void GraphicsContext::savePlatformState() void GraphicsContext::restorePlatformState() { - // restore our native canvas - GC2Canvas(this)->restore(); // restore our private State m_data->restore(); + // restore our native canvas + GC2Canvas(this)->restore(); } bool GraphicsContext::willFill() const { @@ -735,7 +794,7 @@ void GraphicsContext::clip(const Path& path) // path.platformPath()->dump(false, "clip path"); - GC2Canvas(this)->clipPath(*path.platformPath()); + m_data->clipPathAntiAliased(*path.platformPath()); } void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness) @@ -750,12 +809,14 @@ void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness path.addOval(r, SkPath::kCW_Direction); // only perform the inset if we won't invert r - if (2*thickness < rect.width() && 2*thickness < rect.height()) - { - r.inset(SkIntToScalar(thickness) ,SkIntToScalar(thickness)); + if (2*thickness < rect.width() && 2*thickness < rect.height()) { + // Adding one to the thickness doesn't make the border too thick as + // it's painted over afterwards. But without this adjustment the + // border appears a little anemic after anti-aliasing. + r.inset(SkIntToScalar(thickness+1), SkIntToScalar(thickness+1)); path.addOval(r, SkPath::kCCW_Direction); } - GC2Canvas(this)->clipPath(path); + m_data->clipPathAntiAliased(path); } void GraphicsContext::canvasClip(const Path& path) |