Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(33)

Unified Diff: Source/core/html/canvas/CanvasRenderingContext2D.cpp

Issue 1194733002: Adding the 'filter' context attribute to 2D canvas (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: Source/core/html/canvas/CanvasRenderingContext2D.cpp
diff --git a/Source/core/html/canvas/CanvasRenderingContext2D.cpp b/Source/core/html/canvas/CanvasRenderingContext2D.cpp
index 3492d658b7ba11cb75890cc2e245f5966653c8e3..0dcaf5397bd2f725b99b06b3f7ebb2240d875b3e 100644
--- a/Source/core/html/canvas/CanvasRenderingContext2D.cpp
+++ b/Source/core/html/canvas/CanvasRenderingContext2D.cpp
@@ -644,6 +644,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());
@@ -815,31 +834,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().filter(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
Stephen White 2015/06/22 15:28:54 There's actually a traversal to determine the mini
+ // 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>
@@ -860,8 +901,8 @@ bool CanvasRenderingContext2D::draw(const DrawFunc& drawFunc, const ContainsFunc
return false;
}
- if (isFullCanvasCompositeMode(state().globalComposite())) {
- fullCanvasCompositedDraw(drawFunc, paintType, imageType);
+ if (isFullCanvasCompositeMode(state().globalComposite()) || state().filter(canvas(), accessFont())) {
+ compositedDraw(drawFunc, paintType, imageType);
didDraw(clipBounds);
} else if (state().globalComposite() == SkXfermode::kSrc_Mode) {
clearCanvas(); // takes care of checkOvewrdraw()

Powered by Google App Engine
This is Rietveld 408576698