| Index: Source/core/html/canvas/CanvasRenderingContext2D.cpp
|
| diff --git a/Source/core/html/canvas/CanvasRenderingContext2D.cpp b/Source/core/html/canvas/CanvasRenderingContext2D.cpp
|
| index ad626b2ac61dbe69366729cc585de45edfb25b38..530881d4f49bea62f88371beefff705ace8d1576 100644
|
| --- a/Source/core/html/canvas/CanvasRenderingContext2D.cpp
|
| +++ b/Source/core/html/canvas/CanvasRenderingContext2D.cpp
|
| @@ -645,6 +645,25 @@ void CanvasRenderingContext2D::setGlobalCompositeOperation(const String& operati
|
| modifiableState().setGlobalComposite(xfermode);
|
| }
|
|
|
| +String CanvasRenderingContext2D::filter() const
|
| +{
|
| + return state().unparsedFilter();
|
| +}
|
| +
|
| +void CanvasRenderingContext2D::setFilter(const String& filterString)
|
| +{
|
| + if (filterString == state().unparsedFilter())
|
| + return;
|
| +
|
| + RefPtrWillBeRawPtr<CSSValue> filterValue = CSSParser::parseSingleValue(CSSPropertyWebkitFilter, filterString, CSSParserContext(HTMLStandardMode, 0));
|
| +
|
| + if (!filterValue || filterValue->isInitialValue() || filterValue->isInheritedValue())
|
| + return;
|
| +
|
| + modifiableState().setUnparsedFilter(filterString);
|
| + modifiableState().setFilter(filterValue.release());
|
| +}
|
| +
|
| PassRefPtrWillBeRawPtr<SVGMatrixTearOff> CanvasRenderingContext2D::currentTransform() const
|
| {
|
| return SVGMatrixTearOff::create(state().transform());
|
| @@ -816,31 +835,53 @@ static bool isFullCanvasCompositeMode(SkXfermode::Mode op)
|
| }
|
|
|
| template<typename DrawFunc>
|
| -void CanvasRenderingContext2D::fullCanvasCompositedDraw(const DrawFunc& drawFunc, CanvasRenderingContext2DState::PaintType paintType, CanvasRenderingContext2DState::ImageType imageType)
|
| +void CanvasRenderingContext2D::compositedDraw(const DrawFunc& drawFunc, CanvasRenderingContext2DState::PaintType paintType, CanvasRenderingContext2DState::ImageType imageType)
|
| {
|
| - ASSERT(isFullCanvasCompositeMode(state().globalComposite()));
|
| + SkImageFilter* filter = state().getFilter(canvas(), accessFont());
|
| + ASSERT(isFullCanvasCompositeMode(state().globalComposite()) || filter);
|
| ASSERT(drawingCanvas());
|
| -
|
| - SkPaint layerPaint;
|
| - layerPaint.setXfermodeMode(state().globalComposite());
|
| + SkMatrix ctm = drawingCanvas()->getTotalMatrix();
|
| + drawingCanvas()->resetMatrix();
|
| + SkPaint compositePaint;
|
| + compositePaint.setXfermodeMode(state().globalComposite());
|
| if (state().shouldDrawShadows()) {
|
| // unroll into two independently composited passes if drawing shadows
|
| - drawingCanvas()->saveLayer(nullptr, &layerPaint);
|
| SkPaint shadowPaint = *state().getPaint(paintType, DrawShadowOnly, imageType);
|
| - shadowPaint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
|
| - drawFunc(&shadowPaint);
|
| + int saveCount = drawingCanvas()->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.
|
| + drawingCanvas()->saveLayer(nullptr, &shadowPaint);
|
| + drawingCanvas()->saveLayer(nullptr, &filterPaint);
|
| + SkPaint foregroundPaint = *state().getPaint(paintType, DrawForegroundOnly, imageType);
|
| + drawingCanvas()->setMatrix(ctm);
|
| + drawFunc(&foregroundPaint);
|
| + } else {
|
| + ASSERT(isFullCanvasCompositeMode(state().globalComposite()));
|
| + drawingCanvas()->saveLayer(nullptr, &compositePaint);
|
| + shadowPaint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
|
| + drawingCanvas()->setMatrix(ctm);
|
| + drawFunc(&shadowPaint);
|
| + }
|
| if (!drawingCanvas())
|
| return;
|
| - drawingCanvas()->restore();
|
| + drawingCanvas()->restoreToCount(saveCount);
|
| }
|
|
|
| - drawingCanvas()->saveLayer(nullptr, &layerPaint);
|
| + 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
|
| + drawingCanvas()->saveLayer(nullptr, &compositePaint);
|
| SkPaint foregroundPaint = *state().getPaint(paintType, DrawForegroundOnly, imageType);
|
| foregroundPaint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
|
| + drawingCanvas()->setMatrix(ctm);
|
| drawFunc(&foregroundPaint);
|
| if (!drawingCanvas())
|
| return;
|
| drawingCanvas()->restore();
|
| + drawingCanvas()->setMatrix(ctm);
|
| }
|
|
|
| template<typename DrawFunc, typename ContainsFunc>
|
| @@ -861,8 +902,8 @@ bool CanvasRenderingContext2D::draw(const DrawFunc& drawFunc, const ContainsFunc
|
| return false;
|
| }
|
|
|
| - if (isFullCanvasCompositeMode(state().globalComposite())) {
|
| - fullCanvasCompositedDraw(drawFunc, paintType, imageType);
|
| + if (isFullCanvasCompositeMode(state().globalComposite()) || state().hasFilter()) {
|
| + compositedDraw(drawFunc, paintType, imageType);
|
| didDraw(clipBounds);
|
| } else if (state().globalComposite() == SkXfermode::kSrc_Mode) {
|
| clearCanvas(); // takes care of checkOvewrdraw()
|
|
|