summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/core/paint/svg_foreign_object_painter.cc
blob: 4d7405fcc7c1fa2cc1f24914053dbaa9f0c255ae (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
// 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(), PhysicalOffset());
  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