WebKit Bugzilla
New
Browse
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
RESOLVED FIXED
133543
[CSS Grid Layout] Simplify the named grid lines resolution algorithm
https://bugs.webkit.org/show_bug.cgi?id=133543
Summary
[CSS Grid Layout] Simplify the named grid lines resolution algorithm
Sergio Villar Senin
Reported
2014-06-05 03:00:52 PDT
The support for placing grid items using named grid lines was added in
r164869
and later improved in
r166299
. Despite being correct the code turned out to be quite complex. It's difficult to understand and maintain. It can be heavily simplified if we previously insert the implicit named grid lines generated by grid areas into the list of user-defined named grid lines. If we do that we could directly apply the algorithm described in the spec
http://dev.w3.org/csswg/css-grid/#grid-placement-slot
As a nice side effect, we'll get for free the use case specified in section "5.2.2 Implicit Named Areas", i.e., explicitly adding named lines of the form (foo-start/foo-end) will effectively create a named grid area.
Attachments
Patch
(30.92 KB, patch)
2014-06-05 04:03 PDT
,
Sergio Villar Senin
no flags
Details
Formatted Diff
Diff
Patch
(32.51 KB, patch)
2014-06-05 09:54 PDT
,
Sergio Villar Senin
darin
: review+
Details
Formatted Diff
Diff
Show Obsolete
(1)
View All
Add attachment
proposed patch, testcase, etc.
Sergio Villar Senin
Comment 1
2014-06-05 04:03:46 PDT
Created
attachment 232536
[details]
Patch
Radu Stavila
Comment 2
2014-06-05 05:40:03 PDT
Comment on
attachment 232536
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=232536&action=review
> Source/WebCore/css/StyleResolver.cpp:2684 > + if (!namedGridAreas.isEmpty())
I don't think this condition is necessary. It would be faster to just let it through with the call to createImplicitNamedGridLinesFromGridArea, as it won't fork the code path and it would return immediately anyway.
> Source/WebCore/css/StyleResolver.cpp:2711 > + if (!namedGridAreas.isEmpty())
Ditto.
> Source/WebCore/rendering/RenderGrid.cpp:868 > + return lineName + ((side == ColumnStartSide || side == RowStartSide) ? "-start" : "-end");
For consistency, I think you should add an isStartSide(GridPositionSide) method, similar to isColumnSide.
> Source/WebCore/rendering/RenderGrid.cpp:980 > + // First attempt to match the grid areaâs edge to a named grid area: if there is a named line with the name
"â" character instead of ' It shows up multiple times in the comments.
Sergio Villar Senin
Comment 3
2014-06-05 09:44:20 PDT
Thanks for the review. (In reply to
comment #2
)
> (From update of
attachment 232536
[details]
) > View in context:
https://bugs.webkit.org/attachment.cgi?id=232536&action=review
> > > Source/WebCore/css/StyleResolver.cpp:2684 > > + if (!namedGridAreas.isEmpty()) > > I don't think this condition is necessary. It would be faster to just let it through with the call to createImplicitNamedGridLinesFromGridArea, as it won't fork the code path and it would return immediately anyway.
I am not sure that is true, I don't think there is a unique answer for that as it depends a lot on the branch-prediction features of the CPU architecture and so on.
> > Source/WebCore/rendering/RenderGrid.cpp:868 > > + return lineName + ((side == ColumnStartSide || side == RowStartSide) ? "-start" : "-end"); > > For consistency, I think you should add an isStartSide(GridPositionSide) method, similar to isColumnSide.
Good point.
> > Source/WebCore/rendering/RenderGrid.cpp:980 > > + // First attempt to match the grid areaâs edge to a named grid area: if there is a named line with the name > > "â" character instead of ' > > It shows up multiple times in the comments.
Weird likely some issue copy-pasting. I'll fix that.
Sergio Villar Senin
Comment 4
2014-06-05 09:54:37 PDT
Created
attachment 232559
[details]
Patch
Darin Adler
Comment 5
2014-06-05 10:08:48 PDT
Comment on
attachment 232559
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=232559&action=review
I’ll say review+, but the use of a vector and a std::sort each time we add something is definitely not the right data structure / algorithm choice.
> Source/WebCore/css/StyleResolver.cpp:1862 > + for (auto it = namedGridAreas.begin(), end = namedGridAreas.end(); it != end; ++it) {
This should use a modern for loop: for (auto& area : namedGridAreas) Then below instead of "it->" it would be "area."
> Source/WebCore/css/StyleResolver.cpp:1868 > + { > + NamedGridLinesMap::AddResult startResult = namedGridLines.add(it->key + "-start", Vector<size_t>()); > + startResult.iterator->value.append(areaSpan.initialPositionIndex); > + std::sort(startResult.iterator->value.begin(), startResult.iterator->value.end()); > + }
This code only uses the value, so I would write more like this: auto& startVector = namedGridLines.add(it->key + "-start", Vector<size_t>()).iterator->value; startVector.append(areaSpan.initialPositionIndex); std::sort(vector.begin(), vector.end()); But also, to keep a vector sorted, it is *not* efficient to use keep adding items to the end and then doing a std::sort on the whole vector each time. There are webpages telling you not to do this, such as <
http://stackoverflow.com/questions/2710221/is-there-a-sorted-vector-class-which-supports-insert-etc
>. Please rethink the data structure here. I also don’t understand the reason for the use of size_t for this. Is it the size of some memory object? If not, then it should be some other type, maybe unsigned or even uint64_t.
> Source/WebCore/css/StyleResolver.cpp:1873 > + { > + NamedGridLinesMap::AddResult endResult = namedGridLines.add(it->key + "-end", Vector<size_t>()); > + endResult.iterator->value.append(areaSpan.finalPositionIndex + 1); > + std::sort(endResult.iterator->value.begin(), endResult.iterator->value.end()); > + }
Same comment again.
> Source/WebCore/css/StyleResolver.cpp:2776 > + NamedGridLinesMap namedGridColumnLines = state.style()->namedGridColumnLines(); > + NamedGridLinesMap namedGridRowLines = state.style()->namedGridRowLines();
This looks kind of expensive. Do we really want to copy hash maps here?
> Source/WebCore/rendering/RenderGrid.cpp:988 > + const String namedGridLine = position.namedGridLine();
Not sure why this is "const String" instead of just String.
> Source/WebCore/rendering/RenderGrid.cpp:992 > + auto implicitLineIter = gridLineNames.find(implicitNamedGridLineForSide(namedGridLine, side));
The use of "xxxIter" here is not a normal naming style we use in WebKit. I think you could just leave off the Iter suffix, or use the entire word Iterator, or think of another way to name it.
Darin Adler
Comment 6
2014-06-05 10:10:08 PDT
For example, if the only reason for sorting is that we always want to be able to find the first item, then what we want is a heap, and STL has heap algorithms for us to use to maintain the heap (std::push_heap and friends).
Sergio Villar Senin
Comment 7
2014-06-05 10:31:34 PDT
(In reply to
comment #5
)
> (From update of
attachment 232559
[details]
) > View in context:
https://bugs.webkit.org/attachment.cgi?id=232559&action=review
> > I’ll say review+, but the use of a vector and a std::sort each time we add something is definitely not the right data structure / algorithm choice. > > > Source/WebCore/css/StyleResolver.cpp:1862 > > + for (auto it = namedGridAreas.begin(), end = namedGridAreas.end(); it != end; ++it) { > > This should use a modern for loop: > > for (auto& area : namedGridAreas) > > Then below instead of "it->" it would be "area."
I had thought about that but I needed both the key and the value and I didn't remember the KeyValuePair thing :)
> > Source/WebCore/css/StyleResolver.cpp:1868 > > + { > > + NamedGridLinesMap::AddResult startResult = namedGridLines.add(it->key + "-start", Vector<size_t>()); > > + startResult.iterator->value.append(areaSpan.initialPositionIndex); > > + std::sort(startResult.iterator->value.begin(), startResult.iterator->value.end()); > > + } > > This code only uses the value, so I would write more like this: > > auto& startVector = namedGridLines.add(it->key + "-start", Vector<size_t>()).iterator->value; > startVector.append(areaSpan.initialPositionIndex); > std::sort(vector.begin(), vector.end()); > > But also, to keep a vector sorted, it is *not* efficient to use keep adding items to the end and then doing a std::sort on the whole vector each time. There are webpages telling you not to do this, such as <
http://stackoverflow.com/questions/2710221/is-there-a-sorted-vector-class-which-supports-insert-etc
>. Please rethink the data structure here.
I know, ideally we'd be using a std::set but std:: data types are not allowed in the project, aren't they?
> I also don’t understand the reason for the use of size_t for this. Is it the size of some memory object? If not, then it should be some other type, maybe unsigned or even uint64_t.
It's just an index, as we don't expect grids to be extremely huge I guess it would be more than enough to have an unsigned there, but I'd change it in a different patch.
> > Source/WebCore/css/StyleResolver.cpp:1873 > > + { > > + NamedGridLinesMap::AddResult endResult = namedGridLines.add(it->key + "-end", Vector<size_t>()); > > + endResult.iterator->value.append(areaSpan.finalPositionIndex + 1); > > + std::sort(endResult.iterator->value.begin(), endResult.iterator->value.end()); > > + } > > Same comment again. > > > Source/WebCore/css/StyleResolver.cpp:2776 > > + NamedGridLinesMap namedGridColumnLines = state.style()->namedGridColumnLines(); > > + NamedGridLinesMap namedGridRowLines = state.style()->namedGridRowLines(); > > This looks kind of expensive. Do we really want to copy hash maps here?
No, we don't but the style returns a const reference, so there is no other way to change it than to do a copy+set() unless we add something like mutableNamedGridColumnLines(). I thought about that but there is only one method in the whole RenderStyle like that, so it seems that is really uncommon.
> > Source/WebCore/rendering/RenderGrid.cpp:988 > > + const String namedGridLine = position.namedGridLine(); > > Not sure why this is "const String" instead of just String.
No particular reason.
> > Source/WebCore/rendering/RenderGrid.cpp:992 > > + auto implicitLineIter = gridLineNames.find(implicitNamedGridLineForSide(namedGridLine, side)); > > The use of "xxxIter" here is not a normal naming style we use in WebKit. I think you could just leave off the Iter suffix, or use the entire word Iterator, or think of another way to name it.
Will change that.
Sergio Villar Senin
Comment 8
2014-06-05 10:51:04 PDT
(In reply to
comment #6
)
> For example, if the only reason for sorting is that we always want to be able to find the first item, then what we want is a heap, and STL has heap algorithms for us to use to maintain the heap (std::push_heap and friends).
Unfortunately that's not the case. We need to keep all the indexes sorted. Another option could be to perform all the insertions and then in another loop do a single sort per vector. In any case, although I totally agree that the usage is not correct, in practice those vectors won't be very bug I'd say.
Sergio Villar Senin
Comment 9
2014-06-10 02:15:42 PDT
Comment on
attachment 232559
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=232559&action=review
>>> Source/WebCore/css/StyleResolver.cpp:1868 >>> + } >> >> This code only uses the value, so I would write more like this: >> >> auto& startVector = namedGridLines.add(it->key + "-start", Vector<size_t>()).iterator->value; >> startVector.append(areaSpan.initialPositionIndex); >> std::sort(vector.begin(), vector.end()); >> >> But also, to keep a vector sorted, it is *not* efficient to use keep adding items to the end and then doing a std::sort on the whole vector each time. There are webpages telling you not to do this, such as <
http://stackoverflow.com/questions/2710221/is-there-a-sorted-vector-class-which-supports-insert-etc
>. Please rethink the data structure here. >> >> I also don’t understand the reason for the use of size_t for this. Is it the size of some memory object? If not, then it should be some other type, maybe unsigned or even uint64_t. > > I know, ideally we'd be using a std::set but std:: data types are not allowed in the project, aren't they?
Also note that we only insert 1 item and sort each vector once. As we iterate over grid areas with different names, we'll be accessing different vectors all the time.
Sergio Villar Senin
Comment 10
2014-06-10 03:24:52 PDT
Committed
r169744
: <
http://trac.webkit.org/changeset/169744
>
Note
You need to
log in
before you can comment on or make changes to this bug.
Top of Page
Format For Printing
XML
Clone This Bug