SkImageFilter* CanvasRenderingContext2DState::getFilter(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);

        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 reference SVG.
        StyleBuilder::applyProperty(CSSPropertyWebkitFilter, resolverState, m_filterValue.get());
        RefPtrWillBeRawPtr<FilterEffectBuilder> filterEffectBuilder = FilterEffectBuilder::create();
        const float effectiveZoom = 1.0f; // Deliberately ignore zoom on the canvas element
        filterEffectBuilder->build(styleResolutionHost, filterStyle->filter(), effectiveZoom);

        SkiaImageFilterBuilder imageFilterBuilder;
        RefPtrWillBeRawPtr<FilterEffect> lastEffect = filterEffectBuilder->lastEffect();
        m_resolvedFilter = imageFilterBuilder.build(lastEffect.get(), ColorSpaceDeviceRGB);
    }

    return m_resolvedFilter.get();
}
SkImageFilter* CanvasRenderingContext2DState::getFilter(Element* styleResolutionHost, const Font& font, IntSize canvasSize) 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);

        StyleResolverState resolverState(styleResolutionHost->document(), styleResolutionHost, filterStyle.get());
        resolverState.setStyle(filterStyle);

        StyleBuilder::applyProperty(CSSPropertyWebkitFilter, resolverState, m_filterValue.get());
        RefPtrWillBeRawPtr<FilterEffectBuilder> filterEffectBuilder = FilterEffectBuilder::create();

        // We can't reuse m_fillPaint and m_strokePaint for the filter, since these incorporate
        // the global alpha, which isn't applicable here.
        SkPaint fillPaintForFilter;
        SkPaint strokePaintForFilter;
        m_fillStyle->applyToPaint(fillPaintForFilter);
        m_strokeStyle->applyToPaint(strokePaintForFilter);
        fillPaintForFilter.setColor(m_fillStyle->paintColor());
        strokePaintForFilter.setColor(m_strokeStyle->paintColor());
        FloatSize floatCanvasSize(canvasSize);
        const double effectiveZoom = 1.0; // Deliberately ignore zoom on the canvas element
        filterEffectBuilder->build(styleResolutionHost, filterStyle->filter(), effectiveZoom, &floatCanvasSize, &fillPaintForFilter, &strokePaintForFilter);

        SkiaImageFilterBuilder imageFilterBuilder;
        RefPtrWillBeRawPtr<FilterEffect> lastEffect = filterEffectBuilder->lastEffect();
        m_resolvedFilter = imageFilterBuilder.build(lastEffect.get(), ColorSpaceDeviceRGB);
    }

    return m_resolvedFilter.get();
}
SkImageFilter* CanvasRenderingContext2DState::getFilter(
    Element* styleResolutionHost,
    IntSize canvasSize,
    CanvasRenderingContext2D* context) const {
    if (!m_filterValue)
        return nullptr;

    // StyleResolverState cannot be used in frame-less documents.
    if (!styleResolutionHost->document().frame())
        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(m_fontForFilter);

        StyleResolverState resolverState(styleResolutionHost->document(),
                                         styleResolutionHost, filterStyle.get());
        resolverState.setStyle(filterStyle);

        StyleBuilder::applyProperty(CSSPropertyFilter, resolverState,
                                    *m_filterValue);
        resolverState.loadPendingResources();

        // We can't reuse m_fillPaint and m_strokePaint for the filter, since these
        // incorporate the global alpha, which isn't applicable here.
        SkPaint fillPaintForFilter;
        m_fillStyle->applyToPaint(fillPaintForFilter);
        fillPaintForFilter.setColor(m_fillStyle->paintColor());
        SkPaint strokePaintForFilter;
        m_strokeStyle->applyToPaint(strokePaintForFilter);
        strokePaintForFilter.setColor(m_strokeStyle->paintColor());

        FilterEffectBuilder filterEffectBuilder(
            styleResolutionHost, FloatRect((FloatPoint()), FloatSize(canvasSize)),
            1.0f,  // Deliberately ignore zoom on the canvas element.
            &fillPaintForFilter, &strokePaintForFilter);

        if (FilterEffect* lastEffect =
                    filterEffectBuilder.buildFilterEffect(filterStyle->filter())) {
            m_resolvedFilter =
                SkiaImageFilterBuilder::build(lastEffect, ColorSpaceDeviceRGB);
            if (m_resolvedFilter) {
                updateFilterReferences(toHTMLCanvasElement(styleResolutionHost),
                                       context, filterStyle->filter());
                if (lastEffect->originTainted())
                    context->setOriginTainted();
            }
        }
    }

    return m_resolvedFilter.get();
}