Chromium Code Reviews| Index: Source/core/html/canvas/CanvasRenderingContext2DState.cpp |
| diff --git a/Source/core/html/canvas/CanvasRenderingContext2DState.cpp b/Source/core/html/canvas/CanvasRenderingContext2DState.cpp |
| index 3aebf600c88993927f2fe9cd2ac93a86f6a0894f..15bbf1f2d970f4b8af74a15e191c9d040b49fdb0 100644 |
| --- a/Source/core/html/canvas/CanvasRenderingContext2DState.cpp |
| +++ b/Source/core/html/canvas/CanvasRenderingContext2DState.cpp |
| @@ -7,15 +7,22 @@ |
| #include "core/html/canvas/CanvasRenderingContext2DState.h" |
| #include "core/css/CSSFontSelector.h" |
| +#include "core/css/resolver/FilterOperationResolver.h" |
| +#include "core/css/resolver/StyleBuilder.h" |
| +#include "core/css/resolver/StyleResolverState.h" |
| #include "core/html/canvas/CanvasGradient.h" |
| #include "core/html/canvas/CanvasPattern.h" |
| #include "core/html/canvas/CanvasStyle.h" |
| +#include "core/paint/FilterEffectBuilder.h" |
| +#include "core/style/ComputedStyle.h" |
| #include "platform/graphics/DrawLooperBuilder.h" |
| +#include "platform/graphics/filters/SkiaImageFilterBuilder.h" |
| #include "platform/graphics/skia/SkiaUtils.h" |
| #include "third_party/skia/include/effects/SkDashPathEffect.h" |
| #include "third_party/skia/include/effects/SkDropShadowImageFilter.h" |
| static const char defaultFont[] = "10px sans-serif"; |
| +static const char defaultFilter[] = "none"; |
| namespace blink { |
| @@ -28,6 +35,7 @@ CanvasRenderingContext2DState::CanvasRenderingContext2DState() |
| , m_globalAlpha(1) |
| , m_lineDashOffset(0) |
| , m_unparsedFont(defaultFont) |
| + , m_unparsedFilter(defaultFilter) |
| , m_textAlign(StartTextAlign) |
| , m_textBaseline(AlphabeticTextBaseline) |
| , m_direction(DirectionInherit) |
| @@ -75,6 +83,9 @@ CanvasRenderingContext2DState::CanvasRenderingContext2DState(const CanvasRenderi |
| , m_lineDashOffset(other.m_lineDashOffset) |
| , m_unparsedFont(other.m_unparsedFont) |
| , m_font(other.m_font) |
| + , m_unparsedFilter(other.m_unparsedFilter) |
| + , m_filterValue(other.m_filterValue) |
| + , m_resolvedFilter(other.m_resolvedFilter) |
| , m_textAlign(other.m_textAlign) |
| , m_textBaseline(other.m_textBaseline) |
| , m_direction(other.m_direction) |
| @@ -156,6 +167,9 @@ void CanvasRenderingContext2DState::fontsNeedUpdate(CSSFontSelector* fontSelecto |
| ASSERT(m_realizedFont); |
| m_font.update(fontSelector); |
| + // FIXME: We only really need to invalidate the resolved filter if the font |
| + // update above changed anything and the filter uses font-dependent units. |
| + m_resolvedFilter.clear(); |
| } |
| DEFINE_TRACE(CanvasRenderingContext2DState) |
| @@ -286,6 +300,9 @@ void CanvasRenderingContext2DState::setFont(const Font& font, CSSFontSelector* s |
| m_font.update(selector); |
| m_realizedFont = true; |
| selector->registerForInvalidationCallbacks(this); |
| + // FIXME: We only really need to invalidate the resolved filter if it |
| + // uses font-relative units. |
| + m_resolvedFilter.clear(); |
| } |
| const Font& CanvasRenderingContext2DState::font() const |
| @@ -306,6 +323,34 @@ void CanvasRenderingContext2DState::resetTransform() |
| m_isTransformInvertible = true; |
| } |
| +SkImageFilter* CanvasRenderingContext2DState::filter(Element* styleResolutionHost, const Font& font) const |
| +{ |
| + if (!m_filterValue) |
| + return nullptr; |
| + |
| + if (!m_resolvedFilter) { |
| + RefPtr<ComputedStyle> filterStyle = ComputedStyle::create(); |
| + // Must set font in case the filter uses any font-relative units (em, ex) |
| + filterStyle->setFont(font); |
| + SVGComputedStyle& svgStyle = filterStyle->accessSVGStyle(); |
| + |
| + StyleResolverState resolverState(styleResolutionHost->document(), styleResolutionHost, filterStyle.get()); |
| + resolverState.setStyle(filterStyle); |
| + |
| + // TODO(junov): crbug.com/502877 Feed m_fillStyle and m_strokeStyle into FillPaint and |
| + // StrokePaint respectively for filters that refernece SVG. |
|
Stephen White
2015/06/22 15:28:54
Nit: reference
|
| + StyleBuilder::applyProperty(CSSPropertyWebkitFilter, resolverState, m_filterValue.get()); |
| + RefPtrWillBeRawPtr<FilterEffectBuilder> filterEffectBuilder = FilterEffectBuilder::create(); |
| + filterEffectBuilder->build(styleResolutionHost, filterStyle->filter(), FilterEffectBuilder::IgnoreScale); |
| + |
| + SkiaImageFilterBuilder imageFilterBuilder; |
| + RefPtrWillBeRawPtr<FilterEffect> lastEffect = filterEffectBuilder->lastEffect(); |
| + m_resolvedFilter = imageFilterBuilder.build(lastEffect.get(), ColorSpaceDeviceRGB); |
| + } |
| + |
| + return m_resolvedFilter.get(); |
| +} |
| + |
| SkDrawLooper* CanvasRenderingContext2DState::emptyDrawLooper() const |
| { |
| if (!m_emptyDrawLooper) { |
| @@ -386,6 +431,12 @@ void CanvasRenderingContext2DState::setShadowColor(SkColor shadowColor) |
| shadowParameterChanged(); |
| } |
| +void CanvasRenderingContext2DState::setFilter(PassRefPtrWillBeRawPtr<CSSValue> filterValue) |
| +{ |
| + m_filterValue = filterValue; |
| + m_resolvedFilter.clear(); |
| +} |
| + |
| void CanvasRenderingContext2DState::setGlobalComposite(SkXfermode::Mode mode) |
| { |
| m_strokePaint.setXfermodeMode(mode); |
| @@ -454,7 +505,7 @@ const SkPaint* CanvasRenderingContext2DState::getPaint(PaintType paintType, Shad |
| } |
| if (shadowMode == DrawShadowOnly) { |
| - if (imageType == NonOpaqueImage) { |
| + if (imageType == NonOpaqueImage || m_filterValue) { |
| paint->setLooper(0); |
| paint->setImageFilter(shadowOnlyImageFilter()); |
| return paint; |