Ignore:
Timestamp:
Mar 25, 2021, 1:46:08 PM (4 years ago)
Author:
[email protected]
Message:

Source/WebCore:
Fix edge cases in normalization of conic-gradient color stops
https://bugs.webkit.org/show_bug.cgi?id=221294
<rdar://problem/74157218>

Patch by Tim Nguyen <[email protected]> on 2021-03-25
Reviewed by Darin Adler.

lastOneOrLessIndex had an off-by-one error, so it did not go through the
branch handling clamping all the stop offsets when they're all above 1.

Also made normalizeStopsAndEndpointsOutsideRange logic easier to follow using
Optional<size_t> instead of placeholder values.

Test: web-platform-tests/css/css-images/normalization-conic-2.html

  • css/CSSGradientValue.cpp:

(WebCore::ConicGradientAdapter::normalizeStopsAndEndpointsOutsideRange):

LayoutTests:
Enable normalization-conic-2.html WPT now that underlying bug is fixed.
Also skip some conic-gradient tests only on Windows instead of all platforms.
https://bugs.webkit.org/show_bug.cgi?id=221294
<rdar://problem/74157218>

Patch by Tim Nguyen <[email protected]> on 2021-03-25
Reviewed by Darin Adler.

  • TestExpectations: enabled imported/w3c/web-platform-tests/css/css-images/normalization-conic-2.html.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/css/CSSGradientValue.cpp

    r272497 r275055  
    238238    void normalizeStopsAndEndpointsOutsideRange(Vector<GradientStop>& stops)
    239239    {
    240         auto numStops = stops.size();
    241        
    242         size_t firstZeroOrGreaterIndex = numStops;
     240        size_t numStops = stops.size();
     241        size_t lastStopIndex = numStops - 1;
     242
     243        Optional<size_t> firstZeroOrGreaterIndex;
    243244        for (size_t i = 0; i < numStops; ++i) {
    244245            if (*stops[i].offset >= 0) {
     
    248249        }
    249250
    250         if (firstZeroOrGreaterIndex > 0) {
    251             if (firstZeroOrGreaterIndex < numStops && *stops[firstZeroOrGreaterIndex].offset > 0) {
    252                 float prevOffset = *stops[firstZeroOrGreaterIndex - 1].offset;
    253                 float nextOffset = *stops[firstZeroOrGreaterIndex].offset;
    254                
    255                 float interStopProportion = -prevOffset / (nextOffset - prevOffset);
     251        if (firstZeroOrGreaterIndex) {
     252            size_t index = *firstZeroOrGreaterIndex;
     253            if (index > 0) {
     254                float previousOffset = *stops[index - 1].offset;
     255                float nextOffset = *stops[index].offset;
     256
     257                float interStopProportion = -previousOffset / (nextOffset - previousOffset);
    256258                // FIXME: when we interpolate gradients using premultiplied colors, this should do premultiplication.
    257                 Color blendedColor = blend(stops[firstZeroOrGreaterIndex - 1].color, stops[firstZeroOrGreaterIndex].color, interStopProportion);
    258                
     259                Color blendedColor = blend(stops[index - 1].color, stops[index].color, interStopProportion);
     260
    259261                // Clamp the positions to 0 and set the color.
    260                 for (size_t i = 0; i < firstZeroOrGreaterIndex; ++i) {
     262                for (size_t i = 0; i < index; ++i) {
    261263                    stops[i].offset = 0;
    262264                    stops[i].color = blendedColor;
    263265                }
    264             } else {
    265                 // All stops are below 0; just clamp them.
    266                 for (size_t i = 0; i < firstZeroOrGreaterIndex; ++i)
    267                     stops[i].offset = 0;
    268             }
    269         }
    270 
    271         size_t lastOneOrLessIndex = numStops;
    272         for (int i = numStops - 1; i >= 0; --i) {
     266            }
     267        } else {
     268            // All stop offsets below 0, clamp them.
     269            for (auto& stop : stops)
     270                stop.offset = 0;
     271        }
     272
     273        Optional<size_t> lastOneOrLessIndex;
     274        for (int i = lastStopIndex; i >= 0; --i) {
    273275            if (*stops[i].offset <= 1) {
    274276                lastOneOrLessIndex = i;
     
    276278            }
    277279        }
    278        
    279         if (lastOneOrLessIndex < numStops - 1) {
    280             if (lastOneOrLessIndex < numStops && *stops[lastOneOrLessIndex].offset < 1) {
    281                 float prevOffset = *stops[lastOneOrLessIndex].offset;
    282                 float nextOffset = *stops[lastOneOrLessIndex + 1].offset;
    283                
    284                 float interStopProportion = (1 - prevOffset) / (nextOffset - prevOffset);
     280
     281        if (lastOneOrLessIndex) {
     282            size_t index = *lastOneOrLessIndex;
     283            if (index < lastStopIndex) {
     284                float previousOffset = *stops[index].offset;
     285                float nextOffset = *stops[index + 1].offset;
     286
     287                float interStopProportion = (1 - previousOffset) / (nextOffset - previousOffset);
    285288                // FIXME: when we interpolate gradients using premultiplied colors, this should do premultiplication.
    286                 Color blendedColor = blend(stops[lastOneOrLessIndex].color, stops[lastOneOrLessIndex + 1].color, interStopProportion);
    287                
     289                Color blendedColor = blend(stops[index].color, stops[index + 1].color, interStopProportion);
     290
    288291                // Clamp the positions to 1 and set the color.
    289                 for (size_t i = lastOneOrLessIndex + 1; i < numStops; ++i) {
     292                for (size_t i = index + 1; i <= lastStopIndex; ++i) {
    290293                    stops[i].offset = 1;
    291294                    stops[i].color = blendedColor;
    292295                }
    293             } else {
    294                 // All stops are above 1; just clamp them.
    295                 for (size_t i = lastOneOrLessIndex; i < numStops; ++i)
    296                     stops[i].offset = 1;
    297             }
     296            }
     297        } else {
     298            // All stop offsets above 1, clamp them.
     299            for (auto& stop : stops)
     300                stop.offset = 1;
    298301        }
    299302    }
Note: See TracChangeset for help on using the changeset viewer.