blob: 77847cb1415df263c8168cf863ce4ca52dacf422 (
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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
// 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_container_painter.h"
#include "base/optional.h"
#include "third_party/blink/renderer/core/layout/layout_box_model_object.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_container.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_viewport_container.h"
#include "third_party/blink/renderer/core/layout/svg/svg_layout_support.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/scoped_svg_paint_state.h"
#include "third_party/blink/renderer/core/paint/svg_foreign_object_painter.h"
#include "third_party/blink/renderer/core/paint/svg_model_object_painter.h"
#include "third_party/blink/renderer/core/svg/svg_svg_element.h"
namespace blink {
void SVGContainerPainter::Paint(const PaintInfo& paint_info) {
// Spec: groups w/o children still may render filter content.
if (!layout_svg_container_.FirstChild() &&
!layout_svg_container_.SelfWillPaint())
return;
// Spec: An empty viewBox on the <svg> element disables rendering.
DCHECK(layout_svg_container_.GetElement());
auto* svg_svg_element =
DynamicTo<SVGSVGElement>(*layout_svg_container_.GetElement());
if (svg_svg_element && svg_svg_element->HasEmptyViewBox())
return;
PaintInfo paint_info_before_filtering(paint_info);
if (SVGModelObjectPainter(layout_svg_container_)
.CullRectSkipsPainting(paint_info_before_filtering)) {
return;
}
// We do not apply cull rect optimizations across transforms for two reasons:
// 1) Performance: We can optimize transform changes by not repainting.
// 2) Complexity: Difficulty updating clips when ancestor transforms change.
// This is why we use an infinite cull rect if there is a transform. Non-svg
// content, does this in PaintLayerPainter::PaintSingleFragment.
if (layout_svg_container_.StyleRef().HasTransform()) {
paint_info_before_filtering.ApplyInfiniteCullRect();
} else if (const auto* properties =
layout_svg_container_.FirstFragment().PaintProperties()) {
if (const auto* transform = properties->Transform())
paint_info_before_filtering.TransformCullRect(*transform);
}
ScopedSVGTransformState transform_state(
paint_info_before_filtering, layout_svg_container_,
layout_svg_container_.LocalToSVGParentTransform());
{
base::Optional<ScopedPaintChunkProperties> scoped_paint_chunk_properties;
if (layout_svg_container_.IsSVGViewportContainer() &&
SVGLayoutSupport::IsOverflowHidden(layout_svg_container_)) {
const auto* fragment = paint_info.FragmentToPaint(layout_svg_container_);
if (!fragment)
return;
const auto* properties = fragment->PaintProperties();
// TODO(crbug.com/814815): The condition should be a DCHECK, but for now
// we may paint the object for filters during PrePaint before the
// properties are ready.
if (properties && properties->OverflowClip()) {
scoped_paint_chunk_properties.emplace(
paint_info.context.GetPaintController(),
*properties->OverflowClip(), layout_svg_container_,
paint_info.DisplayItemTypeForClipping());
}
}
ScopedSVGPaintState paint_state(layout_svg_container_,
paint_info_before_filtering);
bool continue_rendering = true;
if (paint_state.GetPaintInfo().phase == PaintPhase::kForeground)
continue_rendering = paint_state.ApplyClipMaskAndFilterIfNecessary();
if (continue_rendering) {
for (LayoutObject* child = layout_svg_container_.FirstChild(); child;
child = child->NextSibling()) {
if (child->IsSVGForeignObject()) {
SVGForeignObjectPainter(ToLayoutSVGForeignObject(*child))
.PaintLayer(paint_state.GetPaintInfo());
} else {
child->Paint(paint_state.GetPaintInfo());
}
}
}
}
SVGModelObjectPainter(layout_svg_container_)
.PaintOutline(paint_info_before_filtering);
if (paint_info_before_filtering.ShouldAddUrlMetadata() &&
paint_info_before_filtering.phase == PaintPhase::kForeground) {
ObjectPainter(layout_svg_container_)
.AddURLRectIfNeeded(paint_info_before_filtering, PhysicalOffset());
}
}
} // namespace blink
|