Index: Source/core/html/canvas/CanvasRenderingContext2D.cpp |
diff --git a/Source/core/html/canvas/CanvasRenderingContext2D.cpp b/Source/core/html/canvas/CanvasRenderingContext2D.cpp |
index b7555853759be36e604a15be6243de8b9bcb1ddc..b67af669300c4a3a33c2a61b57549e0a2cfc47fe 100644 |
--- a/Source/core/html/canvas/CanvasRenderingContext2D.cpp |
+++ b/Source/core/html/canvas/CanvasRenderingContext2D.cpp |
@@ -61,10 +61,12 @@ |
#include "platform/geometry/FloatQuad.h" |
#include "platform/graphics/DrawLooperBuilder.h" |
#include "platform/graphics/ExpensiveCanvasHeuristicParameters.h" |
-#include "platform/graphics/GraphicsContext.h" |
#include "platform/graphics/ImageBuffer.h" |
+#include "platform/graphics/StrokeData.h" |
+#include "platform/graphics/skia/SkiaUtils.h" |
#include "platform/text/BidiTextRun.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" |
@@ -129,6 +131,7 @@ CanvasRenderingContext2D::CanvasRenderingContext2D(HTMLCanvasElement* canvas, co |
{ |
if (document.settings() && document.settings()->antialiasedClips2dCanvasEnabled()) |
m_clipAntialiasing = AntiAliased; |
+ setShouldAntialias(true); |
m_stateStack.append(adoptPtrWillBeNoop(new CanvasRenderingContext2DState())); |
} |
@@ -151,14 +154,14 @@ void CanvasRenderingContext2D::validateStateStack() |
#if ENABLE(ASSERT) |
SkCanvas* skCanvas = canvas()->existingDrawingCanvas(); |
if (skCanvas && m_contextLostMode == NotLostContext) { |
- ASSERT(static_cast<size_t>(skCanvas->getSaveCount() - 1) == m_stateStack.size()); |
+ ASSERT(static_cast<size_t>(skCanvas->getSaveCount()) == m_stateStack.size()); |
} |
#endif |
} |
CanvasRenderingContext2DState& CanvasRenderingContext2D::modifiableState() |
{ |
- ASSERT(!state().hasUnrealizedSaves()); |
+ realizeSaves(); |
return *m_stateStack.last(); |
} |
@@ -282,6 +285,11 @@ void CanvasRenderingContext2D::reset() |
m_stateStack.resize(1); |
m_stateStack.first() = adoptPtrWillBeNoop(new CanvasRenderingContext2DState()); |
m_path.clear(); |
+ SkCanvas* c = canvas()->existingDrawingCanvas(); |
+ if (c) { |
+ c->resetMatrix(); |
+ c->clipRect(SkRect::MakeWH(canvas()->width(), canvas()->height()), SkRegion::kReplace_Op); |
+ } |
validateStateStack(); |
} |
@@ -300,7 +308,7 @@ void CanvasRenderingContext2D::restoreCanvasMatrixClipStack() |
} |
} |
-void CanvasRenderingContext2D::realizeSaves(SkCanvas* canvas) |
+void CanvasRenderingContext2D::realizeSaves() |
{ |
validateStateStack(); |
if (state().hasUnrealizedSaves()) { |
@@ -314,8 +322,7 @@ void CanvasRenderingContext2D::realizeSaves(SkCanvas* canvas) |
// by the Vector operations copy the unrealized count from the previous state (in |
// turn necessary to support correct resizing and unwinding of the stack). |
m_stateStack.last()->resetUnrealizedSaveCount(); |
- if (!canvas) |
- canvas = drawingCanvas(); |
+ SkCanvas* canvas = drawingCanvas(); |
if (canvas) |
canvas->save(); |
validateStateStack(); |
@@ -345,16 +352,6 @@ void CanvasRenderingContext2D::restore() |
if (c) |
c->restore(); |
- // Temporary code while crbug.com/453113 is a WIP: GraphicsContext state stack |
- // is no longer exercised so state stored still stored in GC must be re-installed |
- // after a restore. |
- GraphicsContext* gc = drawingContext(); |
- if (gc) { |
- gc->setAlphaAsFloat(state().globalAlpha()); |
- gc->setCompositeOperation(state().globalComposite()); |
- gc->setImageInterpolationQuality(state().imageSmoothingEnabled() ? CanvasDefaultInterpolationQuality : InterpolationNone); |
- } |
- |
validateStateStack(); |
} |
@@ -390,7 +387,6 @@ void CanvasRenderingContext2D::setStrokeStyle(const StringOrCanvasGradientOrCanv |
if (!parseColorOrCurrentColor(parsedColor, colorString, canvas())) |
return; |
if (state().strokeStyle()->isEquivalentRGBA(parsedColor)) { |
- realizeSaves(nullptr); |
modifiableState().setUnparsedStrokeColor(colorString); |
return; |
} |
@@ -408,11 +404,7 @@ void CanvasRenderingContext2D::setStrokeStyle(const StringOrCanvasGradientOrCanv |
ASSERT(canvasStyle); |
- SkCanvas* c = drawingCanvas(); |
- realizeSaves(c); |
modifiableState().setStrokeStyle(canvasStyle.release()); |
- if (!c) |
- return; |
modifiableState().setUnparsedStrokeColor(colorString); |
} |
@@ -435,7 +427,6 @@ void CanvasRenderingContext2D::setFillStyle(const StringOrCanvasGradientOrCanvas |
if (!parseColorOrCurrentColor(parsedColor, colorString, canvas())) |
return; |
if (state().fillStyle()->isEquivalentRGBA(parsedColor)) { |
- realizeSaves(nullptr); |
modifiableState().setUnparsedFillColor(colorString); |
return; |
} |
@@ -452,11 +443,6 @@ void CanvasRenderingContext2D::setFillStyle(const StringOrCanvasGradientOrCanvas |
} |
ASSERT(canvasStyle); |
- SkCanvas* c = drawingCanvas(); |
- if (!c) |
- return; |
- realizeSaves(c); |
- |
modifiableState().setFillStyle(canvasStyle.release()); |
modifiableState().setUnparsedFillColor(colorString); |
} |
@@ -472,11 +458,7 @@ void CanvasRenderingContext2D::setLineWidth(float width) |
return; |
if (state().lineWidth() == width) |
return; |
- SkCanvas* c = drawingCanvas(); |
- realizeSaves(c); |
modifiableState().setLineWidth(width); |
- if (!c) |
- return; |
} |
String CanvasRenderingContext2D::lineCap() const |
@@ -491,11 +473,7 @@ void CanvasRenderingContext2D::setLineCap(const String& s) |
return; |
if (state().lineCap() == cap) |
return; |
- SkCanvas* c = drawingCanvas(); |
- realizeSaves(c); |
modifiableState().setLineCap(cap); |
- if (!c) |
- return; |
} |
String CanvasRenderingContext2D::lineJoin() const |
@@ -510,11 +488,7 @@ void CanvasRenderingContext2D::setLineJoin(const String& s) |
return; |
if (state().lineJoin() == join) |
return; |
- SkCanvas* c = drawingCanvas(); |
- realizeSaves(c); |
modifiableState().setLineJoin(join); |
- if (!c) |
- return; |
} |
float CanvasRenderingContext2D::miterLimit() const |
@@ -528,11 +502,7 @@ void CanvasRenderingContext2D::setMiterLimit(float limit) |
return; |
if (state().miterLimit() == limit) |
return; |
- SkCanvas* c = drawingCanvas(); |
- realizeSaves(c); |
modifiableState().setMiterLimit(limit); |
- if (!c) |
- return; |
} |
float CanvasRenderingContext2D::shadowOffsetX() const |
@@ -546,7 +516,6 @@ void CanvasRenderingContext2D::setShadowOffsetX(float x) |
return; |
if (state().shadowOffset().width() == x) |
return; |
- realizeSaves(nullptr); |
modifiableState().setShadowOffsetX(x); |
} |
@@ -561,7 +530,6 @@ void CanvasRenderingContext2D::setShadowOffsetY(float y) |
return; |
if (state().shadowOffset().height() == y) |
return; |
- realizeSaves(nullptr); |
modifiableState().setShadowOffsetY(y); |
} |
@@ -576,7 +544,6 @@ void CanvasRenderingContext2D::setShadowBlur(float blur) |
return; |
if (state().shadowBlur() == blur) |
return; |
- realizeSaves(nullptr); |
modifiableState().setShadowBlur(blur); |
} |
@@ -592,7 +559,6 @@ void CanvasRenderingContext2D::setShadowColor(const String& color) |
return; |
if (state().shadowColor() == rgba) |
return; |
- realizeSaves(nullptr); |
modifiableState().setShadowColor(rgba); |
} |
@@ -614,8 +580,6 @@ void CanvasRenderingContext2D::setLineDash(const Vector<float>& dash) |
{ |
if (!lineDashSequenceIsValid(dash)) |
return; |
- |
- realizeSaves(nullptr); |
modifiableState().setLineDash(dash); |
} |
@@ -628,8 +592,6 @@ void CanvasRenderingContext2D::setLineDashOffset(float offset) |
{ |
if (!std::isfinite(offset) || state().lineDashOffset() == offset) |
return; |
- |
- realizeSaves(nullptr); |
modifiableState().setLineDashOffset(offset); |
} |
@@ -644,12 +606,17 @@ void CanvasRenderingContext2D::setGlobalAlpha(float alpha) |
return; |
if (state().globalAlpha() == alpha) |
return; |
- SkCanvas* c = drawingCanvas(); |
- realizeSaves(c); |
modifiableState().setGlobalAlpha(alpha); |
- if (!c) |
- return; |
- drawingContext()->setAlphaAsFloat(alpha); |
+} |
+ |
+bool CanvasRenderingContext2D::shouldAntialias() const |
+{ |
+ return state().shouldAntialias(); |
+} |
+ |
+void CanvasRenderingContext2D::setShouldAntialias(bool doAA) |
+{ |
+ modifiableState().setShouldAntialias(doAA); |
} |
String CanvasRenderingContext2D::globalCompositeOperation() const |
@@ -673,12 +640,7 @@ void CanvasRenderingContext2D::setGlobalCompositeOperation(const String& operati |
SkXfermode::Mode xfermode = WebCoreCompositeToSkiaComposite(op, blendMode); |
if (state().globalComposite() == xfermode) |
return; |
- SkCanvas* c = drawingCanvas(); |
- realizeSaves(c); |
modifiableState().setGlobalComposite(xfermode); |
- if (!c) |
- return; |
- drawingContext()->setCompositeOperation(xfermode); |
} |
PassRefPtrWillBeRawPtr<SVGMatrixTearOff> CanvasRenderingContext2D::currentTransform() const |
@@ -707,8 +669,6 @@ void CanvasRenderingContext2D::scale(float sx, float sy) |
if (state().transform() == newTransform) |
return; |
- realizeSaves(c); |
- |
modifiableState().setTransform(newTransform); |
if (!state().isTransformInvertible()) |
return; |
@@ -731,8 +691,6 @@ void CanvasRenderingContext2D::rotate(float angleInRadians) |
if (state().transform() == newTransform) |
return; |
- realizeSaves(c); |
- |
modifiableState().setTransform(newTransform); |
if (!state().isTransformInvertible()) |
return; |
@@ -756,8 +714,6 @@ void CanvasRenderingContext2D::translate(float tx, float ty) |
if (state().transform() == newTransform) |
return; |
- realizeSaves(c); |
- |
modifiableState().setTransform(newTransform); |
if (!state().isTransformInvertible()) |
return; |
@@ -779,8 +735,6 @@ void CanvasRenderingContext2D::transform(float m11, float m12, float m21, float |
if (state().transform() == newTransform) |
return; |
- realizeSaves(c); |
- |
modifiableState().setTransform(newTransform); |
if (!state().isTransformInvertible()) |
return; |
@@ -802,7 +756,6 @@ void CanvasRenderingContext2D::resetTransform() |
if (ctm.isIdentity() && invertibleCTM) |
return; |
- realizeSaves(c); |
// resetTransform() resolves the non-invertible CTM state. |
modifiableState().resetTransform(); |
c->setMatrix(affineTransformToSkMatrix(canvas()->baseTransform())); |
@@ -899,9 +852,12 @@ bool CanvasRenderingContext2D::draw(const DrawFunc& drawFunc, const ContainsFunc |
return false; |
// If gradient size is zero, then paint nothing. |
- CanvasGradient* gradient = state().style(paintType)->canvasGradient(); |
- if (gradient && gradient->gradient()->isZeroSize()) |
- return false; |
+ CanvasStyle* style = state().style(paintType); |
+ if (style) { |
+ CanvasGradient* gradient = style->canvasGradient(); |
+ if (gradient && gradient->gradient()->isZeroSize()) |
+ return false; |
+ } |
if (isFullCanvasCompositeMode(state().globalComposite())) { |
fullCanvasCompositedDraw(drawFunc, paintType, imageType); |
@@ -915,7 +871,7 @@ bool CanvasRenderingContext2D::draw(const DrawFunc& drawFunc, const ContainsFunc |
SkIRect dirtyRect; |
if (computeDirtyRect(bounds, clipBounds, &dirtyRect)) { |
const SkPaint* paint = state().getPaint(paintType, DrawShadowAndForeground, imageType); |
- if (paintType == CanvasRenderingContext2DState::FillPaintType && drawCoversClipBounds(clipBounds)) |
+ if (paintType != CanvasRenderingContext2DState::StrokePaintType && drawCoversClipBounds(clipBounds)) |
checkOverdraw(bounds, paint, imageType, ClipFill); |
drawFunc(paint); |
didDraw(dirtyRect); |
@@ -1064,8 +1020,6 @@ void CanvasRenderingContext2D::clipInternal(const Path& path, const String& wind |
return; |
} |
- realizeSaves(c); |
- |
SkPath skPath = path.skPath(); |
skPath.setFillType(parseWinding(windingRuleString)); |
modifiableState().clipPath(skPath, m_clipAntialiasing); |
@@ -1222,20 +1176,6 @@ void CanvasRenderingContext2D::clearRect(float x, float y, float width, float he |
} |
} |
-void CanvasRenderingContext2D::applyShadow(ShadowMode shadowMode) |
-{ |
- GraphicsContext* c = drawingContext(); |
- if (!c) |
- return; |
- |
- if (state().shouldDrawShadows()) { |
- c->setShadow(state().shadowOffset(), state().shadowBlur(), state().shadowColor(), |
- DrawLooperBuilder::ShadowIgnoresTransforms, DrawLooperBuilder::ShadowRespectsAlpha, shadowMode); |
- } else { |
- c->clearShadow(); |
- } |
-} |
- |
static inline FloatRect normalizeRect(const FloatRect& rect) |
{ |
return FloatRect(std::min(rect.x(), rect.maxX()), |
@@ -1301,45 +1241,77 @@ void CanvasRenderingContext2D::drawImage(const CanvasImageSourceUnion& imageSour |
drawImage(imageSourceInternal, sx, sy, sw, sh, dx, dy, dw, dh, exceptionState); |
} |
-void CanvasRenderingContext2D::drawVideo(CanvasImageSource* imageSource, const FloatRect& srcRect, const FloatRect& dstRect) |
+bool CanvasRenderingContext2D::shouldDrawImageAntialiased(const FloatRect& destRect) const |
{ |
- HTMLVideoElement* video = static_cast<HTMLVideoElement*>(imageSource); |
- ASSERT(video); |
+ if (!shouldAntialias()) |
+ return false; |
SkCanvas* c = drawingCanvas(); |
- if (!c) |
- return; |
- c->save(); |
- c->clipRect(WebCoreFloatRectToSKRect(dstRect)); |
- c->translate(dstRect.x(), dstRect.y()); |
- c->scale(dstRect.width() / srcRect.width(), dstRect.height() / srcRect.height()); |
- c->translate(-srcRect.x(), -srcRect.y()); |
- video->paintCurrentFrameInContext(drawingContext(), IntRect(IntPoint(), IntSize(video->videoWidth(), video->videoHeight()))); |
- // In case the paint propagated a queued context loss signal |
- if (drawingCanvas()) |
- drawingCanvas()->restore(); |
+ ASSERT(c); |
+ |
+ const SkMatrix &ctm = c->getTotalMatrix(); |
+ // Don't disable anti-aliasing if we're rotated or skewed. |
+ if (!ctm.rectStaysRect()) |
+ return true; |
+ // Check if the dimensions of the destination are "small" (less than one |
+ // device pixel). To prevent sudden drop-outs. Since we know that |
+ // kRectStaysRect_Mask is set, the matrix either has scale and no skew or |
+ // vice versa. We can query the kAffine_Mask flag to determine which case |
+ // it is. |
+ // FIXME: This queries the CTM while drawing, which is generally |
+ // discouraged. Always drawing with AA can negatively impact performance |
+ // though - that's why it's not always on. |
+ SkScalar widthExpansion, heightExpansion; |
+ if (ctm.getType() & SkMatrix::kAffine_Mask) |
+ widthExpansion = ctm[SkMatrix::kMSkewY], heightExpansion = ctm[SkMatrix::kMSkewX]; |
+ else |
+ widthExpansion = ctm[SkMatrix::kMScaleX], heightExpansion = ctm[SkMatrix::kMScaleY]; |
+ return destRect.width() * fabs(widthExpansion) < 1 || destRect.height() * fabs(heightExpansion) < 1; |
} |
-void CanvasRenderingContext2D::drawImageOnContext(CanvasImageSource* imageSource, Image* image, const FloatRect& srcRect, const FloatRect& dstRect, const SkPaint* paint) |
+void CanvasRenderingContext2D::drawImageInternal(CanvasImageSource* imageSource, Image* image, const FloatRect& srcRect, const FloatRect& dstRect, const SkPaint* paint) |
{ |
- SkXfermode::Mode mode; |
- if (!SkXfermode::AsMode(paint->getXfermode(), &mode)) |
- mode = SkXfermode::kSrcOver_Mode; |
+ SkCanvas* c = drawingCanvas(); |
+ ASSERT(c); |
+ |
+ int initialSaveCount = c->getSaveCount(); |
+ SkPaint imagePaint = *paint; |
- RefPtr<SkImageFilter> imageFilter(paint->getImageFilter()); |
- drawingContext()->setDropShadowImageFilter(imageFilter.release()); |
- RefPtr<SkDrawLooper> drawLooper(paint->getLooper()); |
- drawingContext()->setDrawLooper(drawLooper.release()); |
+ if (paint->getImageFilter()) { |
+ SkMatrix ctm = c->getTotalMatrix(); |
+ SkMatrix invCtm; |
+ if (!ctm.invert(&invCtm)) { |
+ ASSERT_NOT_REACHED(); // There is an earlier check for invertibility |
+ } |
+ c->save(); |
+ c->concat(invCtm); |
+ SkRect bounds = dstRect; |
+ ctm.mapRect(&bounds); |
+ SkRect filteredBounds; |
+ paint->getImageFilter()->computeFastBounds(bounds, &filteredBounds); |
+ SkPaint layerPaint; |
+ layerPaint.setXfermode(paint->getXfermode()); |
+ layerPaint.setImageFilter(paint->getImageFilter()); |
+ c->saveLayer(&filteredBounds, &layerPaint); |
+ c->concat(ctm); |
+ imagePaint.setXfermodeMode(SkXfermode::kSrcOver_Mode); |
+ imagePaint.setImageFilter(nullptr); |
+ } |
if (!imageSource->isVideoElement()) { |
- drawingContext()->drawImage(image, dstRect, srcRect, mode); |
+ // TODO: Find a way to pass SkCanvas::kBleed_DrawBitmapRectFlag |
+ imagePaint.setAntiAlias(shouldDrawImageAntialiased(dstRect)); |
+ image->draw(c, imagePaint, dstRect, srcRect, DoNotRespectImageOrientation, Image::DoNotClampImage); |
} else { |
- SkXfermode::Mode oldMode = drawingContext()->compositeOperation(); |
- drawingContext()->setCompositeOperation(mode); |
- drawVideo(imageSource, srcRect, dstRect); |
- // Must re-check drawingContext() in case drawVideo propagated a pending context loss signal |
- if (drawingContext()) |
- drawingContext()->setCompositeOperation(oldMode); |
+ c->save(); |
+ c->clipRect(WebCoreFloatRectToSKRect(dstRect)); |
+ c->translate(dstRect.x(), dstRect.y()); |
+ c->scale(dstRect.width() / srcRect.width(), dstRect.height() / srcRect.height()); |
+ c->translate(-srcRect.x(), -srcRect.y()); |
+ HTMLVideoElement* video = static_cast<HTMLVideoElement*>(imageSource); |
+ video->paintCurrentFrame(c, IntRect(IntPoint(), IntSize(video->videoWidth(), video->videoHeight())), &imagePaint); |
} |
+ |
+ c->restoreToCount(initialSaveCount); |
} |
void CanvasRenderingContext2D::drawImage(CanvasImageSource* imageSource, |
@@ -1392,15 +1364,14 @@ void CanvasRenderingContext2D::drawImage(CanvasImageSource* imageSource, |
draw( |
[this, &imageSource, &image, &srcRect, dstRect](const SkPaint* paint) // draw lambda |
{ |
- if (drawingCanvas()) |
- drawImageOnContext(imageSource, image.get(), srcRect, dstRect, paint); |
+ drawImageInternal(imageSource, image.get(), srcRect, dstRect, paint); |
}, |
[this, &dstRect](const SkIRect& clipBounds) // overdraw test lambda |
{ |
return rectContainsTransformedRect(dstRect, clipBounds); |
}, |
dstRect, |
- CanvasRenderingContext2DState::FillPaintType, |
+ CanvasRenderingContext2DState::ImagePaintType, |
imageSource->isOpaque() ? CanvasRenderingContext2DState::OpaqueImage : CanvasRenderingContext2DState::NonOpaqueImage); |
validateStateStack(); |
@@ -1546,13 +1517,6 @@ SkCanvas* CanvasRenderingContext2D::drawingCanvas() const |
return canvas()->drawingCanvas(); |
} |
-GraphicsContext* CanvasRenderingContext2D::drawingContext() const |
-{ |
- if (isContextLost()) |
- return nullptr; |
- return canvas()->drawingContext(); |
-} |
- |
ImageData* CanvasRenderingContext2D::createImageData(ImageData* imageData) const |
{ |
return ImageData::create(imageData->size()); |
@@ -1730,7 +1694,6 @@ void CanvasRenderingContext2D::setFont(const String& newFont) |
// The parse succeeded. |
String newFontSafeCopy(newFont); // Create a string copy since newFont can be deleted inside realizeSaves. |
- realizeSaves(nullptr); |
modifiableState().setUnparsedFont(newFontSafeCopy); |
// Map the <canvas> font into the text style. If the font uses keywords like larger/smaller, these will work |
@@ -1773,7 +1736,6 @@ void CanvasRenderingContext2D::setTextAlign(const String& s) |
return; |
if (state().textAlign() == align) |
return; |
- realizeSaves(nullptr); |
modifiableState().setTextAlign(align); |
} |
@@ -1789,7 +1751,6 @@ void CanvasRenderingContext2D::setTextBaseline(const String& s) |
return; |
if (state().textBaseline() == baseline) |
return; |
- realizeSaves(nullptr); |
modifiableState().setTextBaseline(baseline); |
} |
@@ -1832,7 +1793,6 @@ void CanvasRenderingContext2D::setDirection(const String& directionString) |
if (state().direction() == direction) |
return; |
- realizeSaves(nullptr); |
modifiableState().setDirection(direction); |
} |
@@ -2006,8 +1966,6 @@ void CanvasRenderingContext2D::inflateStrokeRect(FloatRect& rect) const |
const Font& CanvasRenderingContext2D::accessFont() |
{ |
- // This needs style to be up to date, but can't assert so because drawTextInternal |
- // can invalidate style before this is called (e.g. drawingContext invalidates style). |
if (!state().hasRealizedFont()) |
setFont(state().unparsedFont()); |
return state().font(); |
@@ -2061,11 +2019,7 @@ void CanvasRenderingContext2D::setImageSmoothingEnabled(bool enabled) |
if (enabled == state().imageSmoothingEnabled()) |
return; |
- SkCanvas* c = drawingCanvas(); |
- realizeSaves(c); |
modifiableState().setImageSmoothingEnabled(enabled); |
- if (c) |
- drawingContext()->setImageInterpolationQuality(enabled ? CanvasDefaultInterpolationQuality : InterpolationNone); |
} |
void CanvasRenderingContext2D::getContextAttributes(Canvas2DContextAttributes& attrs) const |
@@ -2115,14 +2069,13 @@ bool CanvasRenderingContext2D::focusRingCallIsValid(const Path& path, Element* e |
void CanvasRenderingContext2D::drawFocusRing(const Path& path) |
{ |
- GraphicsContext* c = drawingContext(); |
- if (!c) |
+ if (!drawingCanvas()) |
return; |
- // These should match the style defined in html.css. |
- Color focusRingColor = LayoutTheme::theme().focusRingColor(); |
+ SkColor color = LayoutTheme::theme().focusRingColor().rgb(); |
const int focusRingWidth = 5; |
- const int focusRingOutline = 0; |
+ |
+ drawPlatformFocusRing(path.skPath(), drawingCanvas(), color, focusRingWidth); |
// We need to add focusRingWidth to dirtyRect. |
StrokeData strokeData; |
@@ -2132,14 +2085,6 @@ void CanvasRenderingContext2D::drawFocusRing(const Path& path) |
if (!computeDirtyRect(path.strokeBoundingRect(strokeData), &dirtyRect)) |
return; |
- c->setAlphaAsFloat(1.0); |
- c->clearShadow(); |
- c->setCompositeOperation(SkXfermode::kSrcOver_Mode); |
- c->drawFocusRing(path, focusRingWidth, focusRingOutline, focusRingColor); |
- c->setAlphaAsFloat(state().globalAlpha()); |
- c->setCompositeOperation(state().globalComposite()); |
- |
- validateStateStack(); |
didDraw(dirtyRect); |
} |