Closed Bug 594935 Opened 14 years ago Closed 12 years ago

support calc() on gradient stop positions

Categories

(Core :: CSS Parsing and Computation, defect)

defect
Not set
normal

Tracking

()

RESOLVED FIXED
mozilla18

People

(Reporter: dbaron, Assigned: thomas)

References

(Blocks 1 open bug)

Details

(Keywords: css3, dev-doc-complete)

Attachments

(2 files, 8 obsolete files)

We might want to support calc() on the gradient stop positions in the -moz-*-gradient functions in the background-image property.  (This is different from the gradient endpoint positions, which are covered in bug 594934.)

This is work that I did not do in bug 363249 / bug 585715, and am not currently planning to do for Mozilla 2 / Firefox 4.
Btw, in case you need a use case for this, it's extremely useful when mixing percentages with absolute units in color stop positions. For example, you want to make a middle stripe with thickness 1in regardless of container size. The gradient for that would be 

linear-gradient(white calc(50%-.5in), red calc(50%-.5in), red calc(50%+.5in), white calc(50%+.5in))

I'm pretty sure there are similar cases with "normal" gradients too, but this is the case that usually has me wishing for calc() in color stop positions.
Minimal testcase containing one div using calc() and another using pixels. Both should look identical once calc() is allowed.
Attachment #597563 - Attachment is obsolete: true
Attachment #597565 - Attachment mime type: text/plain → text/html
Assignee: nobody → thomas
(In reply to Brandon Frohs from comment #4)
> Created attachment 597565 [details]
> Testcase showing 2 divs (1 using calc(), 1 using px) (should look identical)

Testcase need to remove "45deg, " in order to look identical. Since, "div#two" have no "45deg, " style sheet.
Testcase showing 2 divs (1 using calc(), 1 using px) (should look identical). Update testcase remove "45deg" from style sheet
Attachment #597565 - Attachment is obsolete: true
1. Handle eStyleUnit_Calc type in nsCSSRendering::PaintGradient
2. Add VARIANT_CALC to ParseVariant @ CSSParserImpl::ParseColorStop
3. Add SETCOORD_STORE_CALC to SetCoord @ SetGradient
4. Update comment @ layout/style/nsStyleStruct.h
Attachment #662544 - Flags: review?(bzbarsky)
1. Handle eStyleUnit_Calc type in nsCSSRendering::PaintGradient
2. Add VARIANT_CALC to ParseVariant @ CSSParserImpl::ParseColorStop
3. Add SETCOORD_STORE_CALC to SetCoord @ SetGradient
4. Update comment @ layout/style/nsStyleStruct.h
Attachment #662544 - Attachment is obsolete: true
Attachment #662544 - Flags: review?(bzbarsky)
Attachment #662614 - Flags: review?(bzbarsky)
Comment on attachment 662614 [details] [diff] [review]
Add calc to parser and do calc in PaintGradient

>diff --git a/layout/base/nsCSSRendering.cpp b/layout/base/nsCSSRendering.cpp
>--- a/layout/base/nsCSSRendering.cpp
>+++ b/layout/base/nsCSSRendering.cpp
>@@ -2041,6 +2041,7 @@
>     for (uint32_t i = 0; i < aGradient->mStops.Length(); ++i) {
>       const nsStyleGradientStop& stop = aGradient->mStops[i];
>       double position;
>+      nsStyleCoord::Calc *calc;
>       switch (stop.mLocation.GetUnit()) {
>       case eStyleUnit_None:
>         if (i == 0) {

Instead of declaring variables outside the switch, put {} inside the case, like here:
http://hg.mozilla.org/mozilla-central/file/0c8ac138706e/layout/style/nsStyleAnimation.cpp#l390

>@@ -2068,6 +2069,11 @@
>         position = lineLength < 1e-6 ? 0.0 :
>             stop.mLocation.GetCoordValue() / appUnitsPerPixel / lineLength;
>         break;
>+      case eStyleUnit_Calc:
>+        calc = stop.mLocation.GetCalcValue();
>+        position = calc->mPercent +
>+            NSAppUnitsToFloatPixels(calc->mLength, appUnitsPerPixel) / lineLength;
>+        break;

This presumably needs the same test of lineLength being very small that the eStyleUnit_Percent case has.

(It might also be worth sharing the code if you can see a good way to do it, but I don't.)

You should also add tests to layout/style/test/property_database.js (where there are other gradient tests), and make sure that the mochitests in layout/style/ still pass after you do.
Attached patch Update acorrding to Comment 9 (obsolete) — Splinter Review
Add tests to layout/style/test/property_database.js
Attachment #662614 - Attachment is obsolete: true
Attachment #662614 - Flags: review?(bzbarsky)
Attachment #662791 - Flags: review?(bzbarsky)
(In reply to David Baron [:dbaron] from comment #9)
> Comment on attachment 662614 [details] [diff] [review]
> Add calc to parser and do calc in PaintGradient
> 
> >diff --git a/layout/base/nsCSSRendering.cpp b/layout/base/nsCSSRendering.cpp
> >--- a/layout/base/nsCSSRendering.cpp
> >+++ b/layout/base/nsCSSRendering.cpp
> >@@ -2041,6 +2041,7 @@
> >     for (uint32_t i = 0; i < aGradient->mStops.Length(); ++i) {
> >       const nsStyleGradientStop& stop = aGradient->mStops[i];
> >       double position;
> >+      nsStyleCoord::Calc *calc;
> >       switch (stop.mLocation.GetUnit()) {
> >       case eStyleUnit_None:
> >         if (i == 0) {
> 
> Instead of declaring variables outside the switch, put {} inside the case,
> like here:
> http://hg.mozilla.org/mozilla-central/file/0c8ac138706e/layout/style/
> nsStyleAnimation.cpp#l390
> 
> >@@ -2068,6 +2069,11 @@
> >         position = lineLength < 1e-6 ? 0.0 :
> >             stop.mLocation.GetCoordValue() / appUnitsPerPixel / lineLength;
> >         break;
> >+      case eStyleUnit_Calc:
> >+        calc = stop.mLocation.GetCalcValue();
> >+        position = calc->mPercent +
> >+            NSAppUnitsToFloatPixels(calc->mLength, appUnitsPerPixel) / lineLength;
> >+        break;
> 
> This presumably needs the same test of lineLength being very small that the
> eStyleUnit_Percent case has.
> 
I do not see any related tests in 

https://bugzilla.mozilla.org/show_bug.cgi?id=594935
http://hg.mozilla.org/mozilla-central/rev/32e1ceb06e44

> (It might also be worth sharing the code if you can see a good way to do it,
> but I don't.)
> 
> You should also add tests to layout/style/test/property_database.js (where
> there are other gradient tests), and make sure that the mochitests in
> layout/style/ still pass after you do.

Get it. Thanks
I mean that your code needs to test whether lineLength < 1e-6, just like the code above does.
Update prevent lineLength too small or devided-by-zero
Attachment #662791 - Attachment is obsolete: true
Attachment #662791 - Flags: review?(bzbarsky)
Attachment #662837 - Flags: review?(bzbarsky)
Try run for 0d31e2c87860 is complete.
Detailed breakdown of the results available here:
    https://tbpl.mozilla.org/?tree=Try&rev=0d31e2c87860
Results (out of 14 total builds):
    exception: 14
Builds (or logs if builds failed) available at:
http://ftp.mozilla.org/pub/mozilla.org/firefox/try-builds/thomas@thomasy.tw-0d31e2c87860
Comment on attachment 662837 [details] [diff] [review]
Add calc to parser and do calc in PaintGradient

Adding the "-p -U 8" flags to your diff command would be a good idea.  It would definitely make this easier to review!

r=me
Attachment #662837 - Flags: review?(bzbarsky) → review+
(In reply to Boris Zbarsky (:bz) from comment #15)
> Comment on attachment 662837 [details] [diff] [review]
> Add calc to parser and do calc in PaintGradient
> 
> Adding the "-p -U 8" flags to your diff command would be a good idea.  It
> would definitely make this easier to review!
> 
> r=me

Get it.

Green on try.

https://tbpl.mozilla.org/?tree=Try&rev=58b4680ecb51
Keywords: checkin-needed
This appears to have some intermittent reftest failures on WinXP. Please investigate.
Keywords: checkin-needed
Happens on Win7 too.
(In reply to Ryan VanderMeulen from comment #18)
> Happens on Win7 too.

It always crashes at 
nsStyleCoord::HashValue(unsigned int) [nsStyleCoord.cpp:174f70187687 : 106 + 0x6]
Attached patch Add stop point to HasCalc() (obsolete) — Splinter Review
Add add stop point to HasCalc() and it seem have no crash on Windows https://tbpl.mozilla.org/?tree=Try&rev=559d028d4aa2
Attachment #662837 - Attachment is obsolete: true
Attachment #663786 - Flags: review?(bzbarsky)
Comment on attachment 663786 [details] [diff] [review]
Add stop point to HasCalc()

Please remove the "try" bits from the checkin message and r=me.

Sorry for the lag here; I hadn't realized this was just a small change from the previous diff.  :(
Attachment #663786 - Flags: review?(bzbarsky) → review+
Update checkin message.
Attachment #663786 - Attachment is obsolete: true
Attachment #667775 - Flags: review?(bzbarsky)
Update check-in message.
Attachment #667775 - Attachment is obsolete: true
Attachment #667775 - Flags: review?(bzbarsky)
Attachment #667776 - Flags: review?(bzbarsky)
Comment on attachment 667776 [details] [diff] [review]
Add calc to parser and do calc in PaintGradient

r=me.  Really, no need for extra review on a nit like this.

By the way, r=bzbarsky is just fine.  ;)
Attachment #667776 - Flags: review?(bzbarsky) → review+
Keywords: checkin-needed
Landed: https://hg.mozilla.org/integration/mozilla-inbound/rev/9fd65b219801
Flags: in-testsuite+
Keywords: checkin-needed
https://hg.mozilla.org/mozilla-central/rev/9fd65b219801
Status: NEW → RESOLVED
Closed: 12 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla18
Keywords: dev-doc-needed
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: