New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
stylo: Implement -moz-transform property #16231
Conversation
let matrix = SpecifiedMatrix { | ||
m11: values[0], m12: values[1], m13: Number::new(0.0), m14: Number::new(0.0), | ||
m21: values[2], m22: values[3], m23: Number::new(0.0), m24: Number::new(0.0), | ||
m31: Number::new(0.0), m32: Number::new(0.0), m33: Number::new(1.0), m34: Number::new(0.0), | ||
m41: values[4], m42: values[5], m43: Number::new(0.0), m44: Number::new(1.0), | ||
m41: lengths[0].clone(), m42: lengths[1].clone(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not happy with these indentations but I couldn't find a better way to indent this :(
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need to stress too much on it. NBD really :)
https://treeherder.mozilla.org/#/jobs?repo=try&revision=7dda1b604bbfda11d29b22a262b63397b383fccc |
m41: self.m41.to_computed_value(context), | ||
m42: self.m42.to_computed_value(context), | ||
m43: self.m43.to_computed_value(context), | ||
m41: length_to_computed_number(self.m41.to_computed_value(context)), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, we need to keep these as LoPoN, no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why? That's the computed value form.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, length values are getting normalized into numbers during computed value conversion. See:
data:text/html,<script>var div = document.createElement('div');div.style.MozTransform = "matrix(1, 1, 1, 1, 40px, 120px)";alert("Specified: " + div.style.MozTransform);alert("Computed: " + window.getComputedStyle(div).MozTransform);</script>
Otherwise interpolation algorithm would fail.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We already allow percentages in translate
; these are resolved against the refbox in layout time. Interpolation fails for us here, and gecko uses interpolatematrix to handle these -- it defers interpolation till layout time. This is an independent issue we need to fix.
Yes, lengths can map to numbers by pixel value here, but percentages do not map.
(I think I've mentioned it before -- I'm quite annoyed that the spec doesn't really specify units here, but to be 100% correct, the homogeneous coordinates in the matrix should be in units of pixel, and the rest are unitless ratios, but it implicitly expects us to convert the ratio to pixels of the same numeric value)
@@ -577,6 +573,12 @@ impl ShorthandId { | |||
None => return None | |||
}; | |||
|
|||
// Alias shorthand properties like -moz-transform should not be | |||
// serialized as shothand. They will be serialized as londhand. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
spelling of shorthand and longhand
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops, will fix that :)
// Alias shorthand properties like -moz-transform should not be | ||
// serialized as shothand. They will be serialized as londhand. | ||
if self.flags().contains(ALIAS_PROPERTY) { | ||
return None; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that you still want it to work if someone asks for -moz-transform
to be serialized. I suspect this is the cause of most of the test failures.
Where are the LoPoN values computed to numbers? In gecko, specified and computed transform are the same. |
Either::First(length) => { | ||
match length { | ||
computed::LengthOrPercentage::Length(len) => (len.0 / 60) as CSSFloat, | ||
computed::LengthOrPercentage::Percentage(percentage) => percentage, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That being said, I don't think this is right, is it? What are percentages resolved against?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like gecko is convert to number while computing but doesn't serialize it.
See with and without percentage value in this example, it's same:
<!DOCTYPE html>
<style>
div {
width: 100px;
height: 100px;
background-color: red;
-moz-transform: matrix(1, 0.3, 0, 1, 500%, 0);
}
</style>
<div></div>
Probably this is a gecko bug.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suspect that's a serialization bug, not how it's actually treated. again, translate takes percentages, and they get resolved at use time, which leads to a bunch of interpolation headaches.
match value { | ||
Either::First(length) => { | ||
match length { | ||
computed::LengthOrPercentage::Length(len) => (len.0 / 60) as CSSFloat, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's Au::to_f32_px
iirc, or at least the AU_PER_PX constant that you can use instead of the magic value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, that's better. I'll change that. Thanks!
computed::LengthOrPercentage::Length(len) => (len.0 / 60) as CSSFloat, | ||
computed::LengthOrPercentage::Percentage(percentage) => percentage, | ||
computed::LengthOrPercentage::Calc(calc) => { | ||
(calc.length.0 / 60) as CSSFloat + calc.percentage.unwrap_or(0.0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here re. 60, and percentage resolution doesn't really seem right.
self.creates_stacking_context = arg_to_bool(creates_stacking_context) | ||
self.fixpos_cb = arg_to_bool(fixpos_cb) | ||
self.abspos_cb = arg_to_bool(abspos_cb) | ||
self.flags = flags.split() if flags else [] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: flags = []
in the function definition?
(I'm not sure why we have this tradition of default'ing all the arguments to None
in the function definition and change them here)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, when I try to default flags argument to []
, python gives an AttributeError that tells split is not an attribute of list
.
@@ -1619,6 +1673,17 @@ ${helpers.predefined_type("scroll-snap-coordinate", | |||
} | |||
} | |||
|
|||
/// Parses `transform` property. | |||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
inline? (here and below)
☔ The latest upstream changes (presumably #16242) made this pull request unmergeable. Please resolve the merge conflicts. |
Updated the PR, now it also stores the percentage forms in computed value and passes to gecko side. But still I need to test this and do another pass on the code to see if I can change some parts with a better way. Also I had to create a new amended commit instead of fixup commits because of huge conflicts. That will make hard to review, sorry about that :/ Btw, do we want -moz-transform in Servo? |
I am ambivalent on -moz-transform being in Servo, do whichever is easier. It is probably harder to add servo support since this needs extra layout tweaks (not much though). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So overall this approach is on the right track, but we have some issues which I hadn't realized initially.
Firstly, we got the parsing wrong. Probably my fault, I think I misread the original code. For prefixed matrix, the last two elements can be length, percentage, number, or calc. For prefixed matrix3d, fourth from last and third from last is l/p/n/calc. Second from last is length/number/calc, not percentage (it's in the z-direction, percentage can't apply in that direction because there's no z-direction to the reference box).
We can resolve lengths to their Au values as Numbers whilst computing (or leave them as Au). Percentages must stay put; .value()
is not something we should be calling here. During layout time, the first percentage will be resolved against width, and the second against height -- see what Translate
does in fragment.rs
. I am not sure how to deal with calcs, we can leave them as calcs I guess and let layout resolution deal with it. I suspect the best approach here is to compute the LoNs (parsed as LoNoC) as L (Au), and the LoPoNs (parsed as LoPoN) as LoP. However, this may need special handling to handle unitless calcs. This can be a followup, I don't think we really care about unitless calcs in -moz-transform
that much. I can expand on what the issue here is if you want, though.
I think we need to stop using ComputedMatrix
for computed prefixed matrices. Ignore animation for now, let animation fail for these -- the interpolatematrix approach is what we need to use here.
Instead, have a separate PrefixedMatrix variant that uses a struct similar to ComputedMatrix
(ComputedMatrixWithPercents
?) that holds number or percentage in the xy homogeneous slots. This can be resolved to a ComputedMatrix
given a refbox width and height, and use that in layout. Again, we're ignoring animation for now, prefixed matrices can't be animated without interpolatematrix (which I can help you work on next if you have time, see bug 1335998!)
It is also okay to use the same matrix variant for prefixed and uprefixed, and have them all use the same ComputedMatrixWithPercents
type. This just means animation code has to be tweaked a bit to attempt to convert the matrix into one with pure numbers provided it doesn't contain percents. Use whichever approach you prefer!
)}; | ||
% if item == "number_percentage": | ||
${css_value_setters[item] % ( | ||
"bindings::Gecko_CSSValue_GetArrayItem(gecko_value, %d)" % (index + 1), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should be number OR percentage, not AND, no?
☔ The latest upstream changes (presumably #16315) made this pull request unmergeable. Please resolve the merge conflicts. |
867d0d7
to
3bd8523
Compare
☔ The latest upstream changes (presumably #16373) made this pull request unmergeable. Please resolve the merge conflicts. |
It works in stylo currently but I have problem with serialization. It serializes transform property as -moz-transform. I need to find a way to workaround that. |
You'll need to special case serialization here. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks correct. I think you still need to fix the case where we explicitly ask for serialization.
https://treeherder.mozilla.org/#/jobs?repo=try&revision=24a503ecb5367d0c693312d7d2909f8b08ecdde3
// | ||
// -moz-transform accepts LengthOrPercentageOrNumber in the | ||
// nondiagonal homogeneous components. transform accepts only number. | ||
let mut values = vec![]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use Vec::with_capacity(4)
and 2
Oops, rebase fail. Will look at serialization soon. |
Ok, solved the serialization problem with that fixup commit. I wanted to solve it with mako code generation but couldn't. That works, but maybe we can do better. |
☔ The latest upstream changes (presumably #16473) made this pull request unmergeable. Please resolve the merge conflicts. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
r=me
@bors-servo r=Manishearth |
📌 Commit f9225d8 has been approved by |
stylo: Implement -moz-transform property -moz-transform property is an alias shorthand property. It has transform as sub-property but their parsing is different in some cases(matrix/matrix3d). -moz-transform also accepts LengthOrPercentage in the nondiagonal homogeneous components of matrix and matrix3d. It looks like length and percentage values are getting computed to number directly. For example 120px converts into 120 and calc(120px + 20%) converts into 140. So I did like this. But we need to check this behavior again to be sure, I guess. Also I spent half day investigating why matrices are not serializing after this change and found out their ToCss functions is not completely implemented yet 😄 I was going to implement them but there is an easy issue about it(#15194) so I left it that way. Probably all tests won't pass without it. --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors - [X] These changes fix #16003 and [Bug 1351356](https://bugzilla.mozilla.org/show_bug.cgi?id=1351356) <!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.--> <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/16231) <!-- Reviewable:end -->
☀️ Test successful - android, arm32, arm64, linux-dev, linux-rel-css, linux-rel-wpt, mac-dev-unit, mac-rel-css, mac-rel-wpt1, mac-rel-wpt2, windows-msvc-dev |
-moz-transform property is an alias shorthand property. It has transform as sub-property but their parsing is different in some cases(matrix/matrix3d). -moz-transform also accepts LengthOrPercentage in the nondiagonal homogeneous components of matrix and matrix3d.
It looks like length and percentage values are getting computed to number directly. For example 120px converts into 120 and calc(120px + 20%) converts into 140. So I did like this. But we need to check this behavior again to be sure, I guess.
Also I spent half day investigating why matrices are not serializing after this change and found out their ToCss functions is not completely implemented yet 😄 I was going to implement them but there is an easy issue about it(#15194) so I left it that way. Probably all tests won't pass without it.
./mach build -d
does not report any errors./mach test-tidy
does not report any errorsThis change is