Bug 234524

Summary: [LBSE] Begin layer-aware RenderSVGModelObject implementation
Product: WebKit Reporter: Nikolas Zimmermann <zimmermann>
Component: SVGAssignee: Nikolas Zimmermann <zimmermann>
Status: RESOLVED FIXED    
Severity: Normal CC: changseok, dino, esprehn+autocc, ews-watchlist, fmalita, fred.wang, glenn, gyuyoung.kim, kondapallykalyan, pdr, rbuis, sabouhallawa, schenney, sergio, simon.fraser, webkit-bug-importer, zimmermann
Priority: P2 Keywords: InRadar
Version: WebKit Nightly Build   
Hardware: Unspecified   
OS: Unspecified   
Bug Depends on: 234235    
Bug Blocks: 90738, 234632    
Attachments:
Description Flags
Patch, v1
none
Patch, v2
none
Patch, v3
ews-feeder: commit-queue-
Patch, v4
none
Patch, v5
none
Patch, v6
none
Patch, v7
none
Patch, v8 rbuis: review+

Description Nikolas Zimmermann 2021-12-20 13:29:00 PST
Following the move RenderSVGModelObject -> LegacyRenderSVGModelObject (bug #234235), a new RenderSVGModelObject implementation, tied to ENABLE(LAYER_BASED_SVG_ENGINE) is needed. Unlike LegacyRenderSVGModelObject it inherits from RenderLayerModelObject of RenderElement, since SVG elements in LBSE may create layers (to be upstreamed in future patches).
Comment 1 Nikolas Zimmermann 2021-12-20 15:10:45 PST
Created attachment 447652 [details]
Patch, v1
Comment 2 Rob Buis 2021-12-21 07:41:28 PST
Comment on attachment 447652 [details]
Patch, v1

View in context: https://bugs.webkit.org/attachment.cgi?id=447652&action=review

> Source/WebCore/ChangeLog:21
> +        the reason for the unnecessary confusing SVG inheritance structure Furthermore we explicitly

Forgot a period before "Furthermore".

> Source/WebCore/Sources.txt:2483
> +rendering/svg/RenderSVGModelObject.cpp

These additions break the sorted list.

> Source/WebCore/rendering/RenderLayerModelObject.cpp:239
> +    if (!is<RenderSVGModelObject>(*this))

Is the only time this can be hit when we deal with RenderLineBreak? If so then maybe it is nicer to add a computeVisibleRectInContainer to RenderLineBreak that skips straight to RenderObject:: computeVisibleRectInContainer and make this an ASSERT.

> Source/WebCore/rendering/RenderLayerModelObject.cpp:281
> +    if (!is<RenderSVGModelObject>(*this))

Ditto.

> Source/WebCore/rendering/svg/RenderSVGModelObject.cpp:2
> + * Copyright (c) 2009, Google Inc. All rights reserved.

Why Google and why 2009? Also if you added code (I assume you did) then maybe Igalia 2021 is in order.

> Source/WebCore/rendering/svg/RenderSVGModelObject.h:2
> + * Copyright (c) 2009, Google Inc. All rights reserved.

Ditto.
Comment 3 Nikolas Zimmermann 2021-12-21 12:37:36 PST
(In reply to Rob Buis from comment #2)
Thanks for the review!

> > Source/WebCore/ChangeLog:21
> > +        the reason for the unnecessary confusing SVG inheritance structure Furthermore we explicitly
> 
> Forgot a period before "Furthermore".
Fixed.
 
> > Source/WebCore/Sources.txt:2483
> > +rendering/svg/RenderSVGModelObject.cpp
> 
> These additions break the sorted list.
Oh, not checked by EWS apparently. Fixed.

> > Source/WebCore/rendering/RenderLayerModelObject.cpp:239
> > +    if (!is<RenderSVGModelObject>(*this))
> 
> Is the only time this can be hit when we deal with RenderLineBreak? If so
> then maybe it is nicer to add a computeVisibleRectInContainer to
> RenderLineBreak that skips straight to RenderObject::
> computeVisibleRectInContainer and make this an ASSERT.
Hmm, what's the relation to RenderLineBreak? Cannot follow you here.
In the full LBSE, only RenderSVGModelObject / RenderSVGBlock need a computeVisibleRectInContainer() implementation, and RenderLayerModelObject is the common base class for them.
 
> > Source/WebCore/rendering/RenderLayerModelObject.cpp:281
> > +    if (!is<RenderSVGModelObject>(*this))
> 
> Ditto.
Same as above, not sure what you mean.

> 
> > Source/WebCore/rendering/svg/RenderSVGModelObject.cpp:2
> > + * Copyright (c) 2009, Google Inc. All rights reserved.
> 
> Why Google and why 2009? Also if you added code (I assume you did) then
> maybe Igalia 2021 is in order.
Well that's a straight copy from LegacyRenderSVGModelObject, and I have to preserve copyright. But you're right: Igalia is missing.

> 
> > Source/WebCore/rendering/svg/RenderSVGModelObject.h:2
> > + * Copyright (c) 2009, Google Inc. All rights reserved.
> 
> Ditto.
Comment 4 Nikolas Zimmermann 2021-12-21 12:42:27 PST
Created attachment 447745 [details]
Patch, v2
Comment 5 Rob Buis 2021-12-22 01:24:07 PST
(In reply to Rob Buis from comment #2)
> Comment on attachment 447652 [details]
> > Is the only time this can be hit when we deal with RenderLineBreak? If so
> > then maybe it is nicer to add a computeVisibleRectInContainer to
> > RenderLineBreak that skips straight to RenderObject::
> > computeVisibleRectInContainer and make this an ASSERT.
> Hmm, what's the relation to RenderLineBreak? Cannot follow you here.
> In the full LBSE, only RenderSVGModelObject / RenderSVGBlock need a
> computeVisibleRectInContainer() implementation, and RenderLayerModelObject
> is the common base class for them.

computeVisibleRectInContainer is overridden in all subclasses except in RenderLineBreak. So by adding computeVisibleRectInContainer to RenderLineBreak,
RenderLayerModelObject::computeVisibleRectInContainer should only by called by SVG subclasses, so the if should be able to be converted into an ASSERT.
Comment 6 Nikolas Zimmermann 2021-12-22 05:57:54 PST
(In reply to Rob Buis from comment #5)
> (In reply to Rob Buis from comment #2)
> > Comment on attachment 447652 [details]
> > > Is the only time this can be hit when we deal with RenderLineBreak? If so
> > > then maybe it is nicer to add a computeVisibleRectInContainer to
> > > RenderLineBreak that skips straight to RenderObject::
> > > computeVisibleRectInContainer and make this an ASSERT.
> > Hmm, what's the relation to RenderLineBreak? Cannot follow you here.
> > In the full LBSE, only RenderSVGModelObject / RenderSVGBlock need a
> > computeVisibleRectInContainer() implementation, and RenderLayerModelObject
> > is the common base class for them.
> 
> computeVisibleRectInContainer is overridden in all subclasses except in
> RenderLineBreak. So by adding computeVisibleRectInContainer to
> RenderLineBreak,
> RenderLayerModelObject::computeVisibleRectInContainer should only by called
> by SVG subclasses, so the if should be able to be converted into an ASSERT.

That sounds fishy to me:

a) I would not expect a function in RenderLayerModelObject to assert that it‘s called on a RenderSVGModelObject/RenderSVGBlock only.

b) It hurting extensibility: a new HTML/CSS renderer class inheriting from RenderLayerModelObject has to implement mapLocalToContainer() and call the super-super class implementation (e.g. RenderLineBreak needs to skip RenderLayerModelObject::mapLocalToContainer()). The „short cut“ to implement the SVG-style mapLocalToContainer() implementation would affect all non-SVG callsites for no reason. 

But still you have a valid point. I propose to add only a protected mapLocalToContainerForSVG() method and not implement RenderLayerModelObject::mapLocalToContainer(). Each SVG renderers that needs mapLocalToContainer() can implement it and just call mapLocalToContainerSVG()…

What do you think?
Comment 7 Rob Buis 2021-12-22 06:23:14 PST
(In reply to Nikolas Zimmermann from comment #6)
> That sounds fishy to me:
> 
> a) I would not expect a function in RenderLayerModelObject to assert that
> it‘s called on a RenderSVGModelObject/RenderSVGBlock only.
> 
> b) It hurting extensibility: a new HTML/CSS renderer class inheriting from
> RenderLayerModelObject has to implement mapLocalToContainer() and call the
> super-super class implementation (e.g. RenderLineBreak needs to skip
> RenderLayerModelObject::mapLocalToContainer()). The „short cut“ to implement
> the SVG-style mapLocalToContainer() implementation would affect all non-SVG
> callsites for no reason. 
> 
> But still you have a valid point. I propose to add only a protected
> mapLocalToContainerForSVG() method and not implement
> RenderLayerModelObject::mapLocalToContainer(). Each SVG renderers that needs
> mapLocalToContainer() can implement it and just call
> mapLocalToContainerSVG()…
> 
> What do you think?

I was more looking at computeVisibleRectInContainer. But your suggestion sounds good to me.
Comment 8 Nikolas Zimmermann 2021-12-22 10:34:21 PST
Created attachment 447817 [details]
Patch, v3
Comment 9 Nikolas Zimmermann 2021-12-22 11:11:15 PST
Created attachment 447819 [details]
Patch, v4
Comment 10 Rob Buis 2021-12-23 01:08:42 PST
Comment on attachment 447819 [details]
Patch, v4

View in context: https://bugs.webkit.org/attachment.cgi?id=447819&action=review

> Source/WebCore/rendering/svg/RenderSVGModelObject.h:95
> +    virtual Path computeClipPath(AffineTransform&) const;

I think it is better to introduce these (RenderLayer specific) APIs when we start calling them.

> Source/WebCore/rendering/svg/RenderSVGModelObject.h:116
> +    void paintSVGOutline(PaintInfo&, const LayoutPoint& adjustedPaintOffset);

Ditto.
Comment 11 Nikolas Zimmermann 2021-12-23 02:12:18 PST
Created attachment 447866 [details]
Patch, v5
Comment 12 Nikolas Zimmermann 2021-12-23 02:12:37 PST
(In reply to Rob Buis from comment #10)
> Comment on attachment 447819 [details]
> Patch, v4
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=447819&action=review
> 
> > Source/WebCore/rendering/svg/RenderSVGModelObject.h:95
> > +    virtual Path computeClipPath(AffineTransform&) const;
> 
> I think it is better to introduce these (RenderLayer specific) APIs when we
> start calling them.
> 
> > Source/WebCore/rendering/svg/RenderSVGModelObject.h:116
> > +    void paintSVGOutline(PaintInfo&, const LayoutPoint& adjustedPaintOffset);
> 
> Ditto.

I agree with both.
Comment 13 Rob Buis 2021-12-23 02:25:27 PST
Comment on attachment 447866 [details]
Patch, v5

View in context: https://bugs.webkit.org/attachment.cgi?id=447866&action=review

Getting closer :)

> Source/WebCore/rendering/svg/RenderSVGModelObject.cpp:179
> +    auto* container = this->parent();

Probably this can be removed.

> Source/WebCore/rendering/svg/RenderSVGModelObject.cpp:212
> +    auto repaintBoundingBox = enclosingLayoutRect(this->repaintRectInLocalCoordinates());

Ditto?

> Source/WebCore/rendering/svg/RenderSVGModelObject.cpp:228
> +    if (style().visibility() == Visibility::Hidden || style().display() == DisplayType::None)

Can DisplayType::None really happen? What about display: contents?

> Source/WebCore/rendering/svg/RenderSVGModelObject.cpp:278
> +Path RenderSVGModelObject::computeClipPath(AffineTransform& transform) const

Needs to be removed.
Comment 14 Nikolas Zimmermann 2021-12-23 11:19:03 PST
Created attachment 447887 [details]
Patch, v6
Comment 15 Radar WebKit Bug Importer 2021-12-27 13:29:16 PST
<rdar://problem/86944226>
Comment 16 Nikolas Zimmermann 2022-01-03 00:17:52 PST
(In reply to Rob Buis from comment #13)
> Getting closer :)
Step by step :-)

> 
> > Source/WebCore/rendering/svg/RenderSVGModelObject.cpp:179
> > +    auto* container = this->parent();
> 
> Probably this can be removed.
Done.

> > Source/WebCore/rendering/svg/RenderSVGModelObject.cpp:212
> > +    auto repaintBoundingBox = enclosingLayoutRect(this->repaintRectInLocalCoordinates());
> 
> Ditto?
Indeed, the function call used to be named 'repaintBoundingBox' in the downstream branch, that's a left-over from renaming back to legacy nomenclature: 'repaintRectInLocalCoordinates' (to minimize patch size).
 
> > Source/WebCore/rendering/svg/RenderSVGModelObject.cpp:228
> > +    if (style().visibility() == Visibility::Hidden || style().display() == DisplayType::None)
> 
> Can DisplayType::None really happen? What about display: contents?
DisplayType::None can happen -- we create renderers for e.g. <g display="none">. No idea about "display: contents" - never used it nor thought about its usage within SVG context. That's a general issue I think, out of scope for this patch -- shouldPaintSVGRenderer() behaves the same in the legacy engine.

> Source/WebCore/rendering/svg/RenderSVGModelObject.cpp:278
> > +Path RenderSVGModelObject::computeClipPath(AffineTransform& transform) const
> 
> Needs to be removed.
Already done in patch v6, which was posted before I saw these comments.

New patch coming soon.
Comment 17 Nikolas Zimmermann 2022-01-03 00:34:53 PST
Created attachment 448214 [details]
Patch, v7
Comment 18 Rob Buis 2022-01-03 01:19:20 PST
(In reply to Nikolas Zimmermann from comment #16)
> > Can DisplayType::None really happen? What about display: contents?
> DisplayType::None can happen -- we create renderers for e.g. <g
> display="none">. No idea about "display: contents" - never used it nor
> thought about its usage within SVG context. That's a general issue I think,
> out of scope for this patch -- shouldPaintSVGRenderer() behaves the same in
> the legacy engine.

Agreed that display: contents is out of scope for this patch, we should remember to look into it at some point though.
Comment 19 Rob Buis 2022-01-03 02:05:13 PST
Comment on attachment 448214 [details]
Patch, v7

View in context: https://bugs.webkit.org/attachment.cgi?id=448214&action=review

Probably by now copyright info has to be updated to include 2022 if changes are made in the file(s).

> Source/WebCore/rendering/RenderLayerModelObject.cpp:252
> +    ASSERT_UNUSED(containerIsSkipped, !containerIsSkipped);

What is this for?

> Source/WebCore/rendering/svg/RenderSVGModelObject.cpp:64
> +    if (RenderObject::node() && is<SVGGraphicsElement>(nodeForNonAnonymous()))

Can we have anonymous nodes in SVG?

> Source/WebCore/rendering/svg/RenderSVGModelObject.cpp:107
> +    ASSERT_UNUSED(ancestorSkipped, !ancestorSkipped);

Ditto.

> Source/WebCore/rendering/svg/RenderSVGModelObject.cpp:187
> +    bool preserve3D = mode & UseTransforms && (container->style().preserves3D() || style().preserves3D());

The preserve3D checks below could be stored in a temp variable at this line, making things a bit more readable hopefully.

> Source/WebCore/rendering/svg/RenderSVGModelObject.cpp:242
> +    if (other.isEmpty() && !r.isEmpty())

Looks like r.isEmpty() is already proven to be false!
Comment 20 Nikolas Zimmermann 2022-01-03 03:30:51 PST
(In reply to Rob Buis from comment #19)
> Comment on attachment 448214 [details]
> Patch, v7
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=448214&action=review
> 
> Probably by now copyright info has to be updated to include 2022 if changes
> are made in the file(s).
Correct, done.

> 
> > Source/WebCore/rendering/RenderLayerModelObject.cpp:252
> > +    ASSERT_UNUSED(containerIsSkipped, !containerIsSkipped);
> 
> What is this for?
This is a copy of the generic computeVisibleRectInContainer() method, adapted for SVG. Since containerIsSkipped is always false in SVG content, this is assert'ed here.

> 
> > Source/WebCore/rendering/svg/RenderSVGModelObject.cpp:64
> > +    if (RenderObject::node() && is<SVGGraphicsElement>(nodeForNonAnonymous()))
> 
> Can we have anonymous nodes in SVG?
We indeed had at some point in the LBSE prototype, when I modelled SVG view box, by creating an anonymous RenderSVGViewportContainer as direct child of the RenderSVGRoot, encapsulating all SVG content. While this has some benefits, the complexity increase is not worth it, so I've abandoned this.

I'll adapt the code to remove the node() check (it would then assert in nodeForNonAnymous() when called for anonymous nodes).
 
> > Source/WebCore/rendering/svg/RenderSVGModelObject.cpp:107
> > +    ASSERT_UNUSED(ancestorSkipped, !ancestorSkipped);
> 
> Ditto.
I'd like to keep this...

> 
> > Source/WebCore/rendering/svg/RenderSVGModelObject.cpp:187
> > +    bool preserve3D = mode & UseTransforms && (container->style().preserves3D() || style().preserves3D());
> 
... and also that, since it's a 1:1 copy of the generic methods, adapted for SVG.

> The preserve3D checks below could be stored in a temp variable at this line,
> making things a bit more readable hopefully.
I agree, but maybe we'll save this for refactoring all of the preserve3D checks in the render tree?

> 
> > Source/WebCore/rendering/svg/RenderSVGModelObject.cpp:242
> > +    if (other.isEmpty() && !r.isEmpty())
> 
> Looks like r.isEmpty() is already proven to be false!
Hehe, yes, fixed.
Comment 21 Nikolas Zimmermann 2022-01-03 03:34:55 PST
Created attachment 448222 [details]
Patch, v8
Comment 22 Nikolas Zimmermann 2022-01-03 06:01:41 PST
Committed r287538 (245673@trunk): <https://commits.webkit.org/245673@trunk>
Comment 23 Nikolas Zimmermann 2022-01-03 06:11:16 PST
Thanks Rob!