| Index: third_party/WebKit/Source/modules/canvas2d/BaseRenderingContext2D.cpp | 
| diff --git a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.cpp b/third_party/WebKit/Source/modules/canvas2d/BaseRenderingContext2D.cpp | 
| similarity index 43% | 
| copy from third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.cpp | 
| copy to third_party/WebKit/Source/modules/canvas2d/BaseRenderingContext2D.cpp | 
| index fdcfd12a44b4b55eb6ac77b05aa4155e49ea5428..7072ec0678cc326f28819648969157fa2994574a 100644 | 
| --- a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.cpp | 
| +++ b/third_party/WebKit/Source/modules/canvas2d/BaseRenderingContext2D.cpp | 
| @@ -1,324 +1,50 @@ | 
| -/* | 
| - * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved. | 
| - * Copyright (C) 2008, 2010 Nokia Corporation and/or its subsidiary(-ies) | 
| - * Copyright (C) 2007 Alp Toker <alp@atoker.com> | 
| - * Copyright (C) 2008 Eric Seidel <eric@webkit.org> | 
| - * Copyright (C) 2008 Dirk Schulze <krit@webkit.org> | 
| - * Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved. | 
| - * Copyright (C) 2012, 2013 Intel Corporation. All rights reserved. | 
| - * Copyright (C) 2013 Adobe Systems Incorporated. All rights reserved. | 
| - * | 
| - * Redistribution and use in source and binary forms, with or without | 
| - * modification, are permitted provided that the following conditions | 
| - * are met: | 
| - * 1. Redistributions of source code must retain the above copyright | 
| - *    notice, this list of conditions and the following disclaimer. | 
| - * 2. 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 APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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 "modules/canvas2d/CanvasRenderingContext2D.h" | 
| +// Copyright 2016 The Chromium Authors. All rights reserved. | 
| +// Use of this source code is governed by a BSD-style license that can be | 
| +// found in the LICENSE file. | 
| + | 
| +#include "modules/canvas2d/BaseRenderingContext2D.h" | 
|  | 
| #include "bindings/core/v8/ExceptionMessages.h" | 
| #include "bindings/core/v8/ExceptionState.h" | 
| #include "bindings/core/v8/ExceptionStatePlaceholder.h" | 
| -#include "core/CSSPropertyNames.h" | 
| -#include "core/css/StylePropertySet.h" | 
| #include "core/css/parser/CSSParser.h" | 
| -#include "core/css/resolver/StyleResolver.h" | 
| -#include "core/dom/AXObjectCache.h" | 
| -#include "core/dom/StyleEngine.h" | 
| -#include "core/events/Event.h" | 
| #include "core/frame/ImageBitmap.h" | 
| -#include "core/frame/Settings.h" | 
| +#include "core/html/HTMLCanvasElement.h" | 
| +#include "core/html/HTMLImageElement.h" | 
| #include "core/html/HTMLVideoElement.h" | 
| #include "core/html/ImageData.h" | 
| -#include "core/html/TextMetrics.h" | 
| -#include "core/html/canvas/CanvasFontCache.h" | 
| -#include "core/layout/LayoutBox.h" | 
| -#include "core/layout/LayoutTheme.h" | 
| #include "modules/canvas2d/CanvasGradient.h" | 
| #include "modules/canvas2d/CanvasPattern.h" | 
| -#include "modules/canvas2d/CanvasRenderingContext2DState.h" | 
| #include "modules/canvas2d/CanvasStyle.h" | 
| -#include "modules/canvas2d/HitRegion.h" | 
| #include "modules/canvas2d/Path2D.h" | 
| -#include "platform/fonts/FontCache.h" | 
| #include "platform/geometry/FloatQuad.h" | 
| -#include "platform/graphics/DrawLooperBuilder.h" | 
| +#include "platform/graphics/Color.h" | 
| #include "platform/graphics/ExpensiveCanvasHeuristicParameters.h" | 
| +#include "platform/graphics/Image.h" | 
| #include "platform/graphics/ImageBuffer.h" | 
| #include "platform/graphics/StrokeData.h" | 
| #include "platform/graphics/skia/SkiaUtils.h" | 
| -#include "platform/text/BidiTextRun.h" | 
| -#include "public/platform/Platform.h" | 
| -#include "third_party/skia/include/core/SkCanvas.h" | 
| #include "third_party/skia/include/core/SkImageFilter.h" | 
| -#include "wtf/ArrayBufferContents.h" | 
| -#include "wtf/CheckedArithmetic.h" | 
| -#include "wtf/MathExtras.h" | 
| -#include "wtf/OwnPtr.h" | 
| -#include "wtf/text/StringBuilder.h" | 
|  | 
| namespace blink { | 
|  | 
| -static const char defaultFont[] = "10px sans-serif"; | 
| -static const char inherit[] = "inherit"; | 
| -static const char rtl[] = "rtl"; | 
| -static const char ltr[] = "ltr"; | 
| -static const double TryRestoreContextInterval = 0.5; | 
| -static const unsigned MaxTryRestoreContextAttempts = 4; | 
| -static const double cDeviceScaleFactor = 1.0; // Canvas is device independent | 
| - | 
| -static bool contextLostRestoredEventsEnabled() | 
| -{ | 
| -    return RuntimeEnabledFeatures::experimentalCanvasFeaturesEnabled(); | 
| -} | 
| - | 
| -// Drawing methods need to use this instead of SkAutoCanvasRestore in case overdraw | 
| -// detection substitutes the recording canvas (to discard overdrawn draw calls). | 
| -class CanvasRenderingContext2DAutoRestoreSkCanvas { | 
| -    STACK_ALLOCATED(); | 
| -public: | 
| -    explicit CanvasRenderingContext2DAutoRestoreSkCanvas(CanvasRenderingContext2D* context) | 
| -        : m_context(context) | 
| -        , m_saveCount(0) | 
| -    { | 
| -        ASSERT(m_context); | 
| -        SkCanvas* c = m_context->drawingCanvas(); | 
| -        if (c) { | 
| -            m_saveCount = c->getSaveCount(); | 
| -        } | 
| -    } | 
| - | 
| -    ~CanvasRenderingContext2DAutoRestoreSkCanvas() | 
| -    { | 
| -        SkCanvas* c = m_context->drawingCanvas(); | 
| -        if (c) | 
| -            c->restoreToCount(m_saveCount); | 
| -        m_context->validateStateStack(); | 
| -    } | 
| -private: | 
| -    RawPtrWillBeMember<CanvasRenderingContext2D> m_context; | 
| -    int m_saveCount; | 
| -}; | 
| - | 
| -CanvasRenderingContext2D::CanvasRenderingContext2D(HTMLCanvasElement* canvas, const CanvasContextCreationAttributes& attrs, Document& document) | 
| -    : CanvasRenderingContext(canvas) | 
| -    , m_clipAntialiasing(NotAntiAliased) | 
| -    , m_hasAlpha(attrs.alpha()) | 
| -    , m_contextLostMode(NotLostContext) | 
| -    , m_contextRestorable(true) | 
| -    , m_tryRestoreContextAttemptCount(0) | 
| -    , m_dispatchContextLostEventTimer(this, &CanvasRenderingContext2D::dispatchContextLostEvent) | 
| -    , m_dispatchContextRestoredEventTimer(this, &CanvasRenderingContext2D::dispatchContextRestoredEvent) | 
| -    , m_tryRestoreContextEventTimer(this, &CanvasRenderingContext2D::tryRestoreContextEvent) | 
| -    , m_pruneLocalFontCacheScheduled(false) | 
| -{ | 
| -    if (document.settings() && document.settings()->antialiasedClips2dCanvasEnabled()) | 
| -        m_clipAntialiasing = AntiAliased; | 
| -    m_stateStack.append(CanvasRenderingContext2DState::create()); | 
| -    setShouldAntialias(true); | 
| -#if ENABLE(OILPAN) | 
| -    ThreadState::current()->registerPreFinalizer(this); | 
| -#endif | 
| -} | 
| - | 
| -void CanvasRenderingContext2D::unwindStateStack() | 
| -{ | 
| -    if (size_t stackSize = m_stateStack.size()) { | 
| -        if (SkCanvas* skCanvas = canvas()->existingDrawingCanvas()) { | 
| -            while (--stackSize) | 
| -                skCanvas->restore(); | 
| -        } | 
| -    } | 
| -} | 
| - | 
| -CanvasRenderingContext2D::~CanvasRenderingContext2D() | 
| +BaseRenderingContext2D::BaseRenderingContext2D() | 
| +    : m_clipAntialiasing(NotAntiAliased) | 
| { | 
| -    if (m_pruneLocalFontCacheScheduled) { | 
| -        Platform::current()->currentThread()->removeTaskObserver(this); | 
| -    } | 
| -#if !ENABLE(OILPAN) | 
| -    dispose(); | 
| -#endif | 
| -} | 
| - | 
| -void CanvasRenderingContext2D::dispose() | 
| -{ | 
| -    clearFilterReferences(); | 
| +    m_stateStack.append(CanvasRenderingContext2DState::create()); | 
| } | 
|  | 
| -void CanvasRenderingContext2D::validateStateStack() | 
| +BaseRenderingContext2D::~BaseRenderingContext2D() | 
| { | 
| -#if ENABLE(ASSERT) | 
| -    SkCanvas* skCanvas = canvas()->existingDrawingCanvas(); | 
| -    if (skCanvas && m_contextLostMode == NotLostContext) { | 
| -        ASSERT(static_cast<size_t>(skCanvas->getSaveCount()) == m_stateStack.size()); | 
| -    } | 
| -#endif | 
| } | 
|  | 
| -CanvasRenderingContext2DState& CanvasRenderingContext2D::modifiableState() | 
| +CanvasRenderingContext2DState& BaseRenderingContext2D::modifiableState() | 
| { | 
| realizeSaves(); | 
| return *m_stateStack.last(); | 
| } | 
|  | 
| -bool CanvasRenderingContext2D::isAccelerated() const | 
| -{ | 
| -    if (!canvas()->hasImageBuffer()) | 
| -        return false; | 
| -    return canvas()->buffer()->isAccelerated(); | 
| -} | 
| - | 
| -void CanvasRenderingContext2D::stop() | 
| -{ | 
| -    if (!isContextLost()) { | 
| -        // Never attempt to restore the context because the page is being torn down. | 
| -        loseContext(SyntheticLostContext); | 
| -    } | 
| -} | 
| - | 
| -bool CanvasRenderingContext2D::isContextLost() const | 
| -{ | 
| -    return m_contextLostMode != NotLostContext; | 
| -} | 
| - | 
| -void CanvasRenderingContext2D::loseContext(LostContextMode lostMode) | 
| -{ | 
| -    if (m_contextLostMode != NotLostContext) | 
| -        return; | 
| -    m_contextLostMode = lostMode; | 
| -    if (m_contextLostMode == SyntheticLostContext) { | 
| -        canvas()->discardImageBuffer(); | 
| -    } | 
| -    m_dispatchContextLostEventTimer.startOneShot(0, BLINK_FROM_HERE); | 
| -} | 
| - | 
| -void CanvasRenderingContext2D::didSetSurfaceSize() | 
| -{ | 
| -    if (!m_contextRestorable) | 
| -        return; | 
| -    // This code path is for restoring from an eviction | 
| -    // Restoring from surface failure is handled internally | 
| -    ASSERT(m_contextLostMode != NotLostContext && !canvas()->hasImageBuffer()); | 
| - | 
| -    if (canvas()->buffer()) { | 
| -        if (contextLostRestoredEventsEnabled()) { | 
| -            m_dispatchContextRestoredEventTimer.startOneShot(0, BLINK_FROM_HERE); | 
| -        } else { | 
| -            // legacy synchronous context restoration. | 
| -            reset(); | 
| -            m_contextLostMode = NotLostContext; | 
| -        } | 
| -    } | 
| -} | 
| - | 
| -DEFINE_TRACE(CanvasRenderingContext2D) | 
| -{ | 
| -    visitor->trace(m_stateStack); | 
| -    visitor->trace(m_hitRegionManager); | 
| -    CanvasRenderingContext::trace(visitor); | 
| -} | 
| - | 
| -void CanvasRenderingContext2D::dispatchContextLostEvent(Timer<CanvasRenderingContext2D>*) | 
| -{ | 
| -    if (contextLostRestoredEventsEnabled()) { | 
| -        RefPtrWillBeRawPtr<Event> event = Event::createCancelable(EventTypeNames::contextlost); | 
| -        canvas()->dispatchEvent(event); | 
| -        if (event->defaultPrevented()) { | 
| -            m_contextRestorable = false; | 
| -        } | 
| -    } | 
| - | 
| -    // If RealLostContext, it means the context was not lost due to surface failure | 
| -    // but rather due to a an eviction, which means image buffer exists. | 
| -    if (m_contextRestorable && m_contextLostMode == RealLostContext) { | 
| -        m_tryRestoreContextAttemptCount = 0; | 
| -        m_tryRestoreContextEventTimer.startRepeating(TryRestoreContextInterval, BLINK_FROM_HERE); | 
| -    } | 
| -} | 
| - | 
| -void CanvasRenderingContext2D::tryRestoreContextEvent(Timer<CanvasRenderingContext2D>* timer) | 
| -{ | 
| -    if (m_contextLostMode == NotLostContext) { | 
| -        // Canvas was already restored (possibly thanks to a resize), so stop trying. | 
| -        m_tryRestoreContextEventTimer.stop(); | 
| -        return; | 
| -    } | 
| - | 
| -    ASSERT(m_contextLostMode == RealLostContext); | 
| -    if (canvas()->hasImageBuffer() && canvas()->buffer()->restoreSurface()) { | 
| -        m_tryRestoreContextEventTimer.stop(); | 
| -        dispatchContextRestoredEvent(nullptr); | 
| -    } | 
| - | 
| -    if (++m_tryRestoreContextAttemptCount > MaxTryRestoreContextAttempts) { | 
| -        // final attempt: allocate a brand new image buffer instead of restoring | 
| -        canvas()->discardImageBuffer(); | 
| -        m_tryRestoreContextEventTimer.stop(); | 
| -        if (canvas()->buffer()) | 
| -            dispatchContextRestoredEvent(nullptr); | 
| -    } | 
| -} | 
| - | 
| -void CanvasRenderingContext2D::dispatchContextRestoredEvent(Timer<CanvasRenderingContext2D>*) | 
| -{ | 
| -    if (m_contextLostMode == NotLostContext) | 
| -        return; | 
| -    reset(); | 
| -    m_contextLostMode = NotLostContext; | 
| -    if (contextLostRestoredEventsEnabled()) { | 
| -        RefPtrWillBeRawPtr<Event> event(Event::create(EventTypeNames::contextrestored)); | 
| -        canvas()->dispatchEvent(event); | 
| -    } | 
| -} | 
| - | 
| -void CanvasRenderingContext2D::reset() | 
| -{ | 
| -    validateStateStack(); | 
| -    unwindStateStack(); | 
| -    m_stateStack.resize(1); | 
| -    m_stateStack.first() = CanvasRenderingContext2DState::create(); | 
| -    m_path.clear(); | 
| -    SkCanvas* c = canvas()->existingDrawingCanvas(); | 
| -    if (c) { | 
| -        c->resetMatrix(); | 
| -        c->clipRect(SkRect::MakeWH(canvas()->width(), canvas()->height()), SkRegion::kReplace_Op); | 
| -    } | 
| -    validateStateStack(); | 
| -} | 
| - | 
| -void CanvasRenderingContext2D::restoreCanvasMatrixClipStack(SkCanvas* c) const | 
| -{ | 
| -    if (!c) | 
| -        return; | 
| -    WillBeHeapVector<OwnPtrWillBeMember<CanvasRenderingContext2DState>>::const_iterator currState; | 
| -    ASSERT(m_stateStack.begin() < m_stateStack.end()); | 
| -    for (currState = m_stateStack.begin(); currState < m_stateStack.end(); currState++) { | 
| -        c->setMatrix(SkMatrix::I()); | 
| -        currState->get()->playbackClips(c); | 
| -        c->setMatrix(affineTransformToSkMatrix(currState->get()->transform())); | 
| -        c->save(); | 
| -    } | 
| -    c->restore(); | 
| -} | 
| - | 
| -void CanvasRenderingContext2D::realizeSaves() | 
| +void BaseRenderingContext2D::realizeSaves() | 
| { | 
| validateStateStack(); | 
| if (state().hasUnrealizedSaves()) { | 
| @@ -339,12 +65,12 @@ void CanvasRenderingContext2D::realizeSaves() | 
| } | 
| } | 
|  | 
| -void CanvasRenderingContext2D::save() | 
| +void BaseRenderingContext2D::save() | 
| { | 
| m_stateStack.last()->save(); | 
| } | 
|  | 
| -void CanvasRenderingContext2D::restore() | 
| +void BaseRenderingContext2D::restore() | 
| { | 
| validateStateStack(); | 
| if (state().hasUnrealizedSaves()) { | 
| @@ -379,12 +105,12 @@ static inline void convertCanvasStyleToUnionType(CanvasStyle* style, StringOrCan | 
| returnValue.setString(style->color()); | 
| } | 
|  | 
| -void CanvasRenderingContext2D::strokeStyle(StringOrCanvasGradientOrCanvasPattern& returnValue) const | 
| +void BaseRenderingContext2D::strokeStyle(StringOrCanvasGradientOrCanvasPattern& returnValue) const | 
| { | 
| convertCanvasStyleToUnionType(state().strokeStyle(), returnValue); | 
| } | 
|  | 
| -void CanvasRenderingContext2D::setStrokeStyle(const StringOrCanvasGradientOrCanvasPattern& style) | 
| +void BaseRenderingContext2D::setStrokeStyle(const StringOrCanvasGradientOrCanvasPattern& style) | 
| { | 
| ASSERT(!style.isNull()); | 
|  | 
| @@ -395,7 +121,7 @@ void CanvasRenderingContext2D::setStrokeStyle(const StringOrCanvasGradientOrCanv | 
| if (colorString == state().unparsedStrokeColor()) | 
| return; | 
| Color parsedColor = 0; | 
| -        if (!parseColorOrCurrentColor(parsedColor, colorString, canvas())) | 
| +        if (!parseColorOrCurrentColor(parsedColor, colorString)) | 
| return; | 
| if (state().strokeStyle()->isEquivalentRGBA(parsedColor.rgb())) { | 
| modifiableState().setUnparsedStrokeColor(colorString); | 
| @@ -407,8 +133,8 @@ void CanvasRenderingContext2D::setStrokeStyle(const StringOrCanvasGradientOrCanv | 
| } else if (style.isCanvasPattern()) { | 
| CanvasPattern* canvasPattern = style.getAsCanvasPattern(); | 
|  | 
| -        if (canvas()->originClean() && !canvasPattern->originClean()) | 
| -            canvas()->setOriginTainted(); | 
| +        if (originClean() && !canvasPattern->originClean()) | 
| +            setOriginTainted(); | 
|  | 
| canvasStyle = CanvasStyle::createFromPattern(canvasPattern); | 
| } | 
| @@ -420,12 +146,12 @@ void CanvasRenderingContext2D::setStrokeStyle(const StringOrCanvasGradientOrCanv | 
| modifiableState().clearResolvedFilter(); | 
| } | 
|  | 
| -void CanvasRenderingContext2D::fillStyle(StringOrCanvasGradientOrCanvasPattern& returnValue) const | 
| +void BaseRenderingContext2D::fillStyle(StringOrCanvasGradientOrCanvasPattern& returnValue) const | 
| { | 
| convertCanvasStyleToUnionType(state().fillStyle(), returnValue); | 
| } | 
|  | 
| -void CanvasRenderingContext2D::setFillStyle(const StringOrCanvasGradientOrCanvasPattern& style) | 
| +void BaseRenderingContext2D::setFillStyle(const StringOrCanvasGradientOrCanvasPattern& style) | 
| { | 
| ASSERT(!style.isNull()); | 
| validateStateStack(); | 
| @@ -436,7 +162,7 @@ void CanvasRenderingContext2D::setFillStyle(const StringOrCanvasGradientOrCanvas | 
| if (colorString == state().unparsedFillColor()) | 
| return; | 
| Color parsedColor = 0; | 
| -        if (!parseColorOrCurrentColor(parsedColor, colorString, canvas())) | 
| +        if (!parseColorOrCurrentColor(parsedColor, colorString)) | 
| return; | 
| if (state().fillStyle()->isEquivalentRGBA(parsedColor.rgb())) { | 
| modifiableState().setUnparsedFillColor(colorString); | 
| @@ -448,10 +174,10 @@ void CanvasRenderingContext2D::setFillStyle(const StringOrCanvasGradientOrCanvas | 
| } else if (style.isCanvasPattern()) { | 
| CanvasPattern* canvasPattern = style.getAsCanvasPattern(); | 
|  | 
| -        if (canvas()->originClean() && !canvasPattern->originClean()) | 
| -            canvas()->setOriginTainted(); | 
| +        if (originClean() && !canvasPattern->originClean()) | 
| +            setOriginTainted(); | 
| if (canvasPattern->pattern()->isTextureBacked()) | 
| -            canvas()->disableDeferral(DisableDeferralReasonUsingTextureBackedPattern); | 
| +            disableDeferral(DisableDeferralReasonUsingTextureBackedPattern); | 
| canvasStyle = CanvasStyle::createFromPattern(canvasPattern); | 
| } | 
|  | 
| @@ -461,12 +187,12 @@ void CanvasRenderingContext2D::setFillStyle(const StringOrCanvasGradientOrCanvas | 
| modifiableState().clearResolvedFilter(); | 
| } | 
|  | 
| -double CanvasRenderingContext2D::lineWidth() const | 
| +double BaseRenderingContext2D::lineWidth() const | 
| { | 
| return state().lineWidth(); | 
| } | 
|  | 
| -void CanvasRenderingContext2D::setLineWidth(double width) | 
| +void BaseRenderingContext2D::setLineWidth(double width) | 
| { | 
| if (!std::isfinite(width) || width <= 0) | 
| return; | 
| @@ -475,12 +201,12 @@ void CanvasRenderingContext2D::setLineWidth(double width) | 
| modifiableState().setLineWidth(width); | 
| } | 
|  | 
| -String CanvasRenderingContext2D::lineCap() const | 
| +String BaseRenderingContext2D::lineCap() const | 
| { | 
| return lineCapName(state().lineCap()); | 
| } | 
|  | 
| -void CanvasRenderingContext2D::setLineCap(const String& s) | 
| +void BaseRenderingContext2D::setLineCap(const String& s) | 
| { | 
| LineCap cap; | 
| if (!parseLineCap(s, cap)) | 
| @@ -490,12 +216,12 @@ void CanvasRenderingContext2D::setLineCap(const String& s) | 
| modifiableState().setLineCap(cap); | 
| } | 
|  | 
| -String CanvasRenderingContext2D::lineJoin() const | 
| +String BaseRenderingContext2D::lineJoin() const | 
| { | 
| return lineJoinName(state().lineJoin()); | 
| } | 
|  | 
| -void CanvasRenderingContext2D::setLineJoin(const String& s) | 
| +void BaseRenderingContext2D::setLineJoin(const String& s) | 
| { | 
| LineJoin join; | 
| if (!parseLineJoin(s, join)) | 
| @@ -505,12 +231,12 @@ void CanvasRenderingContext2D::setLineJoin(const String& s) | 
| modifiableState().setLineJoin(join); | 
| } | 
|  | 
| -double CanvasRenderingContext2D::miterLimit() const | 
| +double BaseRenderingContext2D::miterLimit() const | 
| { | 
| return state().miterLimit(); | 
| } | 
|  | 
| -void CanvasRenderingContext2D::setMiterLimit(double limit) | 
| +void BaseRenderingContext2D::setMiterLimit(double limit) | 
| { | 
| if (!std::isfinite(limit) || limit <= 0) | 
| return; | 
| @@ -519,12 +245,12 @@ void CanvasRenderingContext2D::setMiterLimit(double limit) | 
| modifiableState().setMiterLimit(limit); | 
| } | 
|  | 
| -double CanvasRenderingContext2D::shadowOffsetX() const | 
| +double BaseRenderingContext2D::shadowOffsetX() const | 
| { | 
| return state().shadowOffset().width(); | 
| } | 
|  | 
| -void CanvasRenderingContext2D::setShadowOffsetX(double x) | 
| +void BaseRenderingContext2D::setShadowOffsetX(double x) | 
| { | 
| if (!std::isfinite(x)) | 
| return; | 
| @@ -533,12 +259,12 @@ void CanvasRenderingContext2D::setShadowOffsetX(double x) | 
| modifiableState().setShadowOffsetX(x); | 
| } | 
|  | 
| -double CanvasRenderingContext2D::shadowOffsetY() const | 
| +double BaseRenderingContext2D::shadowOffsetY() const | 
| { | 
| return state().shadowOffset().height(); | 
| } | 
|  | 
| -void CanvasRenderingContext2D::setShadowOffsetY(double y) | 
| +void BaseRenderingContext2D::setShadowOffsetY(double y) | 
| { | 
| if (!std::isfinite(y)) | 
| return; | 
| @@ -547,12 +273,12 @@ void CanvasRenderingContext2D::setShadowOffsetY(double y) | 
| modifiableState().setShadowOffsetY(y); | 
| } | 
|  | 
| -double CanvasRenderingContext2D::shadowBlur() const | 
| +double BaseRenderingContext2D::shadowBlur() const | 
| { | 
| return state().shadowBlur(); | 
| } | 
|  | 
| -void CanvasRenderingContext2D::setShadowBlur(double blur) | 
| +void BaseRenderingContext2D::setShadowBlur(double blur) | 
| { | 
| if (!std::isfinite(blur) || blur < 0) | 
| return; | 
| @@ -561,22 +287,22 @@ void CanvasRenderingContext2D::setShadowBlur(double blur) | 
| modifiableState().setShadowBlur(blur); | 
| } | 
|  | 
| -String CanvasRenderingContext2D::shadowColor() const | 
| +String BaseRenderingContext2D::shadowColor() const | 
| { | 
| return Color(state().shadowColor()).serialized(); | 
| } | 
|  | 
| -void CanvasRenderingContext2D::setShadowColor(const String& colorString) | 
| +void BaseRenderingContext2D::setShadowColor(const String& colorString) | 
| { | 
| Color color; | 
| -    if (!parseColorOrCurrentColor(color, colorString, canvas())) | 
| +    if (!parseColorOrCurrentColor(color, colorString)) | 
| return; | 
| if (state().shadowColor() == color) | 
| return; | 
| modifiableState().setShadowColor(color.rgb()); | 
| } | 
|  | 
| -const Vector<double>& CanvasRenderingContext2D::getLineDash() const | 
| +const Vector<double>& BaseRenderingContext2D::getLineDash() const | 
| { | 
| return state().lineDash(); | 
| } | 
| @@ -590,31 +316,31 @@ static bool lineDashSequenceIsValid(const Vector<double>& dash) | 
| return true; | 
| } | 
|  | 
| -void CanvasRenderingContext2D::setLineDash(const Vector<double>& dash) | 
| +void BaseRenderingContext2D::setLineDash(const Vector<double>& dash) | 
| { | 
| if (!lineDashSequenceIsValid(dash)) | 
| return; | 
| modifiableState().setLineDash(dash); | 
| } | 
|  | 
| -double CanvasRenderingContext2D::lineDashOffset() const | 
| +double BaseRenderingContext2D::lineDashOffset() const | 
| { | 
| return state().lineDashOffset(); | 
| } | 
|  | 
| -void CanvasRenderingContext2D::setLineDashOffset(double offset) | 
| +void BaseRenderingContext2D::setLineDashOffset(double offset) | 
| { | 
| if (!std::isfinite(offset) || state().lineDashOffset() == offset) | 
| return; | 
| modifiableState().setLineDashOffset(offset); | 
| } | 
|  | 
| -double CanvasRenderingContext2D::globalAlpha() const | 
| +double BaseRenderingContext2D::globalAlpha() const | 
| { | 
| return state().globalAlpha(); | 
| } | 
|  | 
| -void CanvasRenderingContext2D::setGlobalAlpha(double alpha) | 
| +void BaseRenderingContext2D::setGlobalAlpha(double alpha) | 
| { | 
| if (!(alpha >= 0 && alpha <= 1)) | 
| return; | 
| @@ -623,22 +349,12 @@ void CanvasRenderingContext2D::setGlobalAlpha(double alpha) | 
| modifiableState().setGlobalAlpha(alpha); | 
| } | 
|  | 
| -bool CanvasRenderingContext2D::shouldAntialias() const | 
| -{ | 
| -    return state().shouldAntialias(); | 
| -} | 
| - | 
| -void CanvasRenderingContext2D::setShouldAntialias(bool doAA) | 
| -{ | 
| -    modifiableState().setShouldAntialias(doAA); | 
| -} | 
| - | 
| -String CanvasRenderingContext2D::globalCompositeOperation() const | 
| +String BaseRenderingContext2D::globalCompositeOperation() const | 
| { | 
| return compositeOperatorName(compositeOperatorFromSkia(state().globalComposite()), blendModeFromSkia(state().globalComposite())); | 
| } | 
|  | 
| -void CanvasRenderingContext2D::setGlobalCompositeOperation(const String& operation) | 
| +void BaseRenderingContext2D::setGlobalCompositeOperation(const String& operation) | 
| { | 
| CompositeOperator op = CompositeSourceOver; | 
| WebBlendMode blendMode = WebBlendModeNormal; | 
| @@ -650,12 +366,12 @@ void CanvasRenderingContext2D::setGlobalCompositeOperation(const String& operati | 
| modifiableState().setGlobalComposite(xfermode); | 
| } | 
|  | 
| -String CanvasRenderingContext2D::filter() const | 
| +String BaseRenderingContext2D::filter() const | 
| { | 
| return state().unparsedFilter(); | 
| } | 
|  | 
| -void CanvasRenderingContext2D::setFilter(const String& filterString) | 
| +void BaseRenderingContext2D::setFilter(const String& filterString) | 
| { | 
| if (filterString == state().unparsedFilter()) | 
| return; | 
| @@ -669,19 +385,19 @@ void CanvasRenderingContext2D::setFilter(const String& filterString) | 
| modifiableState().setFilter(filterValue.release()); | 
| } | 
|  | 
| -PassRefPtrWillBeRawPtr<SVGMatrixTearOff> CanvasRenderingContext2D::currentTransform() const | 
| +PassRefPtrWillBeRawPtr<SVGMatrixTearOff> BaseRenderingContext2D::currentTransform() const | 
| { | 
| return SVGMatrixTearOff::create(state().transform()); | 
| } | 
|  | 
| -void CanvasRenderingContext2D::setCurrentTransform(PassRefPtrWillBeRawPtr<SVGMatrixTearOff> passMatrixTearOff) | 
| +void BaseRenderingContext2D::setCurrentTransform(PassRefPtrWillBeRawPtr<SVGMatrixTearOff> passMatrixTearOff) | 
| { | 
| RefPtrWillBeRawPtr<SVGMatrixTearOff> matrixTearOff = passMatrixTearOff; | 
| const AffineTransform& transform = matrixTearOff->value(); | 
| setTransform(transform.a(), transform.b(), transform.c(), transform.d(), transform.e(), transform.f()); | 
| } | 
|  | 
| -void CanvasRenderingContext2D::scale(double sx, double sy) | 
| +void BaseRenderingContext2D::scale(double sx, double sy) | 
| { | 
| SkCanvas* c = drawingCanvas(); | 
| if (!c) | 
| @@ -703,7 +419,7 @@ void CanvasRenderingContext2D::scale(double sx, double sy) | 
| m_path.transform(AffineTransform().scaleNonUniform(1.0 / sx, 1.0 / sy)); | 
| } | 
|  | 
| -void CanvasRenderingContext2D::rotate(double angleInRadians) | 
| +void BaseRenderingContext2D::rotate(double angleInRadians) | 
| { | 
| SkCanvas* c = drawingCanvas(); | 
| if (!c) | 
| @@ -724,7 +440,7 @@ void CanvasRenderingContext2D::rotate(double angleInRadians) | 
| m_path.transform(AffineTransform().rotateRadians(-angleInRadians)); | 
| } | 
|  | 
| -void CanvasRenderingContext2D::translate(double tx, double ty) | 
| +void BaseRenderingContext2D::translate(double tx, double ty) | 
| { | 
| SkCanvas* c = drawingCanvas(); | 
| if (!c) | 
| @@ -747,7 +463,7 @@ void CanvasRenderingContext2D::translate(double tx, double ty) | 
| m_path.transform(AffineTransform().translate(-tx, -ty)); | 
| } | 
|  | 
| -void CanvasRenderingContext2D::transform(double m11, double m12, double m21, double m22, double dx, double dy) | 
| +void BaseRenderingContext2D::transform(double m11, double m12, double m21, double m22, double dx, double dy) | 
| { | 
| SkCanvas* c = drawingCanvas(); | 
| if (!c) | 
| @@ -769,7 +485,7 @@ void CanvasRenderingContext2D::transform(double m11, double m12, double m21, dou | 
| m_path.transform(transform.inverse()); | 
| } | 
|  | 
| -void CanvasRenderingContext2D::resetTransform() | 
| +void BaseRenderingContext2D::resetTransform() | 
| { | 
| SkCanvas* c = drawingCanvas(); | 
| if (!c) | 
| @@ -784,7 +500,7 @@ void CanvasRenderingContext2D::resetTransform() | 
|  | 
| // resetTransform() resolves the non-invertible CTM state. | 
| modifiableState().resetTransform(); | 
| -    c->setMatrix(affineTransformToSkMatrix(canvas()->baseTransform())); | 
| +    c->setMatrix(affineTransformToSkMatrix(baseTransform())); | 
|  | 
| if (invertibleCTM) | 
| m_path.transform(ctm); | 
| @@ -792,7 +508,7 @@ void CanvasRenderingContext2D::resetTransform() | 
| // It means that resetTransform() restores m_path just before CTM became non-invertible. | 
| } | 
|  | 
| -void CanvasRenderingContext2D::setTransform(double m11, double m12, double m21, double m22, double dx, double dy) | 
| +void BaseRenderingContext2D::setTransform(double m11, double m12, double m21, double m22, double dx, double dy) | 
| { | 
| SkCanvas* c = drawingCanvas(); | 
| if (!c) | 
| @@ -805,7 +521,7 @@ void CanvasRenderingContext2D::setTransform(double m11, double m12, double m21, | 
| transform(m11, m12, m21, m22, dx, dy); | 
| } | 
|  | 
| -void CanvasRenderingContext2D::beginPath() | 
| +void BaseRenderingContext2D::beginPath() | 
| { | 
| m_path.clear(); | 
| } | 
| @@ -831,7 +547,7 @@ static bool validateRectForCanvas(double& x, double& y, double& width, double& h | 
| return true; | 
| } | 
|  | 
| -static bool isFullCanvasCompositeMode(SkXfermode::Mode op) | 
| +bool BaseRenderingContext2D::isFullCanvasCompositeMode(SkXfermode::Mode op) | 
| { | 
| // See 4.8.11.1.3 Compositing | 
| // CompositeSourceAtop and CompositeDestinationOut are not listed here as the platforms already | 
| @@ -839,90 +555,6 @@ static bool isFullCanvasCompositeMode(SkXfermode::Mode op) | 
| return op == SkXfermode::kSrcIn_Mode || op == SkXfermode::kSrcOut_Mode || op == SkXfermode::kDstIn_Mode || op == SkXfermode::kDstATop_Mode; | 
| } | 
|  | 
| -template<typename DrawFunc> | 
| -void CanvasRenderingContext2D::compositedDraw(const DrawFunc& drawFunc, SkCanvas* c, CanvasRenderingContext2DState::PaintType paintType, CanvasRenderingContext2DState::ImageType imageType) | 
| -{ | 
| -    SkImageFilter* filter = state().getFilter(canvas(), accessFont(), canvas()->size(), this); | 
| -    ASSERT(isFullCanvasCompositeMode(state().globalComposite()) || filter); | 
| -    SkMatrix ctm = c->getTotalMatrix(); | 
| -    c->resetMatrix(); | 
| -    SkPaint compositePaint; | 
| -    compositePaint.setXfermodeMode(state().globalComposite()); | 
| -    if (state().shouldDrawShadows()) { | 
| -        // unroll into two independently composited passes if drawing shadows | 
| -        SkPaint shadowPaint = *state().getPaint(paintType, DrawShadowOnly, imageType); | 
| -        int saveCount = c->getSaveCount(); | 
| -        if (filter) { | 
| -            SkPaint filterPaint; | 
| -            filterPaint.setImageFilter(filter); | 
| -            // TODO(junov): crbug.com/502921 We could use primitive bounds if we knew that the filter | 
| -            // does not affect transparent black regions. | 
| -            c->saveLayer(nullptr, &shadowPaint); | 
| -            c->saveLayer(nullptr, &filterPaint); | 
| -            SkPaint foregroundPaint = *state().getPaint(paintType, DrawForegroundOnly, imageType); | 
| -            c->setMatrix(ctm); | 
| -            drawFunc(c, &foregroundPaint); | 
| -        } else { | 
| -            ASSERT(isFullCanvasCompositeMode(state().globalComposite())); | 
| -            c->saveLayer(nullptr, &compositePaint); | 
| -            shadowPaint.setXfermodeMode(SkXfermode::kSrcOver_Mode); | 
| -            c->setMatrix(ctm); | 
| -            drawFunc(c, &shadowPaint); | 
| -        } | 
| -        c->restoreToCount(saveCount); | 
| -    } | 
| - | 
| -    compositePaint.setImageFilter(filter); | 
| -    // TODO(junov): crbug.com/502921 We could use primitive bounds if we knew that the filter | 
| -    // does not affect transparent black regions *and* !isFullCanvasCompositeMode | 
| -    c->saveLayer(nullptr, &compositePaint); | 
| -    SkPaint foregroundPaint = *state().getPaint(paintType, DrawForegroundOnly, imageType); | 
| -    foregroundPaint.setXfermodeMode(SkXfermode::kSrcOver_Mode); | 
| -    c->setMatrix(ctm); | 
| -    drawFunc(c, &foregroundPaint); | 
| -    c->restore(); | 
| -    c->setMatrix(ctm); | 
| -} | 
| - | 
| -template<typename DrawFunc, typename ContainsFunc> | 
| -bool CanvasRenderingContext2D::draw(const DrawFunc& drawFunc, const ContainsFunc& drawCoversClipBounds, const SkRect& bounds, CanvasRenderingContext2DState::PaintType paintType, CanvasRenderingContext2DState::ImageType imageType) | 
| -{ | 
| -    if (!state().isTransformInvertible()) | 
| -        return false; | 
| - | 
| -    SkIRect clipBounds; | 
| -    if (!drawingCanvas() || !drawingCanvas()->getClipDeviceBounds(&clipBounds)) | 
| -        return false; | 
| - | 
| -    // If gradient size is zero, then paint nothing. | 
| -    CanvasStyle* style = state().style(paintType); | 
| -    if (style) { | 
| -        CanvasGradient* gradient = style->canvasGradient(); | 
| -        if (gradient && gradient->gradient()->isZeroSize()) | 
| -            return false; | 
| -    } | 
| - | 
| -    if (isFullCanvasCompositeMode(state().globalComposite()) || state().hasFilter(canvas(), accessFont(), canvas()->size(), this)) { | 
| -        compositedDraw(drawFunc, drawingCanvas(), paintType, imageType); | 
| -        didDraw(clipBounds); | 
| -    } else if (state().globalComposite() == SkXfermode::kSrc_Mode) { | 
| -        clearCanvas(); // takes care of checkOverdraw() | 
| -        const SkPaint* paint = state().getPaint(paintType, DrawForegroundOnly, imageType); | 
| -        drawFunc(drawingCanvas(), paint); | 
| -        didDraw(clipBounds); | 
| -    } else { | 
| -        SkIRect dirtyRect; | 
| -        if (computeDirtyRect(bounds, clipBounds, &dirtyRect)) { | 
| -            const SkPaint* paint = state().getPaint(paintType, DrawShadowAndForeground, imageType); | 
| -            if (paintType != CanvasRenderingContext2DState::StrokePaintType && drawCoversClipBounds(clipBounds)) | 
| -                checkOverdraw(bounds, paint, imageType, ClipFill); | 
| -            drawFunc(drawingCanvas(), paint); | 
| -            didDraw(dirtyRect); | 
| -        } | 
| -    } | 
| -    return true; | 
| -} | 
| - | 
| static bool isPathExpensive(const Path& path) | 
| { | 
| const SkPath& skPath = path.skPath(); | 
| @@ -935,7 +567,7 @@ static bool isPathExpensive(const Path& path) | 
| return false; | 
| } | 
|  | 
| -void CanvasRenderingContext2D::drawPathInternal(const Path& path, CanvasRenderingContext2DState::PaintType paintType, SkPath::FillType fillType) | 
| +void BaseRenderingContext2D::drawPathInternal(const Path& path, CanvasRenderingContext2DState::PaintType paintType, SkPath::FillType fillType) | 
| { | 
| if (path.isEmpty()) | 
| return; | 
| @@ -960,7 +592,7 @@ void CanvasRenderingContext2D::drawPathInternal(const Path& path, CanvasRenderin | 
| return false; | 
| }, bounds, paintType)) { | 
| if (isPathExpensive(path)) { | 
| -            ImageBuffer* buffer = canvas()->buffer(); | 
| +            ImageBuffer* buffer = imageBuffer(); | 
| if (buffer) | 
| buffer->setHasExpensiveOp(); | 
| } | 
| @@ -978,27 +610,27 @@ static SkPath::FillType parseWinding(const String& windingRuleString) | 
| return SkPath::kEvenOdd_FillType; | 
| } | 
|  | 
| -void CanvasRenderingContext2D::fill(const String& windingRuleString) | 
| +void BaseRenderingContext2D::fill(const String& windingRuleString) | 
| { | 
| drawPathInternal(m_path, CanvasRenderingContext2DState::FillPaintType, parseWinding(windingRuleString)); | 
| } | 
|  | 
| -void CanvasRenderingContext2D::fill(Path2D* domPath, const String& windingRuleString) | 
| +void BaseRenderingContext2D::fill(Path2D* domPath, const String& windingRuleString) | 
| { | 
| drawPathInternal(domPath->path(), CanvasRenderingContext2DState::FillPaintType, parseWinding(windingRuleString)); | 
| } | 
|  | 
| -void CanvasRenderingContext2D::stroke() | 
| +void BaseRenderingContext2D::stroke() | 
| { | 
| drawPathInternal(m_path, CanvasRenderingContext2DState::StrokePaintType); | 
| } | 
|  | 
| -void CanvasRenderingContext2D::stroke(Path2D* domPath) | 
| +void BaseRenderingContext2D::stroke(Path2D* domPath) | 
| { | 
| drawPathInternal(domPath->path(), CanvasRenderingContext2DState::StrokePaintType); | 
| } | 
|  | 
| -void CanvasRenderingContext2D::fillRect(double x, double y, double width, double height) | 
| +void BaseRenderingContext2D::fillRect(double x, double y, double width, double height) | 
| { | 
| if (!validateRectForCanvas(x, y, width, height)) | 
| return; | 
| @@ -1033,7 +665,7 @@ static void strokeRectOnCanvas(const FloatRect& rect, SkCanvas* canvas, const Sk | 
| canvas->drawRect(rect, *paint); | 
| } | 
|  | 
| -void CanvasRenderingContext2D::strokeRect(double x, double y, double width, double height) | 
| +void BaseRenderingContext2D::strokeRect(double x, double y, double width, double height) | 
| { | 
| if (!validateRectForCanvas(x, y, width, height)) | 
| return; | 
| @@ -1055,7 +687,7 @@ void CanvasRenderingContext2D::strokeRect(double x, double y, double width, doub | 
| }, bounds, CanvasRenderingContext2DState::StrokePaintType); | 
| } | 
|  | 
| -void CanvasRenderingContext2D::clipInternal(const Path& path, const String& windingRuleString) | 
| +void BaseRenderingContext2D::clipInternal(const Path& path, const String& windingRuleString) | 
| { | 
| SkCanvas* c = drawingCanvas(); | 
| if (!c) { | 
| @@ -1069,32 +701,32 @@ void CanvasRenderingContext2D::clipInternal(const Path& path, const String& wind | 
| skPath.setFillType(parseWinding(windingRuleString)); | 
| modifiableState().clipPath(skPath, m_clipAntialiasing); | 
| c->clipPath(skPath, SkRegion::kIntersect_Op, m_clipAntialiasing == AntiAliased); | 
| -    if (ExpensiveCanvasHeuristicParameters::ComplexClipsAreExpensive && !skPath.isRect(0) && canvas()->hasImageBuffer()) { | 
| -        canvas()->buffer()->setHasExpensiveOp(); | 
| +    if (ExpensiveCanvasHeuristicParameters::ComplexClipsAreExpensive && !skPath.isRect(0) && hasImageBuffer()) { | 
| +        imageBuffer()->setHasExpensiveOp(); | 
| } | 
| } | 
|  | 
| -void CanvasRenderingContext2D::clip(const String& windingRuleString) | 
| +void BaseRenderingContext2D::clip(const String& windingRuleString) | 
| { | 
| clipInternal(m_path, windingRuleString); | 
| } | 
|  | 
| -void CanvasRenderingContext2D::clip(Path2D* domPath, const String& windingRuleString) | 
| +void BaseRenderingContext2D::clip(Path2D* domPath, const String& windingRuleString) | 
| { | 
| clipInternal(domPath->path(), windingRuleString); | 
| } | 
|  | 
| -bool CanvasRenderingContext2D::isPointInPath(const double x, const double y, const String& windingRuleString) | 
| +bool BaseRenderingContext2D::isPointInPath(const double x, const double y, const String& windingRuleString) | 
| { | 
| return isPointInPathInternal(m_path, x, y, windingRuleString); | 
| } | 
|  | 
| -bool CanvasRenderingContext2D::isPointInPath(Path2D* domPath, const double x, const double y, const String& windingRuleString) | 
| +bool BaseRenderingContext2D::isPointInPath(Path2D* domPath, const double x, const double y, const String& windingRuleString) | 
| { | 
| return isPointInPathInternal(domPath->path(), x, y, windingRuleString); | 
| } | 
|  | 
| -bool CanvasRenderingContext2D::isPointInPathInternal(const Path& path, const double x, const double y, const String& windingRuleString) | 
| +bool BaseRenderingContext2D::isPointInPathInternal(const Path& path, const double x, const double y, const String& windingRuleString) | 
| { | 
| SkCanvas* c = drawingCanvas(); | 
| if (!c) | 
| @@ -1111,17 +743,17 @@ bool CanvasRenderingContext2D::isPointInPathInternal(const Path& path, const dou | 
| return path.contains(transformedPoint, SkFillTypeToWindRule(parseWinding(windingRuleString))); | 
| } | 
|  | 
| -bool CanvasRenderingContext2D::isPointInStroke(const double x, const double y) | 
| +bool BaseRenderingContext2D::isPointInStroke(const double x, const double y) | 
| { | 
| return isPointInStrokeInternal(m_path, x, y); | 
| } | 
|  | 
| -bool CanvasRenderingContext2D::isPointInStroke(Path2D* domPath, const double x, const double y) | 
| +bool BaseRenderingContext2D::isPointInStroke(Path2D* domPath, const double x, const double y) | 
| { | 
| return isPointInStrokeInternal(domPath->path(), x, y); | 
| } | 
|  | 
| -bool CanvasRenderingContext2D::isPointInStrokeInternal(const Path& path, const double x, const double y) | 
| +bool BaseRenderingContext2D::isPointInStrokeInternal(const Path& path, const double x, const double y) | 
| { | 
| SkCanvas* c = drawingCanvas(); | 
| if (!c) | 
| @@ -1146,46 +778,7 @@ bool CanvasRenderingContext2D::isPointInStrokeInternal(const Path& path, const d | 
| return path.strokeContains(transformedPoint, strokeData); | 
| } | 
|  | 
| -void CanvasRenderingContext2D::scrollPathIntoView() | 
| -{ | 
| -    scrollPathIntoViewInternal(m_path); | 
| -} | 
| - | 
| -void CanvasRenderingContext2D::scrollPathIntoView(Path2D* path2d) | 
| -{ | 
| -    scrollPathIntoViewInternal(path2d->path()); | 
| -} | 
| - | 
| -void CanvasRenderingContext2D::scrollPathIntoViewInternal(const Path& path) | 
| -{ | 
| -    if (!state().isTransformInvertible() || path.isEmpty()) | 
| -        return; | 
| - | 
| -    canvas()->document().updateLayoutIgnorePendingStylesheets(); | 
| - | 
| -    LayoutObject* renderer = canvas()->layoutObject(); | 
| -    LayoutBox* layoutBox = canvas()->layoutBox(); | 
| -    if (!renderer || !layoutBox) | 
| -        return; | 
| - | 
| -    // Apply transformation and get the bounding rect | 
| -    Path transformedPath = path; | 
| -    transformedPath.transform(state().transform()); | 
| -    FloatRect boundingRect = transformedPath.boundingRect(); | 
| - | 
| -    // Offset by the canvas rect | 
| -    LayoutRect pathRect(boundingRect); | 
| -    IntRect canvasRect = layoutBox->absoluteContentBox(); | 
| -    pathRect.moveBy(canvasRect.location()); | 
| - | 
| -    renderer->scrollRectToVisible( | 
| -        pathRect, ScrollAlignment::alignCenterAlways, ScrollAlignment::alignTopAlways); | 
| - | 
| -    // TODO: should implement "inform the user" that the caret and/or | 
| -    // selection the specified rectangle of the canvas. See http://crbug.com/357987 | 
| -} | 
| - | 
| -void CanvasRenderingContext2D::clearRect(double x, double y, double width, double height) | 
| +void BaseRenderingContext2D::clearRect(double x, double y, double width, double height) | 
| { | 
| if (!validateRectForCanvas(x, y, width, height)) | 
| return; | 
| @@ -1217,10 +810,6 @@ void CanvasRenderingContext2D::clearRect(double x, double y, double width, doubl | 
| didDraw(dirtyRect); | 
| } | 
| } | 
| - | 
| -    if (m_hitRegionManager) { | 
| -        m_hitRegionManager->removeHitRegionsInRect(rect, state().transform()); | 
| -    } | 
| } | 
|  | 
| static inline FloatRect normalizeRect(const FloatRect& rect) | 
| @@ -1264,7 +853,7 @@ static inline CanvasImageSource* toImageSourceInternal(const CanvasImageSourceUn | 
| return nullptr; | 
| } | 
|  | 
| -void CanvasRenderingContext2D::drawImage(const CanvasImageSourceUnion& imageSource, double x, double y, ExceptionState& exceptionState) | 
| +void BaseRenderingContext2D::drawImage(const CanvasImageSourceUnion& imageSource, double x, double y, ExceptionState& exceptionState) | 
| { | 
| CanvasImageSource* imageSourceInternal = toImageSourceInternal(imageSource); | 
| FloatSize sourceRectSize = imageSourceInternal->elementSize(); | 
| @@ -1272,7 +861,7 @@ void CanvasRenderingContext2D::drawImage(const CanvasImageSourceUnion& imageSour | 
| drawImage(imageSourceInternal, 0, 0, sourceRectSize.width(), sourceRectSize.height(), x, y, destRectSize.width(), destRectSize.height(), exceptionState); | 
| } | 
|  | 
| -void CanvasRenderingContext2D::drawImage(const CanvasImageSourceUnion& imageSource, | 
| +void BaseRenderingContext2D::drawImage(const CanvasImageSourceUnion& imageSource, | 
| double x, double y, double width, double height, ExceptionState& exceptionState) | 
| { | 
| CanvasImageSource* imageSourceInternal = toImageSourceInternal(imageSource); | 
| @@ -1280,7 +869,7 @@ void CanvasRenderingContext2D::drawImage(const CanvasImageSourceUnion& imageSour | 
| drawImage(imageSourceInternal, 0, 0, sourceRectSize.width(), sourceRectSize.height(), x, y, width, height, exceptionState); | 
| } | 
|  | 
| -void CanvasRenderingContext2D::drawImage(const CanvasImageSourceUnion& imageSource, | 
| +void BaseRenderingContext2D::drawImage(const CanvasImageSourceUnion& imageSource, | 
| double sx, double sy, double sw, double sh, | 
| double dx, double dy, double dw, double dh, ExceptionState& exceptionState) | 
| { | 
| @@ -1288,9 +877,9 @@ void CanvasRenderingContext2D::drawImage(const CanvasImageSourceUnion& imageSour | 
| drawImage(imageSourceInternal, sx, sy, sw, sh, dx, dy, dw, dh, exceptionState); | 
| } | 
|  | 
| -bool CanvasRenderingContext2D::shouldDrawImageAntialiased(const FloatRect& destRect) const | 
| +bool BaseRenderingContext2D::shouldDrawImageAntialiased(const FloatRect& destRect) const | 
| { | 
| -    if (!shouldAntialias()) | 
| +    if (!state().shouldAntialias()) | 
| return false; | 
| SkCanvas* c = drawingCanvas(); | 
| ASSERT(c); | 
| @@ -1315,7 +904,7 @@ bool CanvasRenderingContext2D::shouldDrawImageAntialiased(const FloatRect& destR | 
| return destRect.width() * fabs(widthExpansion) < 1 || destRect.height() * fabs(heightExpansion) < 1; | 
| } | 
|  | 
| -void CanvasRenderingContext2D::drawImageInternal(SkCanvas* c, CanvasImageSource* imageSource, Image* image, const FloatRect& srcRect, const FloatRect& dstRect, const SkPaint* paint) | 
| +void BaseRenderingContext2D::drawImageInternal(SkCanvas* c, CanvasImageSource* imageSource, Image* image, const FloatRect& srcRect, const FloatRect& dstRect, const SkPaint* paint) | 
| { | 
| int initialSaveCount = c->getSaveCount(); | 
| SkPaint imagePaint = *paint; | 
| @@ -1374,7 +963,7 @@ bool shouldDisableDeferral(CanvasImageSource* imageSource, DisableDeferralReason | 
| return false; | 
| } | 
|  | 
| -void CanvasRenderingContext2D::drawImage(CanvasImageSource* imageSource, | 
| +void BaseRenderingContext2D::drawImage(CanvasImageSource* imageSource, | 
| double sx, double sy, double sw, double sh, | 
| double dx, double dy, double dw, double dh, ExceptionState& exceptionState) | 
| { | 
| @@ -1384,7 +973,7 @@ void CanvasRenderingContext2D::drawImage(CanvasImageSource* imageSource, | 
| RefPtr<Image> image; | 
| SourceImageStatus sourceImageStatus = InvalidSourceImageStatus; | 
| if (!imageSource->isVideoElement()) { | 
| -        AccelerationHint hint = canvas()->buffer()->isAccelerated() ? PreferAcceleration : PreferNoAcceleration; | 
| +        AccelerationHint hint = imageBuffer()->isAccelerated() ? PreferAcceleration : PreferNoAcceleration; | 
| image = imageSource->getSourceImageForCanvas(&sourceImageStatus, hint, SnapshotReasonDrawImage); | 
| if (sourceImageStatus == UndecodableSourceImageStatus) | 
| exceptionState.throwDOMException(InvalidStateError, "The HTMLImageElement provided is in the 'broken' state."); | 
| @@ -1412,7 +1001,7 @@ void CanvasRenderingContext2D::drawImage(CanvasImageSource* imageSource, | 
|  | 
| DisableDeferralReason reason = DisableDeferralReasonUnknown; | 
| if (shouldDisableDeferral(imageSource, &reason) || image->isTextureBacked()) | 
| -        canvas()->disableDeferral(reason); | 
| +        disableDeferral(reason); | 
|  | 
| validateStateStack(); | 
|  | 
| @@ -1434,11 +1023,11 @@ void CanvasRenderingContext2D::drawImage(CanvasImageSource* imageSource, | 
| if (ExpensiveCanvasHeuristicParameters::SVGImageSourcesAreExpensive && imageSource->isSVGSource()) | 
| isExpensive = true; | 
|  | 
| -    if (imageSource->elementSize().width() * imageSource->elementSize().height() > canvas()->width() * canvas()->height() * ExpensiveCanvasHeuristicParameters::ExpensiveImageSizeRatio) | 
| +    if (imageSource->elementSize().width() * imageSource->elementSize().height() > width() * height() * ExpensiveCanvasHeuristicParameters::ExpensiveImageSizeRatio) | 
| isExpensive = true; | 
|  | 
| if (isExpensive) { | 
| -        ImageBuffer* buffer = canvas()->buffer(); | 
| +        ImageBuffer* buffer = imageBuffer(); | 
| if (buffer) | 
| buffer->setHasExpensiveOp(); | 
| } | 
| @@ -1446,36 +1035,36 @@ void CanvasRenderingContext2D::drawImage(CanvasImageSource* imageSource, | 
| if (imageSource->isCanvasElement() && static_cast<HTMLCanvasElement*>(imageSource)->is3D()) { | 
| // WebGL to 2D canvas: must flush graphics context to prevent a race | 
| // FIXME: crbug.com/516331 Fix the underlying synchronization issue so this flush can be eliminated. | 
| -        canvas()->buffer()->flushGpu(FlushReasonDrawImageOfWebGL); | 
| +        imageBuffer()->flushGpu(FlushReasonDrawImageOfWebGL); | 
| } | 
|  | 
| -    if (canvas()->originClean() && wouldTaintOrigin(imageSource)) | 
| -        canvas()->setOriginTainted(); | 
| +    if (originClean() && wouldTaintOrigin(imageSource)) | 
| +        setOriginTainted(); | 
| } | 
|  | 
| -void CanvasRenderingContext2D::clearCanvas() | 
| +void BaseRenderingContext2D::clearCanvas() | 
| { | 
| -    FloatRect canvasRect(0, 0, canvas()->width(), canvas()->height()); | 
| +    FloatRect canvasRect(0, 0, width(), height()); | 
| checkOverdraw(canvasRect, 0, CanvasRenderingContext2DState::NoImage, ClipFill); | 
| SkCanvas* c = drawingCanvas(); | 
| if (c) | 
| -        c->clear(m_hasAlpha ? SK_ColorTRANSPARENT : SK_ColorBLACK); | 
| +        c->clear(hasAlpha() ? SK_ColorTRANSPARENT : SK_ColorBLACK); | 
| } | 
|  | 
| -bool CanvasRenderingContext2D::rectContainsTransformedRect(const FloatRect& rect, const SkIRect& transformedRect) const | 
| +bool BaseRenderingContext2D::rectContainsTransformedRect(const FloatRect& rect, const SkIRect& transformedRect) const | 
| { | 
| FloatQuad quad(rect); | 
| FloatQuad transformedQuad(FloatRect(transformedRect.x(), transformedRect.y(), transformedRect.width(), transformedRect.height())); | 
| return state().transform().mapQuad(quad).containsQuad(transformedQuad); | 
| } | 
|  | 
| -CanvasGradient* CanvasRenderingContext2D::createLinearGradient(double x0, double y0, double x1, double y1) | 
| +CanvasGradient* BaseRenderingContext2D::createLinearGradient(double x0, double y0, double x1, double y1) | 
| { | 
| CanvasGradient* gradient = CanvasGradient::create(FloatPoint(x0, y0), FloatPoint(x1, y1)); | 
| return gradient; | 
| } | 
|  | 
| -CanvasGradient* CanvasRenderingContext2D::createRadialGradient(double x0, double y0, double r0, double x1, double y1, double r1, ExceptionState& exceptionState) | 
| +CanvasGradient* BaseRenderingContext2D::createRadialGradient(double x0, double y0, double r0, double x1, double y1, double r1, ExceptionState& exceptionState) | 
| { | 
| if (r0 < 0 || r1 < 0) { | 
| exceptionState.throwDOMException(IndexSizeError, String::format("The %s provided is less than 0.", r0 < 0 ? "r0" : "r1")); | 
| @@ -1486,7 +1075,7 @@ CanvasGradient* CanvasRenderingContext2D::createRadialGradient(double x0, double | 
| return gradient; | 
| } | 
|  | 
| -CanvasPattern* CanvasRenderingContext2D::createPattern(const CanvasImageSourceUnion& imageSource, const String& repetitionType, ExceptionState& exceptionState) | 
| +CanvasPattern* BaseRenderingContext2D::createPattern(const CanvasImageSourceUnion& imageSource, const String& repetitionType, ExceptionState& exceptionState) | 
| { | 
| Pattern::RepeatMode repeatMode = CanvasPattern::parseRepetitionType(repetitionType, exceptionState); | 
| if (exceptionState.hadException()) | 
| @@ -1521,7 +1110,7 @@ CanvasPattern* CanvasRenderingContext2D::createPattern(const CanvasImageSourceUn | 
| return CanvasPattern::create(imageForRendering.release(), repeatMode, originClean); | 
| } | 
|  | 
| -bool CanvasRenderingContext2D::computeDirtyRect(const FloatRect& localRect, SkIRect* dirtyRect) | 
| +bool BaseRenderingContext2D::computeDirtyRect(const FloatRect& localRect, SkIRect* dirtyRect) | 
| { | 
| SkIRect clipBounds; | 
| if (!drawingCanvas()->getClipDeviceBounds(&clipBounds)) | 
| @@ -1529,7 +1118,7 @@ bool CanvasRenderingContext2D::computeDirtyRect(const FloatRect& localRect, SkIR | 
| return computeDirtyRect(localRect, clipBounds, dirtyRect); | 
| } | 
|  | 
| -bool CanvasRenderingContext2D::computeDirtyRect(const FloatRect& localRect, const SkIRect& transformedClipBounds, SkIRect* dirtyRect) | 
| +bool BaseRenderingContext2D::computeDirtyRect(const FloatRect& localRect, const SkIRect& transformedClipBounds, SkIRect* dirtyRect) | 
| { | 
| FloatRect canvasRect = state().transform().mapRect(localRect); | 
|  | 
| @@ -1551,33 +1140,12 @@ bool CanvasRenderingContext2D::computeDirtyRect(const FloatRect& localRect, cons | 
| return true; | 
| } | 
|  | 
| -void CanvasRenderingContext2D::didDraw(const SkIRect& dirtyRect) | 
| -{ | 
| -    if (dirtyRect.isEmpty()) | 
| -        return; | 
| - | 
| -    if (ExpensiveCanvasHeuristicParameters::BlurredShadowsAreExpensive && state().shouldDrawShadows() && state().shadowBlur() > 0) { | 
| -        ImageBuffer* buffer = canvas()->buffer(); | 
| -        if (buffer) | 
| -            buffer->setHasExpensiveOp(); | 
| -    } | 
| - | 
| -    canvas()->didDraw(SkRect::Make(dirtyRect)); | 
| -} | 
| - | 
| -SkCanvas* CanvasRenderingContext2D::drawingCanvas() const | 
| -{ | 
| -    if (isContextLost()) | 
| -        return nullptr; | 
| -    return canvas()->drawingCanvas(); | 
| -} | 
| - | 
| -ImageData* CanvasRenderingContext2D::createImageData(ImageData* imageData) const | 
| +ImageData* BaseRenderingContext2D::createImageData(ImageData* imageData) const | 
| { | 
| return ImageData::create(imageData->size()); | 
| } | 
|  | 
| -ImageData* CanvasRenderingContext2D::createImageData(double sw, double sh, ExceptionState& exceptionState) const | 
| +ImageData* BaseRenderingContext2D::createImageData(double sw, double sh, ExceptionState& exceptionState) const | 
| { | 
| if (!sw || !sh) { | 
| exceptionState.throwDOMException(IndexSizeError, String::format("The source %s is 0.", sw ? "height" : "width")); | 
| @@ -1597,9 +1165,9 @@ ImageData* CanvasRenderingContext2D::createImageData(double sw, double sh, Excep | 
| return ImageData::create(size); | 
| } | 
|  | 
| -ImageData* CanvasRenderingContext2D::getImageData(double sx, double sy, double sw, double sh, ExceptionState& exceptionState) const | 
| +ImageData* BaseRenderingContext2D::getImageData(double sx, double sy, double sw, double sh, ExceptionState& exceptionState) const | 
| { | 
| -    if (!canvas()->originClean()) | 
| +    if (!originClean()) | 
| exceptionState.throwSecurityError("The canvas has been tainted by cross-origin data."); | 
| else if (!sw || !sh) | 
| exceptionState.throwDOMException(IndexSizeError, String::format("The source %s is 0.", sw ? "height" : "width")); | 
| @@ -1625,7 +1193,7 @@ ImageData* CanvasRenderingContext2D::getImageData(double sx, double sy, double s | 
| return nullptr; | 
|  | 
| IntRect imageDataRect = enclosingIntRect(logicalRect); | 
| -    ImageBuffer* buffer = canvas()->buffer(); | 
| +    ImageBuffer* buffer = imageBuffer(); | 
| if (!buffer || isContextLost()) | 
| return ImageData::create(imageDataRect.size()); | 
|  | 
| @@ -1639,18 +1207,18 @@ ImageData* CanvasRenderingContext2D::getImageData(double sx, double sy, double s | 
| DOMUint8ClampedArray::create(arrayBuffer, 0, arrayBuffer->byteLength())); | 
| } | 
|  | 
| -void CanvasRenderingContext2D::putImageData(ImageData* data, double dx, double dy, ExceptionState& exceptionState) | 
| +void BaseRenderingContext2D::putImageData(ImageData* data, double dx, double dy, ExceptionState& exceptionState) | 
| { | 
| putImageData(data, dx, dy, 0, 0, data->width(), data->height(), exceptionState); | 
| } | 
|  | 
| -void CanvasRenderingContext2D::putImageData(ImageData* data, double dx, double dy, double dirtyX, double dirtyY, double dirtyWidth, double dirtyHeight, ExceptionState& exceptionState) | 
| +void BaseRenderingContext2D::putImageData(ImageData* data, double dx, double dy, double dirtyX, double dirtyY, double dirtyWidth, double dirtyHeight, ExceptionState& exceptionState) | 
| { | 
| if (data->data()->bufferBase()->isNeutered()) { | 
| exceptionState.throwDOMException(InvalidStateError, "The source data has been neutered."); | 
| return; | 
| } | 
| -    ImageBuffer* buffer = canvas()->buffer(); | 
| +    ImageBuffer* buffer = imageBuffer(); | 
| if (!buffer) | 
| return; | 
|  | 
| @@ -1682,383 +1250,7 @@ void CanvasRenderingContext2D::putImageData(ImageData* data, double dx, double d | 
| didDraw(destRect); | 
| } | 
|  | 
| -String CanvasRenderingContext2D::font() const | 
| -{ | 
| -    if (!state().hasRealizedFont()) | 
| -        return defaultFont; | 
| - | 
| -    canvas()->document().canvasFontCache()->willUseCurrentFont(); | 
| -    StringBuilder serializedFont; | 
| -    const FontDescription& fontDescription = state().font().fontDescription(); | 
| - | 
| -    if (fontDescription.style() == FontStyleItalic) | 
| -        serializedFont.appendLiteral("italic "); | 
| -    if (fontDescription.weight() == FontWeightBold) | 
| -        serializedFont.appendLiteral("bold "); | 
| -    if (fontDescription.variant() == FontVariantSmallCaps) | 
| -        serializedFont.appendLiteral("small-caps "); | 
| - | 
| -    serializedFont.appendNumber(fontDescription.computedPixelSize()); | 
| -    serializedFont.appendLiteral("px"); | 
| - | 
| -    const FontFamily& firstFontFamily = fontDescription.family(); | 
| -    for (const FontFamily* fontFamily = &firstFontFamily; fontFamily; fontFamily = fontFamily->next()) { | 
| -        if (fontFamily != &firstFontFamily) | 
| -            serializedFont.append(','); | 
| - | 
| -        // FIXME: We should append family directly to serializedFont rather than building a temporary string. | 
| -        String family = fontFamily->family(); | 
| -        if (family.startsWith("-webkit-")) | 
| -            family = family.substring(8); | 
| -        if (family.contains(' ')) | 
| -            family = "\"" + family + "\""; | 
| - | 
| -        serializedFont.append(' '); | 
| -        serializedFont.append(family); | 
| -    } | 
| - | 
| -    return serializedFont.toString(); | 
| -} | 
| - | 
| -void CanvasRenderingContext2D::setFont(const String& newFont) | 
| -{ | 
| -    // The style resolution required for rendering text is not available in frame-less documents. | 
| -    if (!canvas()->document().frame()) | 
| -        return; | 
| - | 
| -    canvas()->document().updateLayoutTreeForNodeIfNeeded(canvas()); | 
| - | 
| -    // The following early exit is dependent on the cache not being empty | 
| -    // because an empty cache may indicate that a style change has occured | 
| -    // which would require that the font be re-resolved. This check has to | 
| -    // come after the layout tree update to flush pending style changes. | 
| -    if (newFont == state().unparsedFont() && state().hasRealizedFont() && m_fontsResolvedUsingCurrentStyle.size() > 0) | 
| -        return; | 
| - | 
| -    CanvasFontCache* canvasFontCache = canvas()->document().canvasFontCache(); | 
| - | 
| -    // Map the <canvas> font into the text style. If the font uses keywords like larger/smaller, these will work | 
| -    // relative to the canvas. | 
| -    RefPtr<ComputedStyle> fontStyle; | 
| -    const ComputedStyle* computedStyle = canvas()->ensureComputedStyle(); | 
| -    if (computedStyle) { | 
| -        HashMap<String, Font>::iterator i = m_fontsResolvedUsingCurrentStyle.find(newFont); | 
| -        if (i != m_fontsResolvedUsingCurrentStyle.end()) { | 
| -            ASSERT(m_fontLRUList.contains(newFont)); | 
| -            m_fontLRUList.remove(newFont); | 
| -            m_fontLRUList.add(newFont); | 
| -            modifiableState().setFont(i->value, canvas()->document().styleEngine().fontSelector()); | 
| -        } else { | 
| -            MutableStylePropertySet* parsedStyle = canvasFontCache->parseFont(newFont); | 
| -            if (!parsedStyle) | 
| -                return; | 
| -            fontStyle = ComputedStyle::create(); | 
| -            FontDescription elementFontDescription(computedStyle->fontDescription()); | 
| -            // Reset the computed size to avoid inheriting the zoom factor from the <canvas> element. | 
| -            elementFontDescription.setComputedSize(elementFontDescription.specifiedSize()); | 
| -            fontStyle->setFontDescription(elementFontDescription); | 
| -            fontStyle->font().update(fontStyle->font().fontSelector()); | 
| -            canvas()->document().ensureStyleResolver().computeFont(fontStyle.get(), *parsedStyle); | 
| -            m_fontsResolvedUsingCurrentStyle.add(newFont, fontStyle->font()); | 
| -            ASSERT(!m_fontLRUList.contains(newFont)); | 
| -            m_fontLRUList.add(newFont); | 
| -            pruneLocalFontCache(canvasFontCache->hardMaxFonts()); // hard limit | 
| -            schedulePruneLocalFontCacheIfNeeded(); // soft limit | 
| -            modifiableState().setFont(fontStyle->font(), canvas()->document().styleEngine().fontSelector()); | 
| -        } | 
| -    } else { | 
| -        Font resolvedFont; | 
| -        if (!canvasFontCache->getFontUsingDefaultStyle(newFont, resolvedFont)) | 
| -            return; | 
| -        modifiableState().setFont(resolvedFont, canvas()->document().styleEngine().fontSelector()); | 
| -    } | 
| - | 
| -    // The parse succeeded. | 
| -    String newFontSafeCopy(newFont); // Create a string copy since newFont can be deleted inside realizeSaves. | 
| -    modifiableState().setUnparsedFont(newFontSafeCopy); | 
| -} | 
| - | 
| -void CanvasRenderingContext2D::schedulePruneLocalFontCacheIfNeeded() | 
| -{ | 
| -    if (m_pruneLocalFontCacheScheduled) | 
| -        return; | 
| -    m_pruneLocalFontCacheScheduled = true; | 
| -    Platform::current()->currentThread()->addTaskObserver(this); | 
| -} | 
| - | 
| -void CanvasRenderingContext2D::didProcessTask() | 
| -{ | 
| -    // The rendering surface needs to be prepared now because it will be too late | 
| -    // to create a layer once we are in the paint invalidation phase. | 
| -    canvas()->prepareSurfaceForPaintingIfNeeded(); | 
| - | 
| -    pruneLocalFontCache(canvas()->document().canvasFontCache()->maxFonts()); | 
| -    m_pruneLocalFontCacheScheduled = false; | 
| -    Platform::current()->currentThread()->removeTaskObserver(this); | 
| -} | 
| - | 
| -void CanvasRenderingContext2D::pruneLocalFontCache(size_t targetSize) | 
| -{ | 
| -    if (targetSize == 0) { | 
| -        // Short cut: LRU does not matter when evicting everything | 
| -        m_fontLRUList.clear(); | 
| -        m_fontsResolvedUsingCurrentStyle.clear(); | 
| -        return; | 
| -    } | 
| -    while (m_fontLRUList.size() > targetSize) { | 
| -        m_fontsResolvedUsingCurrentStyle.remove(m_fontLRUList.first()); | 
| -        m_fontLRUList.removeFirst(); | 
| -    } | 
| -} | 
| - | 
| -void CanvasRenderingContext2D::styleDidChange(const ComputedStyle* oldStyle, const ComputedStyle& newStyle) | 
| -{ | 
| -    if (oldStyle && oldStyle->font() == newStyle.font()) | 
| -        return; | 
| -    pruneLocalFontCache(0); | 
| -} | 
| - | 
| -void CanvasRenderingContext2D::filterNeedsInvalidation() | 
| -{ | 
| -    state().clearResolvedFilter(); | 
| -} | 
| - | 
| -String CanvasRenderingContext2D::textAlign() const | 
| -{ | 
| -    return textAlignName(state().textAlign()); | 
| -} | 
| - | 
| -void CanvasRenderingContext2D::setTextAlign(const String& s) | 
| -{ | 
| -    TextAlign align; | 
| -    if (!parseTextAlign(s, align)) | 
| -        return; | 
| -    if (state().textAlign() == align) | 
| -        return; | 
| -    modifiableState().setTextAlign(align); | 
| -} | 
| - | 
| -String CanvasRenderingContext2D::textBaseline() const | 
| -{ | 
| -    return textBaselineName(state().textBaseline()); | 
| -} | 
| - | 
| -void CanvasRenderingContext2D::setTextBaseline(const String& s) | 
| -{ | 
| -    TextBaseline baseline; | 
| -    if (!parseTextBaseline(s, baseline)) | 
| -        return; | 
| -    if (state().textBaseline() == baseline) | 
| -        return; | 
| -    modifiableState().setTextBaseline(baseline); | 
| -} | 
| - | 
| -static inline TextDirection toTextDirection(CanvasRenderingContext2DState::Direction direction, HTMLCanvasElement* canvas, const ComputedStyle** computedStyle = 0) | 
| -{ | 
| -    const ComputedStyle* style = (computedStyle || direction == CanvasRenderingContext2DState::DirectionInherit) ? canvas->ensureComputedStyle() : nullptr; | 
| -    if (computedStyle) | 
| -        *computedStyle = style; | 
| -    switch (direction) { | 
| -    case CanvasRenderingContext2DState::DirectionInherit: | 
| -        return style ? style->direction() : LTR; | 
| -    case CanvasRenderingContext2DState::DirectionRTL: | 
| -        return RTL; | 
| -    case CanvasRenderingContext2DState::DirectionLTR: | 
| -        return LTR; | 
| -    } | 
| -    ASSERT_NOT_REACHED(); | 
| -    return LTR; | 
| -} | 
| - | 
| -String CanvasRenderingContext2D::direction() const | 
| -{ | 
| -    if (state().direction() == CanvasRenderingContext2DState::DirectionInherit) | 
| -        canvas()->document().updateLayoutTreeForNodeIfNeeded(canvas()); | 
| -    return toTextDirection(state().direction(), canvas()) == RTL ? rtl : ltr; | 
| -} | 
| - | 
| -void CanvasRenderingContext2D::setDirection(const String& directionString) | 
| -{ | 
| -    CanvasRenderingContext2DState::Direction direction; | 
| -    if (directionString == inherit) | 
| -        direction = CanvasRenderingContext2DState::DirectionInherit; | 
| -    else if (directionString == rtl) | 
| -        direction = CanvasRenderingContext2DState::DirectionRTL; | 
| -    else if (directionString == ltr) | 
| -        direction = CanvasRenderingContext2DState::DirectionLTR; | 
| -    else | 
| -        return; | 
| - | 
| -    if (state().direction() == direction) | 
| -        return; | 
| - | 
| -    modifiableState().setDirection(direction); | 
| -} | 
| - | 
| -void CanvasRenderingContext2D::fillText(const String& text, double x, double y) | 
| -{ | 
| -    drawTextInternal(text, x, y, CanvasRenderingContext2DState::FillPaintType); | 
| -} | 
| - | 
| -void CanvasRenderingContext2D::fillText(const String& text, double x, double y, double maxWidth) | 
| -{ | 
| -    drawTextInternal(text, x, y, CanvasRenderingContext2DState::FillPaintType, &maxWidth); | 
| -} | 
| - | 
| -void CanvasRenderingContext2D::strokeText(const String& text, double x, double y) | 
| -{ | 
| -    drawTextInternal(text, x, y, CanvasRenderingContext2DState::StrokePaintType); | 
| -} | 
| - | 
| -void CanvasRenderingContext2D::strokeText(const String& text, double x, double y, double maxWidth) | 
| -{ | 
| -    drawTextInternal(text, x, y, CanvasRenderingContext2DState::StrokePaintType, &maxWidth); | 
| -} | 
| - | 
| -TextMetrics* CanvasRenderingContext2D::measureText(const String& text) | 
| -{ | 
| -    TextMetrics* metrics = TextMetrics::create(); | 
| - | 
| -    // The style resolution required for rendering text is not available in frame-less documents. | 
| -    if (!canvas()->document().frame()) | 
| -        return metrics; | 
| - | 
| -    canvas()->document().updateLayoutTreeForNodeIfNeeded(canvas()); | 
| -    const Font& font = accessFont(); | 
| - | 
| -    TextDirection direction; | 
| -    if (state().direction() == CanvasRenderingContext2DState::DirectionInherit) | 
| -        direction = determineDirectionality(text); | 
| -    else | 
| -        direction = toTextDirection(state().direction(), canvas()); | 
| -    TextRun textRun(text, 0, 0, TextRun::AllowTrailingExpansion | TextRun::ForbidLeadingExpansion, direction, false); | 
| -    textRun.setNormalizeSpace(true); | 
| -    FloatRect textBounds = font.selectionRectForText(textRun, FloatPoint(), font.fontDescription().computedSize(), 0, -1, true); | 
| - | 
| -    // x direction | 
| -    metrics->setWidth(font.width(textRun)); | 
| -    metrics->setActualBoundingBoxLeft(-textBounds.x()); | 
| -    metrics->setActualBoundingBoxRight(textBounds.maxX()); | 
| - | 
| -    // y direction | 
| -    const FontMetrics& fontMetrics = font.fontMetrics(); | 
| -    const float ascent = fontMetrics.floatAscent(); | 
| -    const float descent = fontMetrics.floatDescent(); | 
| -    const float baselineY = getFontBaseline(fontMetrics); | 
| - | 
| -    metrics->setFontBoundingBoxAscent(ascent - baselineY); | 
| -    metrics->setFontBoundingBoxDescent(descent + baselineY); | 
| -    metrics->setActualBoundingBoxAscent(-textBounds.y() - baselineY); | 
| -    metrics->setActualBoundingBoxDescent(textBounds.maxY() + baselineY); | 
| - | 
| -    // Note : top/bottom and ascend/descend are currently the same, so there's no difference | 
| -    //        between the EM box's top and bottom and the font's ascend and descend | 
| -    metrics->setEmHeightAscent(0); | 
| -    metrics->setEmHeightDescent(0); | 
| - | 
| -    metrics->setHangingBaseline(-0.8f * ascent + baselineY); | 
| -    metrics->setAlphabeticBaseline(baselineY); | 
| -    metrics->setIdeographicBaseline(descent + baselineY); | 
| -    return metrics; | 
| -} | 
| - | 
| -void CanvasRenderingContext2D::drawTextInternal(const String& text, double x, double y, CanvasRenderingContext2DState::PaintType paintType, double* maxWidth) | 
| -{ | 
| -    // The style resolution required for rendering text is not available in frame-less documents. | 
| -    if (!canvas()->document().frame()) | 
| -        return; | 
| - | 
| -    // accessFont needs the style to be up to date, but updating style can cause script to run, | 
| -    // (e.g. due to autofocus) which can free the canvas (set size to 0, for example), so update | 
| -    // style before grabbing the drawingCanvas. | 
| -    canvas()->document().updateLayoutTreeForNodeIfNeeded(canvas()); | 
| - | 
| -    SkCanvas* c = drawingCanvas(); | 
| -    if (!c) | 
| -        return; | 
| - | 
| -    if (!std::isfinite(x) || !std::isfinite(y)) | 
| -        return; | 
| -    if (maxWidth && (!std::isfinite(*maxWidth) || *maxWidth <= 0)) | 
| -        return; | 
| - | 
| -    // Currently, SkPictureImageFilter does not support subpixel text anti-aliasing, which | 
| -    // is expected when !m_hasAlpha, so we need to fall out of display list mode when | 
| -    // drawing text to an opaque canvas | 
| -    // crbug.com/583809 | 
| -    if (!m_hasAlpha && !isAccelerated()) | 
| -        canvas()->disableDeferral(DisableDeferralReasonSubPixelTextAntiAliasingSupport); | 
| - | 
| -    const Font& font = accessFont(); | 
| -    if (!font.primaryFont()) | 
| -        return; | 
| - | 
| -    const FontMetrics& fontMetrics = font.fontMetrics(); | 
| - | 
| -    // FIXME: Need to turn off font smoothing. | 
| - | 
| -    const ComputedStyle* computedStyle = 0; | 
| -    TextDirection direction = toTextDirection(state().direction(), canvas(), &computedStyle); | 
| -    bool isRTL = direction == RTL; | 
| -    bool override = computedStyle ? isOverride(computedStyle->unicodeBidi()) : false; | 
| - | 
| -    TextRun textRun(text, 0, 0, TextRun::AllowTrailingExpansion, direction, override); | 
| -    textRun.setNormalizeSpace(true); | 
| -    // Draw the item text at the correct point. | 
| -    FloatPoint location(x, y + getFontBaseline(fontMetrics)); | 
| -    double fontWidth = font.width(textRun); | 
| - | 
| -    bool useMaxWidth = (maxWidth && *maxWidth < fontWidth); | 
| -    double width = useMaxWidth ? *maxWidth : fontWidth; | 
| - | 
| -    TextAlign align = state().textAlign(); | 
| -    if (align == StartTextAlign) | 
| -        align = isRTL ? RightTextAlign : LeftTextAlign; | 
| -    else if (align == EndTextAlign) | 
| -        align = isRTL ? LeftTextAlign : RightTextAlign; | 
| - | 
| -    switch (align) { | 
| -    case CenterTextAlign: | 
| -        location.setX(location.x() - width / 2); | 
| -        break; | 
| -    case RightTextAlign: | 
| -        location.setX(location.x() - width); | 
| -        break; | 
| -    default: | 
| -        break; | 
| -    } | 
| - | 
| -    // The slop built in to this mask rect matches the heuristic used in FontCGWin.cpp for GDI text. | 
| -    TextRunPaintInfo textRunPaintInfo(textRun); | 
| -    textRunPaintInfo.bounds = FloatRect(location.x() - fontMetrics.height() / 2, | 
| -        location.y() - fontMetrics.ascent() - fontMetrics.lineGap(), | 
| -        width + fontMetrics.height(), | 
| -        fontMetrics.lineSpacing()); | 
| -    if (paintType == CanvasRenderingContext2DState::StrokePaintType) | 
| -        inflateStrokeRect(textRunPaintInfo.bounds); | 
| - | 
| -    CanvasRenderingContext2DAutoRestoreSkCanvas stateRestorer(this); | 
| -    if (useMaxWidth) { | 
| -        drawingCanvas()->save(); | 
| -        drawingCanvas()->translate(location.x(), location.y()); | 
| -        // We draw when fontWidth is 0 so compositing operations (eg, a "copy" op) still work. | 
| -        drawingCanvas()->scale((fontWidth > 0 ? (width / fontWidth) : 0), 1); | 
| -        location = FloatPoint(); | 
| -    } | 
| - | 
| -    draw( | 
| -        [&font, this, &textRunPaintInfo, &location](SkCanvas* c, const SkPaint* paint) // draw lambda | 
| -        { | 
| -            font.drawBidiText(c, textRunPaintInfo, location, Font::UseFallbackIfFontNotReady, cDeviceScaleFactor, *paint); | 
| -        }, | 
| -        [](const SkIRect& rect) // overdraw test lambda | 
| -        { | 
| -            return false; | 
| -        }, | 
| -        textRunPaintInfo.bounds, paintType); | 
| -} | 
| - | 
| -void CanvasRenderingContext2D::inflateStrokeRect(FloatRect& rect) const | 
| +void BaseRenderingContext2D::inflateStrokeRect(FloatRect& rect) const | 
| { | 
| // Fast approximation of the stroke's bounding rect. | 
| // This yields a slightly oversized rect but is very fast | 
| @@ -2073,61 +1265,12 @@ void CanvasRenderingContext2D::inflateStrokeRect(FloatRect& rect) const | 
| rect.inflate(delta); | 
| } | 
|  | 
| -const Font& CanvasRenderingContext2D::accessFont() | 
| -{ | 
| -    if (!state().hasRealizedFont()) | 
| -        setFont(state().unparsedFont()); | 
| -    canvas()->document().canvasFontCache()->willUseCurrentFont(); | 
| -    return state().font(); | 
| -} | 
| - | 
| -int CanvasRenderingContext2D::getFontBaseline(const FontMetrics& fontMetrics) const | 
| -{ | 
| -    switch (state().textBaseline()) { | 
| -    case TopTextBaseline: | 
| -        return fontMetrics.ascent(); | 
| -    case HangingTextBaseline: | 
| -        // According to http://wiki.apache.org/xmlgraphics-fop/LineLayout/AlignmentHandling | 
| -        // "FOP (Formatting Objects Processor) puts the hanging baseline at 80% of the ascender height" | 
| -        return (fontMetrics.ascent() * 4) / 5; | 
| -    case BottomTextBaseline: | 
| -    case IdeographicTextBaseline: | 
| -        return -fontMetrics.descent(); | 
| -    case MiddleTextBaseline: | 
| -        return -fontMetrics.descent() + fontMetrics.height() / 2; | 
| -    case AlphabeticTextBaseline: | 
| -    default: | 
| -        // Do nothing. | 
| -        break; | 
| -    } | 
| -    return 0; | 
| -} | 
| - | 
| -void CanvasRenderingContext2D::setIsHidden(bool hidden) | 
| -{ | 
| -    if (canvas()->hasImageBuffer()) | 
| -        canvas()->buffer()->setIsHidden(hidden); | 
| -    if (hidden) { | 
| -        pruneLocalFontCache(0); | 
| -    } | 
| -} | 
| - | 
| -bool CanvasRenderingContext2D::isTransformInvertible() const | 
| -{ | 
| -    return state().isTransformInvertible(); | 
| -} | 
| - | 
| -WebLayer* CanvasRenderingContext2D::platformLayer() const | 
| -{ | 
| -    return canvas()->buffer() ? canvas()->buffer()->platformLayer() : 0; | 
| -} | 
| - | 
| -bool CanvasRenderingContext2D::imageSmoothingEnabled() const | 
| +bool BaseRenderingContext2D::imageSmoothingEnabled() const | 
| { | 
| return state().imageSmoothingEnabled(); | 
| } | 
|  | 
| -void CanvasRenderingContext2D::setImageSmoothingEnabled(bool enabled) | 
| +void BaseRenderingContext2D::setImageSmoothingEnabled(bool enabled) | 
| { | 
| if (enabled == state().imageSmoothingEnabled()) | 
| return; | 
| @@ -2135,12 +1278,12 @@ void CanvasRenderingContext2D::setImageSmoothingEnabled(bool enabled) | 
| modifiableState().setImageSmoothingEnabled(enabled); | 
| } | 
|  | 
| -String CanvasRenderingContext2D::imageSmoothingQuality() const | 
| +String BaseRenderingContext2D::imageSmoothingQuality() const | 
| { | 
| return state().imageSmoothingQuality(); | 
| } | 
|  | 
| -void CanvasRenderingContext2D::setImageSmoothingQuality(const String& quality) | 
| +void BaseRenderingContext2D::setImageSmoothingQuality(const String& quality) | 
| { | 
| if (quality == state().imageSmoothingQuality()) | 
| return; | 
| @@ -2148,169 +1291,10 @@ void CanvasRenderingContext2D::setImageSmoothingQuality(const String& quality) | 
| modifiableState().setImageSmoothingQuality(quality); | 
| } | 
|  | 
| -void CanvasRenderingContext2D::getContextAttributes(Canvas2DContextAttributes& attrs) const | 
| -{ | 
| -    attrs.setAlpha(m_hasAlpha); | 
| -} | 
| - | 
| -void CanvasRenderingContext2D::drawFocusIfNeeded(Element* element) | 
| -{ | 
| -    drawFocusIfNeededInternal(m_path, element); | 
| -} | 
| - | 
| -void CanvasRenderingContext2D::drawFocusIfNeeded(Path2D* path2d, Element* element) | 
| -{ | 
| -    drawFocusIfNeededInternal(path2d->path(), element); | 
| -} | 
| - | 
| -void CanvasRenderingContext2D::drawFocusIfNeededInternal(const Path& path, Element* element) | 
| -{ | 
| -    if (!focusRingCallIsValid(path, element)) | 
| -        return; | 
| - | 
| -    // Note: we need to check document->focusedElement() rather than just calling | 
| -    // element->focused(), because element->focused() isn't updated until after | 
| -    // focus events fire. | 
| -    if (element->document().focusedElement() == element) { | 
| -        scrollPathIntoViewInternal(path); | 
| -        drawFocusRing(path); | 
| -    } | 
| - | 
| -    // Update its accessible bounds whether it's focused or not. | 
| -    updateElementAccessibility(path, element); | 
| -} | 
| - | 
| -bool CanvasRenderingContext2D::focusRingCallIsValid(const Path& path, Element* element) | 
| -{ | 
| -    ASSERT(element); | 
| -    if (!state().isTransformInvertible()) | 
| -        return false; | 
| -    if (path.isEmpty()) | 
| -        return false; | 
| -    if (!element->isDescendantOf(canvas())) | 
| -        return false; | 
| - | 
| -    return true; | 
| -} | 
| - | 
| -void CanvasRenderingContext2D::drawFocusRing(const Path& path) | 
| -{ | 
| -    if (!drawingCanvas()) | 
| -        return; | 
| - | 
| -    SkColor color = LayoutTheme::theme().focusRingColor().rgb(); | 
| -    const int focusRingWidth = 5; | 
| - | 
| -    drawPlatformFocusRing(path.skPath(), drawingCanvas(), color, focusRingWidth); | 
| - | 
| -    // We need to add focusRingWidth to dirtyRect. | 
| -    StrokeData strokeData; | 
| -    strokeData.setThickness(focusRingWidth); | 
| - | 
| -    SkIRect dirtyRect; | 
| -    if (!computeDirtyRect(path.strokeBoundingRect(strokeData), &dirtyRect)) | 
| -        return; | 
| - | 
| -    didDraw(dirtyRect); | 
| -} | 
| - | 
| -void CanvasRenderingContext2D::updateElementAccessibility(const Path& path, Element* element) | 
| -{ | 
| -    element->document().updateLayoutIgnorePendingStylesheets(); | 
| -    AXObjectCache* axObjectCache = element->document().existingAXObjectCache(); | 
| -    LayoutBoxModelObject* lbmo = canvas()->layoutBoxModelObject(); | 
| -    LayoutObject* renderer = canvas()->layoutObject(); | 
| -    if (!axObjectCache || !lbmo || !renderer) | 
| -        return; | 
| - | 
| -    // Get the transformed path. | 
| -    Path transformedPath = path; | 
| -    transformedPath.transform(state().transform()); | 
| - | 
| -    // Offset by the canvas rect, taking border and padding into account. | 
| -    IntRect canvasRect = renderer->absoluteBoundingBoxRect(); | 
| -    canvasRect.move(lbmo->borderLeft() + lbmo->paddingLeft(), lbmo->borderTop() + lbmo->paddingTop()); | 
| -    LayoutRect elementRect = enclosingLayoutRect(transformedPath.boundingRect()); | 
| -    elementRect.moveBy(canvasRect.location()); | 
| -    axObjectCache->setCanvasObjectBounds(element, elementRect); | 
| -} | 
| - | 
| -void CanvasRenderingContext2D::addHitRegion(const HitRegionOptions& options, ExceptionState& exceptionState) | 
| -{ | 
| -    if (options.id().isEmpty() && !options.control()) { | 
| -        exceptionState.throwDOMException(NotSupportedError, "Both id and control are null."); | 
| -        return; | 
| -    } | 
| - | 
| -    if (options.control() && !canvas()->isSupportedInteractiveCanvasFallback(*options.control())) { | 
| -        exceptionState.throwDOMException(NotSupportedError, "The control is neither null nor a supported interactive canvas fallback element."); | 
| -        return; | 
| -    } | 
| - | 
| -    Path hitRegionPath = options.hasPath() ? options.path()->path() : m_path; | 
| - | 
| -    SkCanvas* c = drawingCanvas(); | 
| - | 
| -    if (hitRegionPath.isEmpty() || !c || !state().isTransformInvertible() | 
| -        || !c->getClipDeviceBounds(0)) { | 
| -        exceptionState.throwDOMException(NotSupportedError, "The specified path has no pixels."); | 
| -        return; | 
| -    } | 
| - | 
| -    hitRegionPath.transform(state().transform()); | 
| - | 
| -    if (state().hasClip()) { | 
| -        hitRegionPath.intersectPath(state().getCurrentClipPath()); | 
| -        if (hitRegionPath.isEmpty()) | 
| -            exceptionState.throwDOMException(NotSupportedError, "The specified path has no pixels."); | 
| -    } | 
| - | 
| -    if (!m_hitRegionManager) | 
| -        m_hitRegionManager = HitRegionManager::create(); | 
| - | 
| -    // Remove previous region (with id or control) | 
| -    m_hitRegionManager->removeHitRegionById(options.id()); | 
| -    m_hitRegionManager->removeHitRegionByControl(options.control().get()); | 
| - | 
| -    RefPtrWillBeRawPtr<HitRegion> hitRegion = HitRegion::create(hitRegionPath, options); | 
| -    Element* element = hitRegion->control(); | 
| -    if (element && element->isDescendantOf(canvas())) | 
| -        updateElementAccessibility(hitRegion->path(), hitRegion->control()); | 
| -    m_hitRegionManager->addHitRegion(hitRegion.release()); | 
| -} | 
| - | 
| -void CanvasRenderingContext2D::removeHitRegion(const String& id) | 
| -{ | 
| -    if (m_hitRegionManager) | 
| -        m_hitRegionManager->removeHitRegionById(id); | 
| -} | 
| - | 
| -void CanvasRenderingContext2D::clearHitRegions() | 
| -{ | 
| -    if (m_hitRegionManager) | 
| -        m_hitRegionManager->removeAllHitRegions(); | 
| -} | 
| - | 
| -HitRegion* CanvasRenderingContext2D::hitRegionAtPoint(const FloatPoint& point) | 
| -{ | 
| -    if (m_hitRegionManager) | 
| -        return m_hitRegionManager->getHitRegionAtPoint(point); | 
| - | 
| -    return nullptr; | 
| -} | 
| - | 
| -unsigned CanvasRenderingContext2D::hitRegionsCount() const | 
| -{ | 
| -    if (m_hitRegionManager) | 
| -        return m_hitRegionManager->getHitRegionsCount(); | 
| - | 
| -    return 0; | 
| -} | 
| - | 
| -void CanvasRenderingContext2D::checkOverdraw(const SkRect& rect, const SkPaint* paint, CanvasRenderingContext2DState::ImageType imageType, DrawType drawType) | 
| +void BaseRenderingContext2D::checkOverdraw(const SkRect& rect, const SkPaint* paint, CanvasRenderingContext2DState::ImageType imageType, DrawType drawType) | 
| { | 
| SkCanvas* c = drawingCanvas(); | 
| -    if (!c || !canvas()->buffer()->isRecording()) | 
| +    if (!c || !imageBuffer()->isRecording()) | 
| return; | 
|  | 
| SkRect deviceRect; | 
| @@ -2357,7 +1341,7 @@ void CanvasRenderingContext2D::checkOverdraw(const SkRect& rect, const SkPaint* | 
| SkShader* shader = paint->getShader(); | 
| if (shader) { | 
| if (shader->isOpaque() && alpha == 0xFF) | 
| -                    canvas()->buffer()->willOverwriteCanvas(); | 
| +                    imageBuffer()->willOverwriteCanvas(); | 
| return; | 
| } | 
| } | 
| @@ -2371,7 +1355,12 @@ void CanvasRenderingContext2D::checkOverdraw(const SkRect& rect, const SkPaint* | 
| return; | 
| } | 
|  | 
| -    canvas()->buffer()->willOverwriteCanvas(); | 
| +    imageBuffer()->willOverwriteCanvas(); | 
| +} | 
| + | 
| +DEFINE_TRACE(BaseRenderingContext2D) | 
| +{ | 
| +    visitor->trace(m_stateStack); | 
| } | 
|  | 
| } // namespace blink | 
|  |