diff options
Diffstat (limited to 'chromium/third_party/blink/renderer/core/paint/scoped_svg_paint_state.cc')
-rw-r--r-- | chromium/third_party/blink/renderer/core/paint/scoped_svg_paint_state.cc | 106 |
1 files changed, 52 insertions, 54 deletions
diff --git a/chromium/third_party/blink/renderer/core/paint/scoped_svg_paint_state.cc b/chromium/third_party/blink/renderer/core/paint/scoped_svg_paint_state.cc index e293f0caa1d..cf1ec8de0e0 100644 --- a/chromium/third_party/blink/renderer/core/paint/scoped_svg_paint_state.cc +++ b/chromium/third_party/blink/renderer/core/paint/scoped_svg_paint_state.cc @@ -25,47 +25,59 @@ #include "third_party/blink/renderer/core/paint/scoped_svg_paint_state.h" #include "third_party/blink/renderer/core/layout/svg/layout_svg_resource_filter.h" -#include "third_party/blink/renderer/core/layout/svg/layout_svg_resource_masker.h" -#include "third_party/blink/renderer/core/layout/svg/svg_layout_support.h" #include "third_party/blink/renderer/core/layout/svg/svg_resources.h" #include "third_party/blink/renderer/core/layout/svg/svg_resources_cache.h" -#include "third_party/blink/renderer/core/paint/svg_mask_painter.h" +#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h" namespace blink { -ScopedSVGPaintState::~ScopedSVGPaintState() { - if (filter_) { - DCHECK(SVGResourcesCache::CachedResourcesForLayoutObject(object_)); - DCHECK( - SVGResourcesCache::CachedResourcesForLayoutObject(object_)->Filter() == - filter_); - DCHECK(filter_recording_context_); - SVGFilterPainter(*filter_).FinishEffect(object_, - *filter_recording_context_); - - // Reset the paint info after the filter effect has been completed. - filter_paint_info_ = nullptr; - } +static void PaintFilteredContent(GraphicsContext& context, + const LayoutObject& object, + const DisplayItemClient& display_item_client, + FilterData* filter_data) { + if (DrawingRecorder::UseCachedDrawingIfPossible(context, display_item_client, + DisplayItem::kSVGFilter)) + return; - if (masker_) { + DrawingRecorder recorder(context, display_item_client, + DisplayItem::kSVGFilter); + sk_sp<PaintFilter> image_filter = filter_data->CreateFilter(); + context.Save(); + + // Clip drawing of filtered image to the minimum required paint rect. + const FloatRect object_bounds = object.StrokeBoundingBox(); + const FloatRect paint_rect = filter_data->MapRect(object_bounds); + context.ClipRect(paint_rect); + + // Use the union of the pre-image and the post-image as the layer bounds. + const FloatRect layer_bounds = UnionRect(object_bounds, paint_rect); + context.BeginLayer(1, SkBlendMode::kSrcOver, &layer_bounds, kColorFilterNone, + std::move(image_filter)); + context.EndLayer(); + context.Restore(); +} + +ScopedSVGPaintState::~ScopedSVGPaintState() { + if (filter_data_ && filter_data_->UpdateStateOnFinish()) { DCHECK(SVGResourcesCache::CachedResourcesForLayoutObject(object_)); DCHECK( - SVGResourcesCache::CachedResourcesForLayoutObject(object_)->Masker() == - masker_); - SVGMaskPainter(*masker_).FinishEffect(object_, GetPaintInfo().context); + SVGResourcesCache::CachedResourcesForLayoutObject(object_)->Filter()); + if (filter_recording_context_) { + filter_data_->UpdateContent( + filter_recording_context_->GetPaintRecord(paint_info_)); + filter_recording_context_ = nullptr; + } + PaintFilteredContent(paint_info_.context, object_, display_item_client_, + filter_data_); + filter_data_ = nullptr; } } -bool ScopedSVGPaintState::ApplyClipMaskAndFilterIfNecessary() { +bool ScopedSVGPaintState::ApplyEffects() { #if DCHECK_IS_ON() DCHECK(!apply_clip_mask_and_filter_if_necessary_called_); apply_clip_mask_and_filter_if_necessary_called_ = true; #endif - // In CAP we should early exit once the paint property state has been - // applied, because all meta (non-drawing) display items are ignored in - // CAP. However we can't simply omit them because there are still - // non-composited painting (e.g. SVG filters in particular) that rely on - // these meta display items. ApplyPaintPropertyState(); // When rendering clip paths as masks, only geometric operations should be @@ -93,8 +105,7 @@ bool ScopedSVGPaintState::ApplyClipMaskAndFilterIfNecessary() { SVGResources* resources = SVGResourcesCache::CachedResourcesForLayoutObject(object_); - if (!ApplyMaskIfNecessary(resources)) - return false; + ApplyMaskIfNecessary(resources); if (is_svg_root_or_foreign_object) { // PaintLayerPainter takes care of filter. @@ -102,7 +113,6 @@ bool ScopedSVGPaintState::ApplyClipMaskAndFilterIfNecessary() { } else if (!ApplyFilterIfNecessary(resources)) { return false; } - return true; } @@ -129,25 +139,20 @@ void ScopedSVGPaintState::ApplyPaintPropertyState() { else if (const auto* clip_path_clip = properties->ClipPathClip()) state.SetClip(*clip_path_clip); scoped_paint_chunk_properties_.emplace( - paint_controller, state, object_, + paint_controller, state, display_item_client_, DisplayItem::PaintPhaseToSVGEffectType(GetPaintInfo().phase)); } void ScopedSVGPaintState::ApplyClipIfNecessary() { if (object_.StyleRef().ClipPath()) { clip_path_clipper_.emplace(GetPaintInfo().context, object_, - PhysicalOffset()); + display_item_client_, PhysicalOffset()); } } -bool ScopedSVGPaintState::ApplyMaskIfNecessary(SVGResources* resources) { - if (LayoutSVGResourceMasker* masker = - resources ? resources->Masker() : nullptr) { - if (!SVGMaskPainter(*masker).PrepareEffect(object_, GetPaintInfo().context)) - return false; - masker_ = masker; - } - return true; +void ScopedSVGPaintState::ApplyMaskIfNecessary(SVGResources* resources) { + if (resources && resources->Masker()) + mask_painter_.emplace(paint_info_.context, object_, display_item_client_); } static bool HasReferenceFilterOnly(const ComputedStyle& style) { @@ -162,27 +167,20 @@ static bool HasReferenceFilterOnly(const ComputedStyle& style) { bool ScopedSVGPaintState::ApplyFilterIfNecessary(SVGResources* resources) { if (!resources) return !HasReferenceFilterOnly(object_.StyleRef()); - LayoutSVGResourceFilter* filter = resources->Filter(); if (!filter) return true; - filter_recording_context_ = - std::make_unique<SVGFilterRecordingContext>(GetPaintInfo().context); - filter_ = filter; - GraphicsContext* filter_context = SVGFilterPainter(*filter).PrepareEffect( - object_, *filter_recording_context_); - if (!filter_context) + filter->ClearInvalidationMask(); + filter_data_ = SVGFilterPainter(*filter).PrepareEffect(object_); + // If we have no filter data (== the filter was invalid) or if we + // don't need to update the source graphics, we can short-circuit + // here. + if (!filter_data_ || !filter_data_->ContentNeedsUpdate()) return false; - // Because the filter needs to cache its contents we replace the context // during filtering with the filter's context. - filter_paint_info_ = - std::make_unique<PaintInfo>(*filter_context, paint_info_); - - // Because we cache the filter contents and do not invalidate on paint - // invalidation rect changes, we need to paint the entire filter region - // so elements outside the initial paint (due to scrolling, etc) paint. - filter_paint_info_->ApplyInfiniteCullRect(); + filter_recording_context_ = + std::make_unique<SVGFilterRecordingContext>(paint_info_); return true; } |