Bug 161371 - More refactoring of RenderMathMLScripts
Summary: More refactoring of RenderMathMLScripts
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: MathML (show other bugs)
Version: WebKit Nightly Build
Hardware: All All
: P2 Normal
Assignee: Frédéric Wang (:fredw)
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2016-08-30 00:23 PDT by Frédéric Wang (:fredw)
Modified: 2016-09-05 02:21 PDT (History)
7 users (show)

See Also:


Attachments
Patch (33.57 KB, patch)
2016-08-30 01:44 PDT, Frédéric Wang (:fredw)
darin: review+
Details | Formatted Diff | Diff
Patch (34.18 KB, patch)
2016-09-05 01:42 PDT, Frédéric Wang (:fredw)
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Frédéric Wang (:fredw) 2016-08-30 00:23:52 PDT
- Make clear that getBaseAndScripts verify the validity, store reference children into a struct and improve the browsing of the child list.
- Split getScriptMetricsAndLayoutIfNeeded into three separate parts (see bug 161084 comment 4)
Comment 1 Frédéric Wang (:fredw) 2016-08-30 01:44:37 PDT
Created attachment 287379 [details]
Patch
Comment 2 Javier Fernandez 2016-08-30 14:49:10 PDT
Comment on attachment 287379 [details]
Patch

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

> Source/WebCore/rendering/mathml/RenderMathMLScripts.cpp:179
> +    if (!validateAndGetReferenceChildren(reference))

We only use this method to create a valid instance of ReferenceChildren. Why not just define the typical "create" function, which returns a pointer ? In case of no valid reference, then we will just get nullptr.

> Source/WebCore/rendering/mathml/RenderMathMLScripts.cpp:222
> +RenderMathMLScripts::VerticalParameters RenderMathMLScripts::verticalParameters() const

do you need the class name in the return type ?

> Source/WebCore/rendering/mathml/RenderMathMLScripts.cpp:224
> +    VerticalParameters parameters;

The lines to get each parameter are indeed too long, but perhaps you can find a way to implement it clear and use static initializers, like this:

return { baseAscent, baseDescent, ... }

> Source/WebCore/rendering/mathml/RenderMathMLScripts.cpp:251
> +    VerticalParameters parameters = verticalParameters();

Ditto.

> Source/WebCore/rendering/mathml/RenderMathMLScripts.cpp:303
> +        auto subScript = reference.firstPostScript;

suggestion: why not in a  single line ? 

   auto subscript = reference.firstPostScript ? reference.firstPostScript : reference.firstPreScript;

> Source/WebCore/rendering/mathml/RenderMathMLScripts.cpp:356
> +    if (!validateAndGetReferenceChildren(reference)) {

Ditto.
Comment 3 Frédéric Wang (:fredw) 2016-08-30 15:15:30 PDT
Comment on attachment 287379 [details]
Patch

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

>> Source/WebCore/rendering/mathml/RenderMathMLScripts.cpp:179
>> +    if (!validateAndGetReferenceChildren(reference))
> 
> We only use this method to create a valid instance of ReferenceChildren. Why not just define the typical "create" function, which returns a pointer ? In case of no valid reference, then we will just get nullptr.

So I believe the idea would be to return an Optional<ReferenceChildren> where Nullopt means a failure. I considered that but then validateAndGetReferenceChildren needed a bit more refactoring and that made the use of "reference" elsewhere more verbose, so I suspected it would complicate the readability/review.

>> Source/WebCore/rendering/mathml/RenderMathMLScripts.cpp:222
>> +RenderMathMLScripts::VerticalParameters RenderMathMLScripts::verticalParameters() const
> 
> do you need the class name in the return type ?

Yes.

>> Source/WebCore/rendering/mathml/RenderMathMLScripts.cpp:224
>> +    VerticalParameters parameters;
> 
> The lines to get each parameter are indeed too long, but perhaps you can find a way to implement it clear and use static initializers, like this:
> 
> return { baseAscent, baseDescent, ... }

Not sure this will work very well here.

>> Source/WebCore/rendering/mathml/RenderMathMLScripts.cpp:251
>> +    VerticalParameters parameters = verticalParameters();
> 
> Ditto.

I guess you mean initializing the VerticalMetrics below with { 0, 0, 0, 0 }?

>> Source/WebCore/rendering/mathml/RenderMathMLScripts.cpp:303
>> +        auto subScript = reference.firstPostScript;
> 
> suggestion: why not in a  single line ? 
> 
>    auto subscript = reference.firstPostScript ? reference.firstPostScript : reference.firstPreScript;

Yes I can do that, thanks for the suggestion.
Comment 4 Darin Adler 2016-09-03 12:56:45 PDT
Comment on attachment 287379 [details]
Patch

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

>>> Source/WebCore/rendering/mathml/RenderMathMLScripts.cpp:179
>>> +    if (!validateAndGetReferenceChildren(reference))
>> 
>> We only use this method to create a valid instance of ReferenceChildren. Why not just define the typical "create" function, which returns a pointer ? In case of no valid reference, then we will just get nullptr.
> 
> So I believe the idea would be to return an Optional<ReferenceChildren> where Nullopt means a failure. I considered that but then validateAndGetReferenceChildren needed a bit more refactoring and that made the use of "reference" elsewhere more verbose, so I suspected it would complicate the readability/review.

You can write it like this:

    auto possibleReference = validateAndGetReferenceChildren();
    if (!possibleReference)
        return;
    auto& reference = possibleReference.value();

There is no need to make the code below more verbose. The only annoying thing is the need to have two different names for the local variable. I think the idea is a good one. We should move away from out arguments and also move away from function interfaces where we return multiple independent values, but you should not look at one based on the other.

>>> Source/WebCore/rendering/mathml/RenderMathMLScripts.cpp:222
>>> +RenderMathMLScripts::VerticalParameters RenderMathMLScripts::verticalParameters() const
>> 
>> do you need the class name in the return type ?
> 
> Yes.

If you want to avoid it you can use the "auto" syntax:

    auto RenderMathMLScripts::verticalParameters() const -> VerticalParameters

>>> Source/WebCore/rendering/mathml/RenderMathMLScripts.cpp:224
>>> +    VerticalParameters parameters;
>> 
>> The lines to get each parameter are indeed too long, but perhaps you can find a way to implement it clear and use static initializers, like this:
>> 
>> return { baseAscent, baseDescent, ... }
> 
> Not sure this will work very well here.

I think it’s worth, at some point, investigating alternate coding patterns. It’s not great to have all this boilerplate code.

> Source/WebCore/rendering/mathml/RenderMathMLScripts.cpp:257
> +    VerticalMetrics metrics;
> +    metrics.subShift = 0;
> +    metrics.supShift = 0;
> +    metrics.descent = 0;
> +    metrics.ascent = 0;

Yes, = { 0, 0, 0, 0 } would be very nice here.

> Source/WebCore/rendering/mathml/RenderMathMLScripts.cpp:284
> +        LayoutUnit subAscent = ascentForChild(*reference.firstPostScript);
> +        LayoutUnit subDescent = reference.firstPostScript->logicalHeight() - subAscent;

I like auto better than LayoutUnit for these.

> Source/WebCore/rendering/mathml/RenderMathMLScripts.cpp:292
> +        LayoutUnit supAscent = ascentForChild(*reference.firstPostScript);
> +        LayoutUnit supDescent = reference.firstPostScript->logicalHeight() - supAscent;

And these. And lots more places below. Not sure everyone agrees though.

>> Source/WebCore/rendering/mathml/RenderMathMLScripts.cpp:356
>> +    if (!validateAndGetReferenceChildren(reference)) {
> 
> Ditto.

I agree that the Optional trick would be cleaner here.

> Source/WebCore/rendering/mathml/RenderMathMLScripts.h:61
> +    struct ReferenceChildren {
> +        RenderBox* base;
> +        RenderBox* prescriptDelimiter;
> +        RenderBox* firstPostScript;
> +        RenderBox* firstPreScript;
> +    };

This struct doesn’t have to be in the header. It can be forward declared here in the class definition:

    struct ReferenceChildren;

And then in the .cpp file:

    struct RenderMathMLScripts::ReferenceChildren {
        ...
    };

As long as the code here simply declares functions using the type and doesn’t actually contain code that uses the type, which is the case here.

> Source/WebCore/rendering/mathml/RenderMathMLScripts.h:74
> +    struct VerticalParameters {
> +        LayoutUnit subscriptShiftDown;
> +        LayoutUnit superscriptShiftUp;
> +        LayoutUnit subscriptBaselineDropMin;
> +        LayoutUnit superScriptBaselineDropMax;
> +        LayoutUnit subSuperscriptGapMin;
> +        LayoutUnit superscriptBottomMin;
> +        LayoutUnit subscriptTopMax;
> +        LayoutUnit superscriptBottomMaxWithSubscript;
> +    };

Same thing here.

> Source/WebCore/rendering/mathml/RenderMathMLScripts.h:81
> +    struct VerticalMetrics {
>          LayoutUnit subShift;
>          LayoutUnit supShift;
>          LayoutUnit ascent;
>          LayoutUnit descent;
>      };

Same thing here.
Comment 5 Frédéric Wang (:fredw) 2016-09-05 01:42:47 PDT
Created attachment 287941 [details]
Patch

> The lines to get each parameter are indeed too long, but perhaps you can find a way to implement it clear and use static initializers, like this:
> I like auto better than LayoutUnit for these.
> This struct doesn’t have to be in the header.

The changeset of this patch is already big, these three points are not specific to scripts and should be considered for other MathML classes too and I won't be able to come back to this soon. So I'll leave them for another patch.
Comment 6 Frédéric Wang (:fredw) 2016-09-05 02:21:51 PDT
Committed r205441: <http://trac.webkit.org/changeset/205441>