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 |