GraphicsContext* SVGFilterPainter::prepareEffect( const LayoutObject& object, SVGFilterRecordingContext& recordingContext) { m_filter.clearInvalidationMask(); if (FilterData* filterData = m_filter.getFilterDataForLayoutObject(&object)) { // If the filterData already exists we do not need to record the content // to be filtered. This can occur if the content was previously recorded // or we are in a cycle. if (filterData->m_state == FilterData::PaintingFilter) filterData->m_state = FilterData::PaintingFilterCycleDetected; if (filterData->m_state == FilterData::RecordingContent) filterData->m_state = FilterData::RecordingContentCycleDetected; return nullptr; } SVGFilterGraphNodeMap* nodeMap = SVGFilterGraphNodeMap::create(); FilterEffectBuilder builder(nullptr, object.objectBoundingBox(), 1); Filter* filter = builder.buildReferenceFilter( toSVGFilterElement(*m_filter.element()), nullptr, nodeMap); if (!filter || !filter->lastEffect()) return nullptr; IntRect sourceRegion = enclosingIntRect( intersection(filter->filterRegion(), object.strokeBoundingBox())); filter->getSourceGraphic()->setSourceRect(sourceRegion); FilterData* filterData = FilterData::create(); filterData->lastEffect = filter->lastEffect(); filterData->nodeMap = nodeMap; // TODO(pdr): Can this be moved out of painter? m_filter.setFilterDataForLayoutObject(const_cast<LayoutObject*>(&object), filterData); return recordingContext.beginContent(filterData); }
void SVGFilterRecordingContext::endContent(FilterData* filterData) { DCHECK_EQ(filterData->m_state, FilterData::RecordingContent); Filter* filter = filterData->lastEffect->getFilter(); SourceGraphic* sourceGraphic = filter->getSourceGraphic(); DCHECK(sourceGraphic); // Use the context that contains the filtered content. DCHECK(m_paintController); DCHECK(m_context); m_context->beginRecording(filter->filterRegion()); m_paintController->commitNewDisplayItems(); m_paintController->paintArtifact().replay(*m_context); SkiaImageFilterBuilder::buildSourceGraphic(sourceGraphic, m_context->endRecording()); // Content is cached by the source graphic so temporaries can be freed. m_paintController = nullptr; m_context = nullptr; filterData->m_state = FilterData::ReadyToPaint; }