| 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 69aca02f0e59173f476b8e1a260fa0e05dc9a2ac..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().updateLayoutTreeForNode(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().updateLayoutTreeForNode(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().updateLayoutTreeForNode(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().updateLayoutTreeForNode(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
|
|
|