Chromium Code Reviews| Index: Source/core/html/canvas/CanvasRenderingContext2D.cpp |
| diff --git a/Source/core/html/canvas/CanvasRenderingContext2D.cpp b/Source/core/html/canvas/CanvasRenderingContext2D.cpp |
| index 857ca16f99e644ed5422bff553232724e22523dc..20527d471daf9166debb76e68a37372870dbfc2d 100644 |
| --- a/Source/core/html/canvas/CanvasRenderingContext2D.cpp |
| +++ b/Source/core/html/canvas/CanvasRenderingContext2D.cpp |
| @@ -110,9 +110,9 @@ CanvasRenderingContext2D::CanvasRenderingContext2D(HTMLCanvasElement* canvas, co |
| void CanvasRenderingContext2D::unwindStateStack() |
| { |
| if (size_t stackSize = m_stateStack.size()) { |
| - if (GraphicsContext* context = canvas()->existingDrawingContext()) { |
| + if (SkCanvas* skCanvas = canvas()->existingDrawingCanvas()) { |
| while (--stackSize) |
| - context->restore(); |
| + skCanvas->restore(); |
| } |
| } |
| } |
| @@ -124,9 +124,10 @@ CanvasRenderingContext2D::~CanvasRenderingContext2D() |
| void CanvasRenderingContext2D::validateStateStack() |
| { |
| #if ENABLE(ASSERT) |
| - GraphicsContext* context = canvas()->existingDrawingContext(); |
| - if (context && !context->contextDisabled() && !m_isContextLost) |
| - ASSERT(context->saveCount() == m_stateStack.size()); |
| + SkCanvas* skCanvas = canvas()->existingDrawingCanvas(); |
| + if (skCanvas && !m_isContextLost) { |
| + ASSERT(static_cast<size_t>(skCanvas->getSaveCount() - 1) == m_stateStack.size()); |
|
Stephen Chennney
2015/02/04 19:18:59
Do we have tests covering this assert? I believe i
|
| + } |
| #endif |
| } |
| @@ -134,8 +135,7 @@ bool CanvasRenderingContext2D::isAccelerated() const |
| { |
| if (!canvas()->hasImageBuffer()) |
| return false; |
| - GraphicsContext* context = drawingContext(); |
| - return context && context->isAccelerated(); |
| + return canvas()->buffer()->isAccelerated(); |
| } |
| bool CanvasRenderingContext2D::isContextLost() const |
| @@ -245,25 +245,23 @@ void CanvasRenderingContext2D::reset() |
| void CanvasRenderingContext2D::restoreCanvasMatrixClipStack() |
| { |
| - GraphicsContext* c = drawingContext(); |
| + SkCanvas* c = drawingCanvas(); |
| if (!c) |
| return; |
| WillBeHeapVector<OwnPtrWillBeMember<State>>::iterator currState; |
| for (currState = m_stateStack.begin(); currState < m_stateStack.end(); currState++) { |
| - // We are only restoring state stored in the SkCanvas, and not |
| - // state stored in the graphics context, so we call save() only on the canvas. |
| - // The initial save accounts for the save installed by HTMLCanvasElement::m_contextStateSaver |
| - c->canvas()->save(); |
| + // The initial save accounts for the save installed by canvasElementElement::m_contextStateSaver |
| + c->save(); |
|
Stephen Chennney
2015/02/04 19:18:59
Yippee. Getting rid of a call to GraphicsContext::
|
| c->setMatrix(SkMatrix::I()); |
| currState->get()->m_clipList.playback(c); |
| - c->setCTM(currState->get()->m_transform); |
| + c->setMatrix(affineTransformToSkMatrix(currState->get()->m_transform)); |
| } |
| } |
| // Important: Several of these properties are also stored in GraphicsContext's |
| // StrokeData. The default values that StrokeData uses may not the same values |
| // that the canvas 2d spec specifies. Make sure to sync the initial state of the |
| -// GraphicsContext in HTMLCanvasElement::createImageBuffer()! |
| +// GraphicsContext in canvasElementElement::createImageBuffer()! |
|
Stephen Chennney
2015/02/04 19:18:59
Typo?
|
| CanvasRenderingContext2D::State::State() |
| : m_unrealizedSaveCount(0) |
| , m_strokeStyle(CanvasStyle::createFromRGBA(Color::black)) |
| @@ -388,7 +386,7 @@ void CanvasRenderingContext2D::State::trace(Visitor* visitor) |
| CSSFontSelectorClient::trace(visitor); |
| } |
| -void CanvasRenderingContext2D::realizeSaves(GraphicsContext* context) |
| +void CanvasRenderingContext2D::realizeSaves(SkCanvas* canvas) |
| { |
| validateStateStack(); |
| if (state().m_unrealizedSaveCount) { |
| @@ -402,10 +400,10 @@ void CanvasRenderingContext2D::realizeSaves(GraphicsContext* context) |
| // 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()->m_unrealizedSaveCount = 0; |
| - if (!context) |
| - context = drawingContext(); |
| - if (context) |
| - context->save(); |
| + if (!canvas) |
| + canvas = drawingCanvas(); |
| + if (canvas) |
| + canvas->save(); |
| validateStateStack(); |
| } |
| } |
| @@ -424,9 +422,28 @@ void CanvasRenderingContext2D::restore() |
| m_path.transform(state().m_transform); |
| m_stateStack.removeLast(); |
| m_path.transform(state().m_transform.inverse()); |
| - GraphicsContext* c = drawingContext(); |
| + SkCanvas* c = drawingCanvas(); |
| if (c) |
| c->restore(); |
| + |
| + // Temporary code while crbug.com/453113 is a WIP: GraphicsContext state stack |
|
chrishtr
2015/02/04 07:17:49
How do you plan to get rid of this code later?
dshwang
2015/02/04 13:50:03
I guess @junov will remove GraphicsContext in Imag
|
| + // is no longer exercised so state stored still stored in GC must be re-installed |
| + // after a restore. |
| + GraphicsContext* gc = drawingContext(); |
| + if (gc) { |
| + state().m_fillStyle->applyFillColor(gc); |
| + state().m_strokeStyle->applyStrokeColor(gc); |
| + gc->setStrokeThickness(state().m_lineWidth); |
| + gc->setLineCap(state().m_lineCap); |
| + gc->setLineJoin(state().m_lineJoin); |
| + gc->setMiterLimit(state().m_miterLimit); |
| + applyLineDash(); |
| + gc->setAlphaAsFloat(state().m_globalAlpha); |
| + gc->setCompositeOperation(state().m_globalComposite); |
| + gc->setImageInterpolationQuality(state().m_imageSmoothingEnabled ? CanvasDefaultInterpolationQuality : InterpolationNone); |
| + applyShadow(); |
| + } |
| + |
| validateStateStack(); |
| } |
| @@ -480,12 +497,12 @@ void CanvasRenderingContext2D::setStrokeStyle(const StringOrCanvasGradientOrCanv |
| ASSERT(canvasStyle); |
| - GraphicsContext* c = drawingContext(); |
| + SkCanvas* c = drawingCanvas(); |
| realizeSaves(c); |
| modifiableState().m_strokeStyle = canvasStyle.release(); |
| if (!c) |
| return; |
| - state().m_strokeStyle->applyStrokeColor(c); |
| + state().m_strokeStyle->applyStrokeColor(drawingContext()); |
| modifiableState().m_unparsedStrokeColor = colorString; |
| } |
| @@ -497,7 +514,7 @@ void CanvasRenderingContext2D::fillStyle(StringOrCanvasGradientOrCanvasPattern& |
| void CanvasRenderingContext2D::setFillStyle(const StringOrCanvasGradientOrCanvasPattern& style) |
| { |
| ASSERT(!style.isNull()); |
| - |
| + validateStateStack(); |
| String colorString; |
| RefPtrWillBeRawPtr<CanvasStyle> canvasStyle; |
| if (style.isString()) { |
| @@ -526,12 +543,12 @@ void CanvasRenderingContext2D::setFillStyle(const StringOrCanvasGradientOrCanvas |
| ASSERT(canvasStyle); |
| - GraphicsContext* c = drawingContext(); |
| + SkCanvas* c = drawingCanvas(); |
| realizeSaves(c); |
| modifiableState().m_fillStyle = canvasStyle.release(); |
| if (!c) |
| return; |
| - state().m_fillStyle->applyFillColor(c); |
| + state().m_fillStyle->applyFillColor(drawingContext()); |
| modifiableState().m_unparsedFillColor = colorString; |
| } |
| @@ -546,12 +563,12 @@ void CanvasRenderingContext2D::setLineWidth(float width) |
| return; |
| if (state().m_lineWidth == width) |
| return; |
| - GraphicsContext* c = drawingContext(); |
| + SkCanvas* c = drawingCanvas(); |
| realizeSaves(c); |
| modifiableState().m_lineWidth = width; |
| if (!c) |
| return; |
| - c->setStrokeThickness(width); |
| + drawingContext()->setStrokeThickness(width); |
| } |
| String CanvasRenderingContext2D::lineCap() const |
| @@ -566,12 +583,12 @@ void CanvasRenderingContext2D::setLineCap(const String& s) |
| return; |
| if (state().m_lineCap == cap) |
| return; |
| - GraphicsContext* c = drawingContext(); |
| + SkCanvas* c = drawingCanvas(); |
| realizeSaves(c); |
| modifiableState().m_lineCap = cap; |
| if (!c) |
| return; |
| - c->setLineCap(cap); |
| + drawingContext()->setLineCap(cap); |
| } |
| String CanvasRenderingContext2D::lineJoin() const |
| @@ -586,12 +603,12 @@ void CanvasRenderingContext2D::setLineJoin(const String& s) |
| return; |
| if (state().m_lineJoin == join) |
| return; |
| - GraphicsContext* c = drawingContext(); |
| + SkCanvas* c = drawingCanvas(); |
| realizeSaves(c); |
| modifiableState().m_lineJoin = join; |
| if (!c) |
| return; |
| - c->setLineJoin(join); |
| + drawingContext()->setLineJoin(join); |
| } |
| float CanvasRenderingContext2D::miterLimit() const |
| @@ -605,12 +622,12 @@ void CanvasRenderingContext2D::setMiterLimit(float limit) |
| return; |
| if (state().m_miterLimit == limit) |
| return; |
| - GraphicsContext* c = drawingContext(); |
| + SkCanvas* c = drawingCanvas(); |
| realizeSaves(c); |
| modifiableState().m_miterLimit = limit; |
| if (!c) |
| return; |
| - c->setMiterLimit(limit); |
| + drawingContext()->setMiterLimit(limit); |
| } |
| float CanvasRenderingContext2D::shadowOffsetX() const |
| @@ -744,12 +761,12 @@ void CanvasRenderingContext2D::setGlobalAlpha(float alpha) |
| return; |
| if (state().m_globalAlpha == alpha) |
| return; |
| - GraphicsContext* c = drawingContext(); |
| + SkCanvas* c = drawingCanvas(); |
| realizeSaves(c); |
| modifiableState().m_globalAlpha = alpha; |
| if (!c) |
| return; |
| - c->setAlphaAsFloat(alpha); |
| + drawingContext()->setAlphaAsFloat(alpha); |
| } |
| String CanvasRenderingContext2D::globalCompositeOperation() const |
| @@ -766,12 +783,12 @@ void CanvasRenderingContext2D::setGlobalCompositeOperation(const String& operati |
| SkXfermode::Mode xfermode = WebCoreCompositeToSkiaComposite(op, blendMode); |
| if (state().m_globalComposite == xfermode) |
| return; |
| - GraphicsContext* c = drawingContext(); |
| + SkCanvas* c = drawingCanvas(); |
| realizeSaves(c); |
| modifiableState().m_globalComposite = xfermode; |
| if (!c) |
| return; |
| - c->setCompositeOperation(xfermode); |
| + drawingContext()->setCompositeOperation(xfermode); |
| } |
| void CanvasRenderingContext2D::setCurrentTransform(PassRefPtrWillBeRawPtr<SVGMatrixTearOff> passMatrixTearOff) |
| @@ -783,7 +800,7 @@ void CanvasRenderingContext2D::setCurrentTransform(PassRefPtrWillBeRawPtr<SVGMat |
| void CanvasRenderingContext2D::scale(float sx, float sy) |
| { |
| - GraphicsContext* c = drawingContext(); |
| + SkCanvas* c = drawingCanvas(); |
| if (!c) |
| return; |
| if (!state().m_invertibleCTM) |
| @@ -811,7 +828,7 @@ void CanvasRenderingContext2D::scale(float sx, float sy) |
| void CanvasRenderingContext2D::rotate(float angleInRadians) |
| { |
| - GraphicsContext* c = drawingContext(); |
| + SkCanvas* c = drawingCanvas(); |
| if (!c) |
| return; |
| if (!state().m_invertibleCTM) |
| @@ -833,13 +850,13 @@ void CanvasRenderingContext2D::rotate(float angleInRadians) |
| } |
| modifiableState().m_transform = newTransform; |
| - c->rotate(angleInRadians); |
| + c->rotate(angleInRadians * (180.0f / 3.14159265f)); |
|
dshwang
2015/02/04 13:50:03
how about using piFloat in MathExtras.h
Justin Novosad
2015/02/04 18:37:47
Acknowledged.
|
| m_path.transform(AffineTransform().rotateRadians(-angleInRadians)); |
| } |
| void CanvasRenderingContext2D::translate(float tx, float ty) |
| { |
| - GraphicsContext* c = drawingContext(); |
| + SkCanvas* c = drawingCanvas(); |
| if (!c) |
| return; |
| if (!state().m_invertibleCTM) |
| @@ -867,7 +884,7 @@ void CanvasRenderingContext2D::translate(float tx, float ty) |
| void CanvasRenderingContext2D::transform(float m11, float m12, float m21, float m22, float dx, float dy) |
| { |
| - GraphicsContext* c = drawingContext(); |
| + SkCanvas* c = drawingCanvas(); |
| if (!c) |
| return; |
| if (!state().m_invertibleCTM) |
| @@ -889,13 +906,13 @@ void CanvasRenderingContext2D::transform(float m11, float m12, float m21, float |
| return; |
| } |
| - c->concatCTM(transform); |
| + c->concat(affineTransformToSkMatrix(transform)); |
| m_path.transform(transform.inverse()); |
| } |
| void CanvasRenderingContext2D::resetTransform() |
| { |
| - GraphicsContext* c = drawingContext(); |
| + SkCanvas* c = drawingCanvas(); |
| if (!c) |
| return; |
| @@ -910,7 +927,7 @@ void CanvasRenderingContext2D::resetTransform() |
| // resetTransform() resolves the non-invertible CTM state. |
| modifiableState().m_transform.makeIdentity(); |
| modifiableState().m_invertibleCTM = true; |
| - c->setCTM(canvas()->baseTransform()); |
| + c->setMatrix(affineTransformToSkMatrix(canvas()->baseTransform())); |
| if (invertibleCTM) |
| m_path.transform(ctm); |
| @@ -920,7 +937,7 @@ void CanvasRenderingContext2D::resetTransform() |
| void CanvasRenderingContext2D::setTransform(float m11, float m12, float m21, float m22, float dx, float dy) |
| { |
| - GraphicsContext* c = drawingContext(); |
| + SkCanvas* c = drawingCanvas(); |
| if (!c) |
| return; |
| @@ -965,15 +982,15 @@ static bool isFullCanvasCompositeMode(SkXfermode::Mode op) |
| return op == SkXfermode::kSrcIn_Mode || op == SkXfermode::kSrcOut_Mode || op == SkXfermode::kDstIn_Mode || op == SkXfermode::kDstATop_Mode; |
| } |
| -static WindRule parseWinding(const String& windingRuleString) |
| +static SkPath::FillType parseWinding(const String& windingRuleString) |
| { |
| if (windingRuleString == "nonzero") |
| - return RULE_NONZERO; |
| + return SkPath::kWinding_FillType; |
| if (windingRuleString == "evenodd") |
| - return RULE_EVENODD; |
| + return SkPath::kEvenOdd_FillType; |
| ASSERT_NOT_REACHED(); |
| - return RULE_EVENODD; |
| + return SkPath::kEvenOdd_FillType; |
| } |
| void CanvasRenderingContext2D::fillInternal(const Path& path, const String& windingRuleString) |
| @@ -1000,7 +1017,7 @@ void CanvasRenderingContext2D::fillInternal(const Path& path, const String& wind |
| } |
| WindRule windRule = c->fillRule(); |
| - c->setFillRule(parseWinding(windingRuleString)); |
| + c->setFillRule((WindRule)parseWinding(windingRuleString)); |
| if (isFullCanvasCompositeMode(state().m_globalComposite)) { |
| fullCanvasCompositedDraw(bind(&GraphicsContext::fillPath, c, path)); |
| @@ -1086,7 +1103,7 @@ void CanvasRenderingContext2D::stroke(Path2D* domPath) |
| void CanvasRenderingContext2D::clipInternal(const Path& path, const String& windingRuleString) |
| { |
| - GraphicsContext* c = drawingContext(); |
| + SkCanvas* c = drawingCanvas(); |
| if (!c) { |
| return; |
| } |
| @@ -1096,12 +1113,17 @@ void CanvasRenderingContext2D::clipInternal(const Path& path, const String& wind |
| realizeSaves(c); |
| - WindRule windRule = parseWinding(windingRuleString); |
| + SkPath& skPath = const_cast<SkPath&>(path.skPath()); |
| + // Note: we destructivetly alter the fillType of path |
| + SkPath::FillType oldFillType = skPath.getFillType(); |
| + skPath.setFillType(parseWinding(windingRuleString)); |
| ImageBuffer* buffer = canvas()->buffer(); |
| if (buffer && buffer->needsClipTracking()) { |
| - modifiableState().m_clipList.clipPath(path, windRule, m_clipAntialiasing, state().m_transform); |
| + modifiableState().m_clipList.clipPath(skPath, m_clipAntialiasing, affineTransformToSkMatrix(state().m_transform)); |
| } |
| - c->clipPath(path, windRule, m_clipAntialiasing); |
| + |
| + c->clipPath(skPath, SkRegion::kIntersect_Op, m_clipAntialiasing == AntiAliased); |
| + skPath.setFillType(oldFillType); |
| modifiableState().m_hasClip = true; |
| } |
| @@ -1127,7 +1149,7 @@ bool CanvasRenderingContext2D::isPointInPath(Path2D* domPath, const float x, con |
| bool CanvasRenderingContext2D::isPointInPathInternal(const Path& path, const float x, const float y, const String& windingRuleString) |
| { |
| - GraphicsContext* c = drawingContext(); |
| + SkCanvas* c = drawingCanvas(); |
| if (!c) |
| return false; |
| if (!state().m_invertibleCTM) |
| @@ -1139,7 +1161,7 @@ bool CanvasRenderingContext2D::isPointInPathInternal(const Path& path, const flo |
| AffineTransform ctm = state().m_transform; |
| FloatPoint transformedPoint = ctm.inverse().mapPoint(point); |
| - return path.contains(transformedPoint, parseWinding(windingRuleString)); |
| + return path.contains(transformedPoint, (WindRule)parseWinding(windingRuleString)); |
|
dshwang
2015/02/04 13:50:03
could you make converting inline function for Wind
Justin Novosad
2015/02/04 18:37:47
Acknowledged.
|
| } |
| bool CanvasRenderingContext2D::isPointInStroke(const float x, const float y) |
| @@ -1673,6 +1695,13 @@ void CanvasRenderingContext2D::didDraw(const FloatRect& dirtyRect) |
| canvas()->didDraw(dirtyRect); |
| } |
| +SkCanvas* CanvasRenderingContext2D::drawingCanvas() const |
| +{ |
| + if (isContextLost()) |
| + return nullptr; |
| + return canvas()->drawingCanvas(); |
| +} |
| + |
| GraphicsContext* CanvasRenderingContext2D::drawingContext() const |
| { |
| if (isContextLost()) |
| @@ -1733,7 +1762,7 @@ PassRefPtrWillBeRawPtr<ImageData> CanvasRenderingContext2D::getImageData(float s |
| return nullptr; |
| IntRect imageDataRect = enclosingIntRect(logicalRect); |
| - ImageBuffer* buffer = canvas()->buffer(); |
| + ImageBuffer* buffer =canvas()->buffer(); |
|
Stephen Chennney
2015/02/04 19:18:59
typo?
|
| if (!buffer || isContextLost()) |
| return ImageData::create(imageDataRect.size()); |
| @@ -2224,11 +2253,11 @@ void CanvasRenderingContext2D::setImageSmoothingEnabled(bool enabled) |
| if (enabled == state().m_imageSmoothingEnabled) |
| return; |
| - GraphicsContext* c = drawingContext(); |
| + SkCanvas* c = drawingCanvas(); |
| realizeSaves(c); |
| modifiableState().m_imageSmoothingEnabled = enabled; |
| if (c) |
| - c->setImageInterpolationQuality(enabled ? CanvasDefaultInterpolationQuality : InterpolationNone); |
| + drawingContext()->setImageInterpolationQuality(enabled ? CanvasDefaultInterpolationQuality : InterpolationNone); |
|
dshwang
2015/02/04 13:50:03
Is it safe to mix to use SkCanvas and GraphicsCont
Justin Novosad
2015/02/04 18:37:47
This CL brings us into an intermediate state where
|
| } |
| void CanvasRenderingContext2D::getContextAttributes(Canvas2DContextAttributes& attrs) const |