Skip to content
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

Merged
merged 2 commits into from Apr 19, 2017
Merged

Conversation

canova
Copy link
Contributor

@canova canova commented Apr 2, 2017

-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.



This change is Reviewable

@canova
Copy link
Contributor Author

canova commented Apr 2, 2017

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(),
Copy link
Contributor Author

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 :(

Copy link
Contributor

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 :)

@canova
Copy link
Contributor Author

canova commented Apr 2, 2017

https://treeherder.mozilla.org/#/jobs?repo=try&revision=7dda1b604bbfda11d29b22a262b63397b383fccc
Try shows lots of passes in reftests but some mochitest failures increased probably due to serialization. I'll look closely.

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)),
Copy link
Member

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?

Copy link
Member

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.

Copy link
Contributor Author

@canova canova Apr 2, 2017

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.

Copy link
Member

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.
Copy link
Member

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

Copy link
Contributor Author

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;
Copy link
Member

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.

@Manishearth
Copy link
Member

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,
Copy link
Member

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?

Copy link
Contributor Author

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.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That looks indeed wrong, perhaps @dholbert or @heycam can confirm it? If we do that, let's just add a comment here or something.

Copy link
Member

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,
Copy link
Member

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.

Copy link
Contributor Author

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)
Copy link
Member

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 []
Copy link
Contributor

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)

Copy link
Contributor Author

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,()> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

inline? (here and below)

@highfive highfive added the S-awaiting-review There is new code that needs to be reviewed. label Apr 2, 2017
@bors-servo
Copy link
Contributor

☔ The latest upstream changes (presumably #16242) made this pull request unmergeable. Please resolve the merge conflicts.

@highfive highfive added the S-needs-rebase There are merge conflict errors. label Apr 4, 2017
@canova
Copy link
Contributor Author

canova commented Apr 8, 2017

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?

@Manishearth
Copy link
Member

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).

Copy link
Member

@Manishearth Manishearth left a 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),
Copy link
Member

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?

@bors-servo
Copy link
Contributor

☔ The latest upstream changes (presumably #16315) made this pull request unmergeable. Please resolve the merge conflicts.

@highfive highfive added the S-needs-rebase There are merge conflict errors. label Apr 10, 2017
@canova canova force-pushed the moz-transform branch 3 times, most recently from 867d0d7 to 3bd8523 Compare April 11, 2017 23:40
@bors-servo
Copy link
Contributor

☔ The latest upstream changes (presumably #16373) made this pull request unmergeable. Please resolve the merge conflicts.

@highfive highfive added the S-needs-rebase There are merge conflict errors. label Apr 12, 2017
@canova
Copy link
Contributor Author

canova commented Apr 13, 2017

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.

@Manishearth
Copy link
Member

You'll need to special case serialization here.

Copy link
Member

@Manishearth Manishearth left a 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![];
Copy link
Member

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

@canova
Copy link
Contributor Author

canova commented Apr 14, 2017

Oops, rebase fail. Will look at serialization soon.
https://treeherder.mozilla.org/#/jobs?repo=try&revision=fb1257d23b860442c3e91071de9e4c99ec4e596f

@canova
Copy link
Contributor Author

canova commented Apr 14, 2017

@canova
Copy link
Contributor Author

canova commented Apr 15, 2017

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.
https://treeherder.mozilla.org/#/jobs?repo=try&revision=380b80b0dcfac49f639a50d0b79fdf719cbe64f1

@bors-servo
Copy link
Contributor

☔ The latest upstream changes (presumably #16473) made this pull request unmergeable. Please resolve the merge conflicts.

@highfive highfive added the S-needs-rebase There are merge conflict errors. label Apr 16, 2017
Copy link
Member

@Manishearth Manishearth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

r=me

@canova
Copy link
Contributor Author

canova commented Apr 19, 2017

@bors-servo r=Manishearth

@bors-servo
Copy link
Contributor

📌 Commit f9225d8 has been approved by Manishearth

@highfive highfive added S-awaiting-merge The PR is in the process of compiling and running tests on the automated CI. and removed S-awaiting-review There is new code that needs to be reviewed. S-needs-rebase There are merge conflict errors. labels Apr 19, 2017
@bors-servo
Copy link
Contributor

⌛ Testing commit f9225d8 with merge b8b4ec9...

bors-servo pushed a commit that referenced this pull request Apr 19, 2017
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 -->
@bors-servo
Copy link
Contributor

☀️ 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
Approved by: Manishearth
Pushing b8b4ec9 to master...

@bors-servo bors-servo merged commit f9225d8 into servo:master Apr 19, 2017
@highfive highfive removed the S-awaiting-merge The PR is in the process of compiling and running tests on the automated CI. label Apr 19, 2017
@canova canova deleted the moz-transform branch April 25, 2017 20:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support parsing moz-specific matrix functions in prefixed transform property
6 participants