blob: cb53167f8bf5c425ad83ba1a68fff1ba60bb4918 [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/core/paint/svg_foreign_object_painter.h"
#include "base/optional.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.h"
#include "third_party/blink/renderer/core/layout/svg/svg_layout_support.h"
#include "third_party/blink/renderer/core/paint/block_painter.h"
#include "third_party/blink/renderer/core/paint/object_painter.h"
#include "third_party/blink/renderer/core/paint/paint_info.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/paint/paint_layer_painter.h"
#include "third_party/blink/renderer/core/paint/scoped_svg_paint_state.h"
#include "third_party/blink/renderer/platform/graphics/paint/display_item_cache_skipper.h"
namespace blink {
void SVGForeignObjectPainter::PaintLayer(const PaintInfo& paint_info) {
if (paint_info.phase != PaintPhase::kForeground &&
paint_info.phase != PaintPhase::kSelection)
return;
// Early out in the case of trying to paint an image filter before
// pre-paint has finished.
if (!layout_svg_foreign_object_.FirstFragment().HasLocalBorderBoxProperties())
return;
// TODO(crbug.com/797779): For now foreign object contents don't know whether
// they are painted in a fragmented context and may do something bad in a
// fragmented context, e.g. creating subsequences. Skip cache to avoid that.
// This will be unnecessary when the contents are fragment aware.
base::Optional<DisplayItemCacheSkipper> cache_skipper;
if (layout_svg_foreign_object_.Layer()->Parent()->EnclosingPaginationLayer())
cache_skipper.emplace(paint_info.context);
// <foreignObject> is a replaced normal-flow stacking element.
// See IsReplacedNormalFlowStacking in paint_layer_painter.cc.
PaintLayerPaintingInfo layer_painting_info(
layout_svg_foreign_object_.Layer(),
// Reset to an infinite cull rect, for simplicity. Otherwise
// an adjustment would be needed for ancestor scrolling, and any
// SVG transforms would have to be taken into account. Further,
// cull rects under transform are intentionally reset to infinity,
// to improve cache invalidation performance in the pre-paint tree
// walk (see https://http://crrev.com/482854).
CullRect::Infinite(), paint_info.GetGlobalPaintFlags(), LayoutSize());
PaintLayerPainter(*layout_svg_foreign_object_.Layer())
.Paint(paint_info.context, layer_painting_info, paint_info.PaintFlags());
}
void SVGForeignObjectPainter::Paint(const PaintInfo& paint_info) {
PaintInfo paint_info_before_filtering(paint_info);
ScopedSVGPaintState paint_state(layout_svg_foreign_object_,
paint_info_before_filtering);
if (paint_state.GetPaintInfo().phase == PaintPhase::kForeground &&
!paint_state.ApplyClipMaskAndFilterIfNecessary())
return;
BlockPainter(layout_svg_foreign_object_).Paint(paint_info);
}
} // namespace blink