| Differences between
and this patch
- Source/WebCore/ChangeLog +29 lines
Lines 1-3 Source/WebCore/ChangeLog_sec1
1
2021-12-23  Sam Weinig  <weinig@apple.com>
2
3
        On systems without CG support for alpha premultiplied gradients, the CGGradientRef path should still be used for the subset of gradients that can transformed
4
        https://bugs.webkit.org/show_bug.cgi?id=234653
5
6
        Reviewed by NOBODY (OOPS!).
7
8
        Test: fast/gradients/alpha-premultiplied-representable-by-unpremultiplied.html
9
10
        Optimize gradient rendering on systems without a version of CoreGraphics that supports
11
        alpha premultiplied gradients by using the CGGradientRef code path for the subset of
12
        alpha premultiplied gradients that can be represented as alpha non-premultiplied gradients.
13
14
        Two types of optimizations are possible for two classes of this subset:
15
16
          1. Any gradient that uses the same alpha value for all color stops can be used as is
17
             with the alpha non-premultiplied CGGradientRef.
18
          2. Any gradient that conforms to the rule that "any two consecutive color stops must 
19
             either have one that is fully transparent or have the same alpha value for both"
20
             can be transformed into an identical alpha non-premultiplied gradient by transforming
21
             the fully transparent stops into either one or two stops. A comment in the code
22
             goes into much more detail about this.
23
24
        * platform/graphics/cg/GradientRendererCG.cpp:
25
        (WebCore::classifyAlphaType):
26
        (WebCore::analyzeColorStopsForEmulatedAlphaPremuliplicationOppertunity):
27
        (WebCore::alphaTransformStopsToEmulateAlphaPremuliplication):
28
        (WebCore::GradientRendererCG::pickStrategy const):
29
1
2021-12-23  Brady Eidson  <beidson@apple.com>
30
2021-12-23  Brady Eidson  <beidson@apple.com>
2
31
3
        Add WTF::UUID class which is natively a 128-bit integer
32
        Add WTF::UUID class which is natively a 128-bit integer
- Source/WebCore/platform/graphics/cg/GradientRendererCG.cpp -2 / +356 lines
Lines 40-45 GradientRendererCG::GradientRendererCG(ColorInterpolat Source/WebCore/platform/graphics/cg/GradientRendererCG.cpp_sec1
40
40
41
// MARK: - Strategy selection.
41
// MARK: - Strategy selection.
42
42
43
#if !HAVE(CORE_GRAPHICS_PREMULTIPLIED_INTERPOLATION_GRADIENT)
44
45
enum class EmulatedAlphaPremuliplicationAnalysisResult {
46
    UseGradientAsIs,
47
    UseGradientWithAlphaTransforms,
48
    UseShading
49
};
50
51
enum class AlphaType {
52
    Opaque,
53
    PartiallyTransparent,
54
    FullyTransparent
55
};
56
57
static AlphaType classifyAlphaType(float alpha)
58
{
59
    if (alpha == 1.0f)
60
        return AlphaType::Opaque;
61
    if (alpha == 0.0f)
62
        return AlphaType::FullyTransparent;
63
    return AlphaType::PartiallyTransparent;
64
}
65
66
static EmulatedAlphaPremuliplicationAnalysisResult analyzeColorStopsForEmulatedAlphaPremuliplicationOppertunity(const GradientColorStops& stops)
67
{
68
    if (stops.size() < 2)
69
        return EmulatedAlphaPremuliplicationAnalysisResult::UseGradientAsIs;
70
71
    bool uniformAlpha = true;
72
73
    auto& initialStop = *stops.begin();
74
    auto previousStopAlpha = initialStop.color.alphaAsFloat();
75
    auto previousStopAlphaType = classifyAlphaType(previousStopAlpha);
76
77
    auto stopIterator = stops.begin();
78
    ++stopIterator;
79
80
    while (stopIterator != stops.end()) {
81
        auto& stop = *stopIterator;
82
83
        auto stopAlpha = stop.color.alphaAsFloat();
84
        auto stopAlphaType = classifyAlphaType(stopAlpha);
85
86
        switch (stopAlphaType) {
87
        case AlphaType::Opaque:
88
            switch (previousStopAlphaType) {
89
            case AlphaType::Opaque:
90
                break;
91
            case AlphaType::PartiallyTransparent:
92
                return EmulatedAlphaPremuliplicationAnalysisResult::UseShading;
93
            case AlphaType::FullyTransparent:
94
                uniformAlpha = false;
95
                break;
96
            }
97
            break;
98
99
        case AlphaType::PartiallyTransparent:
100
            switch (previousStopAlphaType) {
101
            case AlphaType::Opaque:
102
                return EmulatedAlphaPremuliplicationAnalysisResult::UseShading;
103
            case AlphaType::PartiallyTransparent:
104
                if (previousStopAlpha != stopAlpha)
105
                    return EmulatedAlphaPremuliplicationAnalysisResult::UseShading;
106
                break;
107
            case AlphaType::FullyTransparent:
108
                uniformAlpha = false;
109
                break;
110
            }
111
            break;
112
113
        case AlphaType::FullyTransparent:
114
            switch (previousStopAlphaType) {
115
            case AlphaType::Opaque:
116
            case AlphaType::PartiallyTransparent:
117
                uniformAlpha = false;
118
                break;
119
120
            case AlphaType::FullyTransparent:
121
                break;
122
            }
123
            break;
124
        }
125
126
        previousStopAlpha = stopAlpha;
127
        previousStopAlphaType = stopAlphaType;
128
129
        ++stopIterator;
130
    }
131
132
    return uniformAlpha ? EmulatedAlphaPremuliplicationAnalysisResult::UseGradientAsIs : EmulatedAlphaPremuliplicationAnalysisResult::UseGradientWithAlphaTransforms;
133
}
134
135
static GradientColorStops alphaTransformStopsToEmulateAlphaPremuliplication(const GradientColorStops& stops)
136
{
137
    // The following is the set of transforms that can be preformed on a color stop list to transform it from one used with a premuliplied alpha gradient
138
    // implmentation to one used by with an un-premultiplied gradient implementation.
139
140
    // ... Opaque  -> Transparent -> Opaque  ...                                  ==>    ... Opaque  -> TRANSFORM{Transparent(PreviousChannels)} | ADDITION{Transparent(NextChannels)} -> Opaque  ...
141
    // ... Partial -> Transparent -> Partial ...                                  ==>    ... Partial -> TRANSFORM{Transparent(PreviousChannels)} | ADDITION{Transparent(NextChannels)} -> Partial ...
142
    // ... Opaque  -> Transparent -> Partial ...                                  ==>    ... Opaque  -> TRANSFORM{Transparent(PreviousChannels)} | ADDITION{Transparent(NextChannels)} -> Partial ...
143
    // ... Partial -> Transparent -> Opaque  ...                                  ==>    ... Partial -> TRANSFORM{Transparent(PreviousChannels)} | ADDITION{Transparent(NextChannels)} -> Opaque  ...
144
    //
145
    // ... Opaque  -> Transparent -> Transparent -> Opaque  ...                   ==>    ... Opaque  -> TRANSFORM{Transparent(PreviousChannels)} -> TRANSFORM{Transparent(NextChannels)} -> Opaque  ...
146
    // ... Partial -> Transparent -> Transparent -> Partial ...                   ==>    ... Partial -> TRANSFORM{Transparent(PreviousChannels)} -> TRANSFORM{Transparent(NextChannels)} -> Partial ...
147
    // ... Opaque  -> Transparent -> Transparent -> Partial ...                   ==>    ... Opaque  -> TRANSFORM{Transparent(PreviousChannels)} -> TRANSFORM{Transparent(NextChannels)} -> Partial ...
148
    // ... Partial -> Transparent -> Transparent -> Opaque  ...                   ==>    ... Partial -> TRANSFORM{Transparent(PreviousChannels)} -> TRANSFORM{Transparent(NextChannels)} -> Opaque  ...
149
    //
150
    // ... Opaque  -> Transparent -> Transparent -> Transparent -> Opaque  ...    ==>    ... Opaque  -> TRANSFORM{Transparent(PreviousChannels)} -> Transparent -> TRANSFORM{Transparent(NextChannels)} -> Opaque  ...
151
    // ... Partial -> Transparent -> Transparent -> Transparent -> Partial ...    ==>    ... Partial -> TRANSFORM{Transparent(PreviousChannels)} -> Transparent -> TRANSFORM{Transparent(NextChannels)} -> Partial ...
152
    // ... Opaque  -> Transparent -> Transparent -> Transparent -> Partial ...    ==>    ... Opaque  -> TRANSFORM{Transparent(PreviousChannels)} -> Transparent -> TRANSFORM{Transparent(NextChannels)} -> Partial ...
153
    // ... Partial -> Transparent -> Transparent -> Transparent -> Opaque  ...    ==>    ... Partial -> TRANSFORM{Transparent(PreviousChannels)} -> Transparent -> TRANSFORM{Transparent(NextChannels)} -> Opaque  ...
154
    //
155
    // [ Transparent -> Opaque      ...                                           ==>    [ TRANSFORM{Transparent(NextChannels)} -> Opaque      ...
156
    // [ Transparent -> Partial     ...                                           ==>    [ TRANSFORM{Transparent(NextChannels)} -> Partial     ...
157
    // [ Transparent -> Transparent ...                                           ==>    [ Transparent                          -> Transparent ...
158
    //
159
    // ... Opaque       -> Transparent ]                                          ==>    ... Opaque      -> TRANSFORM{Transparent(PreviousChannels)} ]
160
    // ... Partial      -> Transparent ]                                          ==>    ... Partial     -> TRANSFORM{Transparent(PreviousChannels)} ]
161
    // ... Transparent  -> Transparent ]                                          ==>    ... Transparent -> Transparent                              ]
162
163
    // For each stop the following actions are possible:
164
    //      - Default           Append self
165
    //      - Steal previous    Append previous.colorWithAlpha(0.0f)
166
    //      - Steal next        Append next.colorWithAlpha(0.0f)
167
    //      - Split             Append previous.colorWithAlpha(0.0f) + next.colorWithAlpha(0.0f)
168
169
    ASSERT(stops.size() > 1);
170
171
    // Special case when we only have two stops to avoid complicating the cases with more.
172
    if (stops.size() == 2) {
173
        // Illegal pairs (ruled out in analysis)
174
        //   Opaque  -> Partial
175
        //   Partial -> Opaque
176
        //
177
        // Possible pairs
178
        //   Opaque      -> Opaque       (default, default)
179
        //   Partial     -> Partial      (default, default)
180
        //   Transparent -> Transparent  (default, default)
181
        //   Opaque      -> Transparent  (default, steal previous)
182
        //   Partial     -> Transparent  (default, steal previous)
183
        //   Transparent -> Opaque       (steals next, default)
184
        //   Transparent -> Partial      (steals next, default)
185
186
        GradientColorStops::StopVector result;
187
        result.reserveInitialCapacity(2);
188
189
        auto& stop1 = stops.stops()[0];
190
        auto& stop2 = stops.stops()[1];
191
192
        auto stop1AlphaType = classifyAlphaType(stop1.color.alphaAsFloat());
193
        auto stop2AlphaType = classifyAlphaType(stop2.color.alphaAsFloat());
194
195
        switch (stop1AlphaType) {
196
        case AlphaType::Opaque:
197
        case AlphaType::PartiallyTransparent:
198
            // ACTION (stop1): Default.
199
            result.uncheckedAppend(stop1);
200
201
            switch (stop2AlphaType) {
202
            case AlphaType::Opaque:
203
            case AlphaType::PartiallyTransparent:
204
                // ACTION (stop2): Default.
205
                result.uncheckedAppend(stop2);
206
                break;
207
            case AlphaType::FullyTransparent:
208
                // ACTION (stop2): Steal previous.
209
                result.uncheckedAppend({ stop2.offset, stop1.color.colorWithAlpha(0.0f) });
210
                break;
211
            }
212
213
            break;
214
215
        case AlphaType::FullyTransparent:
216
            switch (stop2AlphaType) {
217
            case AlphaType::Opaque:
218
            case AlphaType::PartiallyTransparent:
219
                // ACTION (stop1): Steal next.
220
                result.uncheckedAppend({ stop1.offset, stop2.color.colorWithAlpha(0.0f) });
221
                break;
222
            case AlphaType::FullyTransparent:
223
                // ACTION (stop1): Default.
224
                result.uncheckedAppend(stop1);
225
                break;
226
            }
227
            // ACTION (stop2): Default.
228
            result.uncheckedAppend(stop2);
229
            break;
230
        }
231
232
        return GradientColorStops::Sorted { WTFMove(result) };
233
    }
234
235
    // For three or more stops, we handle the first stop special, then the middle stops one at a time with the next and previous stop as context, then the last stop as special.
236
237
    GradientColorStops::StopVector result;
238
239
    // 1. Handle first stop.
240
    //
241
    // [first stop matters]
242
    //
243
    // Illegal pairs (ruled out in analysis)
244
    //   Opaque  -> Partial
245
    //   Partial -> Opaque
246
    //
247
    // Possible pairs
248
    //   Opaque      -> Opaque       (default)
249
    //   Partial     -> Partial      (default)
250
    //   Transparent -> Transparent  (default)
251
    //   Opaque      -> Transparent  (default)
252
    //   Partial     -> Transparent  (default)
253
    //   Transparent -> Opaque       (steals next)
254
    //   Transparent -> Partial      (steals next)
255
256
    auto& firstStop = stops.stops()[0];
257
    auto& secondStop = stops.stops()[1];
258
259
    auto firstStopAlphaType = classifyAlphaType(firstStop.color.alphaAsFloat());
260
    auto secondStopAlphaType = classifyAlphaType(secondStop.color.alphaAsFloat());
261
262
    if (firstStopAlphaType == AlphaType::FullyTransparent && secondStopAlphaType != AlphaType::FullyTransparent) {
263
        // ACTION: Steal next.
264
        result.append({ firstStop.offset, secondStop.color.colorWithAlpha(0.0f) });
265
    } else {
266
        // ACTION: Default.
267
        result.append(firstStop);
268
    }
269
270
    // 2. Handle middle stops.
271
    //
272
    // [middle stop matters]
273
    //
274
    // Illegal triplets (ruled out in analysis)
275
    //   Opaque      -> Opaque      -> Partial
276
    //   Opaque      -> Partial     -> Partial
277
    //   Opaque      -> Partial     -> Opaque
278
    //   Partial     -> Opaque      -> Opaque
279
    //   Partial     -> Partial     -> Opaque
280
    //   Partial     -> Opaque      -> Partial
281
    //
282
    // Possible triplets
283
    //   Opaque      -> Opaque      -> Opaque       (default)
284
    //   Partial     -> Partial     -> Partial      (default)
285
    //   Opaque      -> Opaque      -> Transparent  (default)
286
    //   Opaque      -> Partial     -> Transparent  (default)
287
    //   Partial     -> Partial     -> Transparent  (default)
288
    //   Partial     -> Opaque      -> Transparent  (default)
289
    //   Transparent -> Opaque      -> Transparent  (default)
290
    //   Transparent -> Partial     -> Transparent  (default)
291
    //   Transparent -> Transparent -> Transparent  (default)
292
    //   Opaque      -> Transparent -> Opaque       (splits, steals previous + next)
293
    //   Opaque      -> Transparent -> Partial      (splits, steals previous + next)
294
    //   Partial     -> Transparent -> Partial      (splits, steals previous + next)
295
    //   Partial     -> Transparent -> Opaque       (splits, steals previous + next)
296
    //   Transparent -> Transparent -> Opaque       (steals next)
297
    //   Transparent -> Transparent -> Partial      (steals next)
298
    //   Opaque      -> Transparent -> Transparent  (steals previous)
299
    //   Partial     -> Transparent -> Transparent  (steals previous)
300
301
    size_t previousStopIndex = 0;
302
    size_t stopIndex = 1;
303
    size_t nextStopIndex = 2;
304
305
    for (; nextStopIndex < stops.size(); ++previousStopIndex, ++stopIndex, ++nextStopIndex) {
306
        auto& previousStop = stops.stops()[previousStopIndex];
307
        auto& stop = stops.stops()[stopIndex];
308
        auto& nextStop = stops.stops()[nextStopIndex];
309
310
        auto previousStopAlphaType = classifyAlphaType(previousStop.color.alphaAsFloat());
311
        auto stopAlphaType = classifyAlphaType(stop.color.alphaAsFloat());
312
        auto nextStopAlphaType = classifyAlphaType(nextStop.color.alphaAsFloat());
313
314
        if (stopAlphaType == AlphaType::FullyTransparent) {
315
            switch (previousStopAlphaType) {
316
            case AlphaType::Opaque:
317
            case AlphaType::PartiallyTransparent:
318
                switch (nextStopAlphaType) {
319
                case AlphaType::Opaque:
320
                case AlphaType::PartiallyTransparent:
321
                    // ACTION: Split.
322
                    result.append({ stop.offset, previousStop.color.colorWithAlpha(0.0f) });
323
                    result.append({ stop.offset, nextStop.color.colorWithAlpha(0.0f) });
324
                    break;
325
326
                case AlphaType::FullyTransparent:
327
                    // ACTION: Steal previous.
328
                    result.append({ stop.offset, previousStop.color.colorWithAlpha(0.0f) });
329
                    break;
330
                }
331
                break;
332
333
            case AlphaType::FullyTransparent:
334
                switch (nextStopAlphaType) {
335
                case AlphaType::Opaque:
336
                case AlphaType::PartiallyTransparent:
337
                    // ACTION: Steal next.
338
                    result.append({ stop.offset, nextStop.color.colorWithAlpha(0.0f) });
339
                    break;
340
341
                case AlphaType::FullyTransparent:
342
                    // ACTION: Default.
343
                    result.append(stop);
344
                    break;
345
                }
346
                break;
347
            }
348
        } else {
349
            // ACTION: Default.
350
            result.append(stop);
351
        }
352
    }
353
354
    ASSERT(nextStopIndex == stops.size());
355
356
    // 3. Handle last stop.
357
    //
358
    // [last stop matters]
359
    //
360
    // Illegal pairs (ruled out in analysis phase)
361
    //   Opaque  -> Partial
362
    //   Partial -> Opaque
363
    //
364
    // Possible pairs
365
    //   Opaque      -> Opaque       (default)
366
    //   Partial     -> Partial      (default)
367
    //   Transparent -> Transparent  (default)
368
    //   Opaque      -> Transparent  (steals previous)
369
    //   Partial     -> Transparent  (steals previous)
370
    //   Transparent -> Opaque       (default)
371
    //   Transparent -> Partial      (default)
372
373
    auto& secondToLastStop = stops.stops()[previousStopIndex];
374
    auto& lastStop = stops.stops()[stopIndex];
375
376
    auto secondToLastStopAlphaType = classifyAlphaType(secondToLastStop.color.alphaAsFloat());
377
    auto lastStopAlphaType = classifyAlphaType(lastStop.color.alphaAsFloat());
378
379
    if (lastStopAlphaType == AlphaType::FullyTransparent && secondToLastStopAlphaType != AlphaType::FullyTransparent) {
380
        // ACTION: Steal previous.
381
        result.append({ lastStop.offset, secondToLastStop.color.colorWithAlpha(0.0f) });
382
    } else {
383
        // ACTION: Default.
384
        result.append(lastStop);
385
    }
386
387
    return GradientColorStops::Sorted { WTFMove(result) };
388
}
389
#endif
390
43
GradientRendererCG::Strategy GradientRendererCG::pickStrategy(ColorInterpolationMethod colorInterpolationMethod, const GradientColorStops& stops) const
391
GradientRendererCG::Strategy GradientRendererCG::pickStrategy(ColorInterpolationMethod colorInterpolationMethod, const GradientColorStops& stops) const
44
{
392
{
45
    return WTF::switchOn(colorInterpolationMethod.colorSpace,
393
    return WTF::switchOn(colorInterpolationMethod.colorSpace,
Lines 51-58 GradientRendererCG::Strategy GradientRendererCG::pickS Source/WebCore/platform/graphics/cg/GradientRendererCG.cpp_sec2
51
#if HAVE(CORE_GRAPHICS_PREMULTIPLIED_INTERPOLATION_GRADIENT)
399
#if HAVE(CORE_GRAPHICS_PREMULTIPLIED_INTERPOLATION_GRADIENT)
52
                return makeGradient(colorInterpolationMethod, stops);
400
                return makeGradient(colorInterpolationMethod, stops);
53
#else
401
#else
54
                // FIXME: Use gradient strategy if none of the stops have alpha.
402
                switch (analyzeColorStopsForEmulatedAlphaPremuliplicationOppertunity(stops)) {
55
                return makeShading(colorInterpolationMethod, stops);
403
                case EmulatedAlphaPremuliplicationAnalysisResult::UseGradientAsIs:
404
                    return makeGradient({ ColorInterpolationMethod::SRGB { }, AlphaPremultiplication::Unpremultiplied }, stops);
405
                case EmulatedAlphaPremuliplicationAnalysisResult::UseGradientWithAlphaTransforms:
406
                    return makeGradient({ ColorInterpolationMethod::SRGB { }, AlphaPremultiplication::Unpremultiplied }, alphaTransformStopsToEmulateAlphaPremuliplication(stops));
407
                case EmulatedAlphaPremuliplicationAnalysisResult::UseShading:
408
                    return makeShading(colorInterpolationMethod, stops);
409
                }
56
#endif
410
#endif
57
            }
411
            }
58
        },
412
        },
- LayoutTests/ChangeLog +17 lines
Lines 1-3 LayoutTests/ChangeLog_sec1
1
2021-12-23  Sam Weinig  <weinig@apple.com>
2
3
        On systems without CG support for alpha premultiplied gradients, the CGGradientRef path should still be used for the subset of gradients that can transformed
4
        https://bugs.webkit.org/show_bug.cgi?id=234653
5
6
        Reviewed by NOBODY (OOPS!).
7
8
        Add tests of gradients that can render identically with both alpha premultiplied and non-premultiplied gradients
9
        either using the same color stop list or a transformed one.
10
11
        The main test page contains the alpha premultiplied gradients (which is the default now for CSS gradients), while
12
        the -expected.html contains the alpha non-premultiplied gradients and has alpha premultiplied interpolation explicitly
13
        disabled via a CSSGradientPremultipliedAlphaInterpolationEnabled=false comment command.
14
15
        * fast/gradients/alpha-premultiplied-representable-by-unpremultiplied-expected.html: Added.
16
        * fast/gradients/alpha-premultiplied-representable-by-unpremultiplied.html: Added.
17
1
2021-12-23  Tim Nguyen  <ntim@apple.com>
18
2021-12-23  Tim Nguyen  <ntim@apple.com>
2
19
3
        Rebaseline getComputedStyle tests for iOS after r287356
20
        Rebaseline getComputedStyle tests for iOS after r287356
- LayoutTests/fast/gradients/alpha-premultiplied-representable-by-unpremultiplied-expected.html +192 lines
Line 0 LayoutTests/fast/gradients/alpha-premultiplied-representable-by-unpremultiplied-expected.html_sec1
1
<!DOCTYPE html><!-- webkit-test-runner [ CSSGradientPremultipliedAlphaInterpolationEnabled=false ] -->
2
<html>
3
<head>
4
<style>
5
    div { 
6
        width: 100px;
7
        height: 100px;
8
        border: dashed black 1px;
9
        display: inline-block;
10
    }
11
12
    :root {
13
        --transparent-1: rgba(0, 0, 255, 0);
14
        --transparent-2: rgba(255, 0, 0, 0);
15
        --transparent-3: rgba(0, 255, 0, 0);
16
        --transparent-4: rgba(255, 255, 0, 0);
17
18
        --opaque-1: rgba(0, 0, 255, 1);
19
        --opaque-2: rgba(255, 0, 0, 1);
20
        --opaque-3: rgba(0, 255, 0, 1);
21
        --opaque-4: rgba(255, 255, 0, 1);
22
23
        --partial-1: rgba(0, 0, 255, 0.5);
24
        --partial-2: rgba(255, 0, 0, 0.5);
25
        --partial-3: rgba(0, 255, 0, 0.5);
26
        --partial-4: rgba(255, 255, 0, 0.5);
27
    }
28
29
    /* NOTE: If we ever want to remove the option to disable alpha premultiplied gradients, and alternative way
30
             to test this would be using either Canvas or SVG, which both use unpremultiplied interpolation.    */
31
32
    #opaque-opaque {
33
        /* No transform */
34
        background-image: linear-gradient(var(--opaque-1), var(--opaque-2));
35
    }
36
37
    #partial-partial {
38
        /* No transform */
39
        background-image: linear-gradient(var(--partial-1), var(--partial-2));
40
    }
41
42
    #transparent-transparent {
43
        /* No transform */
44
        background-image: linear-gradient(var(--transparent-1), var(--transparent-2));
45
    }
46
47
    #transparent-opaque {
48
        /* Steal next */
49
        background-image: linear-gradient(var(--transparent-2), var(--opaque-2));
50
    }
51
52
    #transparent-partial {
53
        /* Steal next */
54
        background-image: linear-gradient(var(--transparent-2), var(--partial-2));
55
    }
56
57
    #opaque-transparent {
58
        /* Steal previous */
59
        background-image: linear-gradient(var(--opaque-1), var(--transparent-1));
60
    }
61
62
    #partial-transparent {
63
        /* Steal previous */
64
        background-image: linear-gradient(var(--partial-1), var(--transparent-1));
65
    }
66
67
    #opaque-transparent-opaque {
68
        /* Split */
69
        background-image: linear-gradient(var(--opaque-1), var(--transparent-1) 50%, var(--transparent-3) 50%, var(--opaque-3));
70
    }
71
72
    #opaque-transparent-partial {
73
        /* Split */
74
        background-image: linear-gradient(var(--opaque-1), var(--transparent-1) 50%, var(--transparent-3) 50%, var(--partial-3));
75
    }
76
77
    #partial-transparent-partial {
78
        /* Split */
79
        background-image: linear-gradient(var(--partial-1), var(--transparent-1) 50%, var(--transparent-3) 50%, var(--partial-3));
80
    }
81
82
    #partial-transparent-opaque {
83
        /* Split */
84
        background-image: linear-gradient(var(--partial-1), var(--transparent-1) 50%, var(--transparent-3) 50%, var(--opaque-3));
85
    }
86
87
    #opaque-transparent-transparent-opaque {
88
        /* Steal previous, steal next */
89
        background-image: linear-gradient(var(--opaque-1), var(--transparent-1), var(--transparent-4), var(--opaque-4));
90
    }
91
92
    #opaque-transparent-transparent-partial {
93
        /* Steal previous, steal next */
94
        background-image: linear-gradient(var(--opaque-1), var(--transparent-1), var(--transparent-4), var(--partial-4));
95
    }
96
97
    #partial-transparent-transparent-partial {
98
        /* Steal previous, steal next */
99
        background-image: linear-gradient(var(--partial-1), var(--transparent-1), var(--transparent-4), var(--partial-4));
100
    }
101
102
    #partial-transparent-transparent-opaque {
103
        /* Steal previous, nothing, steal next */
104
        background-image: linear-gradient(var(--partial-1), var(--transparent-1), var(--transparent-4), var(--opaque-4));
105
    }
106
107
    #opaque-transparent-transparent-transparent-opaque {
108
        /* Steal previous, nothing, steal next */
109
        background-image: linear-gradient(var(--opaque-1), var(--transparent-1), var(--transparent-3), var(--transparent-2), var(--opaque-2));
110
    }
111
112
    #opaque-transparent-transparent-transparent-partial {
113
        /* Steal previous, nothing, steal next */
114
        background-image: linear-gradient(var(--opaque-1), var(--transparent-1), var(--transparent-3), var(--transparent-2), var(--partial-2));
115
    }
116
117
    #partial-transparent-transparent-transparent-partial {
118
        /* Steal previous, nothing, steal next */
119
        background-image: linear-gradient(var(--partial-1), var(--transparent-1), var(--transparent-3), var(--transparent-2), var(--partial-2));
120
    }
121
122
    #partial-transparent-transparent-transparent-opaque {
123
        /* Steal previous, nothing, steal next */
124
        background-image: linear-gradient(var(--partial-1), var(--transparent-1), var(--transparent-3), var(--transparent-2), var(--opaque-2));
125
    }
126
127
    #opaque-transparent-transparent {
128
        /* Steal previous, nothing */
129
        background-image: linear-gradient(var(--opaque-1), var(--transparent-1), var(--transparent-3));
130
    }
131
132
    #partial-transparent-transparent {
133
        /* Steal previous, nothing */
134
        background-image: linear-gradient(var(--partial-1), var(--transparent-1), var(--transparent-3));
135
    }
136
137
    #transparent-transparent-opaque {
138
        /* Nothing, steal next */
139
        background-image: linear-gradient(var(--transparent-1), var(--transparent-3), var(--opaque-3));
140
    }
141
142
    #transparent-transparent-partial {
143
        /* Nothing, steal next */
144
        background-image: linear-gradient(var(--transparent-1), var(--transparent-3), var(--partial-3));
145
    }
146
147
    #transparent-transparent-transparent {
148
        /* No transform */
149
        background-image: linear-gradient(var(--transparent-1), var(--transparent-2), var(--transparent-3));
150
    }
151
152
    #transparent-opaque-transparent {
153
        /* Steal next, steal previous */
154
        background-image: linear-gradient(var(--transparent-2), var(--opaque-2), var(--transparent-2));
155
    }
156
157
    #transparent-partial-transparent {
158
        /* Steal next, steal previous */
159
        background-image: linear-gradient(var(--transparent-2), var(--partial-2), var(--transparent-2));
160
    }
161
162
</style>
163
</head>
164
<body>
165
<div id="opaque-opaque"></div>
166
<div id="partial-partial"></div>
167
<div id="transparent-transparent"></div>
168
<div id="transparent-opaque"></div>
169
<div id="transparent-partial"></div>
170
<div id="opaque-transparent"></div>
171
<div id="partial-transparent"></div>
172
<div id="opaque-transparent-opaque"></div>
173
<div id="opaque-transparent-partial"></div>
174
<div id="partial-transparent-partial"></div>
175
<div id="partial-transparent-opaque"></div>
176
<div id="opaque-transparent-transparent-opaque"></div>
177
<div id="opaque-transparent-transparent-partial"></div>
178
<div id="partial-transparent-transparent-partial"></div>
179
<div id="partial-transparent-transparent-opaque"></div>
180
<div id="opaque-transparent-transparent-transparent-opaque"></div>
181
<div id="opaque-transparent-transparent-transparent-partial"></div>
182
<div id="partial-transparent-transparent-transparent-partial"></div>
183
<div id="partial-transparent-transparent-transparent-opaque"></div>
184
<div id="opaque-transparent-transparent"></div>
185
<div id="partial-transparent-transparent"></div>
186
<div id="transparent-transparent-opaque"></div>
187
<div id="transparent-transparent-partial"></div>
188
<div id="transparent-transparent-transparent"></div>
189
<div id="transparent-opaque-transparent"></div>
190
<div id="transparent-partial-transparent"></div>
191
</body>
192
</html>
- LayoutTests/fast/gradients/alpha-premultiplied-representable-by-unpremultiplied.html +162 lines
Line 0 LayoutTests/fast/gradients/alpha-premultiplied-representable-by-unpremultiplied.html_sec1
1
<!DOCTYPE html>
2
<html>
3
<head>
4
<style>
5
    div { 
6
        width: 100px;
7
        height: 100px;
8
        border: dashed black 1px;
9
        display: inline-block;
10
    }
11
12
    :root {
13
        --transparent-1: rgba(0, 0, 255, 0);
14
        --transparent-2: rgba(255, 0, 0, 0);
15
        --transparent-3: rgba(0, 255, 0, 0);
16
        --transparent-4: rgba(255, 255, 0, 0);
17
18
        --opaque-1: rgba(0, 0, 255, 1);
19
        --opaque-2: rgba(255, 0, 0, 1);
20
        --opaque-3: rgba(0, 255, 0, 1);
21
        --opaque-4: rgba(255, 255, 0, 1);
22
23
        --partial-1: rgba(0, 0, 255, 0.5);
24
        --partial-2: rgba(255, 0, 0, 0.5);
25
        --partial-3: rgba(0, 255, 0, 0.5);
26
        --partial-4: rgba(255, 255, 0, 0.5);
27
    }
28
    
29
    #opaque-opaque {
30
        background-image: linear-gradient(var(--opaque-1), var(--opaque-2));
31
    }
32
33
    #partial-partial {
34
        background-image: linear-gradient(var(--partial-1), var(--partial-2));
35
    }
36
37
    #transparent-transparent {
38
        background-image: linear-gradient(var(--transparent-1), var(--transparent-2));
39
    }
40
41
    #transparent-opaque {
42
        background-image: linear-gradient(var(--transparent-1), var(--opaque-2));
43
    }
44
45
    #transparent-partial {
46
        background-image: linear-gradient(var(--transparent-1), var(--partial-2));
47
    }
48
49
    #opaque-transparent {
50
        background-image: linear-gradient(var(--opaque-1), var(--transparent-2));
51
    }
52
53
    #partial-transparent {
54
        background-image: linear-gradient(var(--partial-1), var(--transparent-2));
55
    }
56
57
    #opaque-transparent-opaque {
58
        background-image: linear-gradient(var(--opaque-1), var(--transparent-2), var(--opaque-3));
59
    }
60
61
    #opaque-transparent-partial {
62
        background-image: linear-gradient(var(--opaque-1), var(--transparent-2), var(--partial-3));
63
    }
64
65
    #partial-transparent-partial {
66
        background-image: linear-gradient(var(--partial-1), var(--transparent-2), var(--partial-3));
67
    }
68
69
    #partial-transparent-opaque {
70
        background-image: linear-gradient(var(--partial-1), var(--transparent-2), var(--opaque-3));
71
    }
72
73
    #opaque-transparent-transparent-opaque {
74
        background-image: linear-gradient(var(--opaque-1), var(--transparent-2), var(--transparent-3), var(--opaque-4));
75
    }
76
77
    #opaque-transparent-transparent-partial {
78
        background-image: linear-gradient(var(--opaque-1), var(--transparent-2), var(--transparent-3), var(--partial-4));
79
    }
80
81
    #partial-transparent-transparent-partial {
82
        background-image: linear-gradient(var(--partial-1), var(--transparent-2), var(--transparent-3), var(--partial-4));
83
    }
84
85
    #partial-transparent-transparent-opaque {
86
        background-image: linear-gradient(var(--partial-1), var(--transparent-2), var(--transparent-3), var(--opaque-4));
87
    }
88
89
    #opaque-transparent-transparent-transparent-opaque {
90
        background-image: linear-gradient(var(--opaque-1), var(--transparent-2), var(--transparent-3), var(--transparent-4), var(--opaque-2));
91
    }
92
93
    #opaque-transparent-transparent-transparent-partial {
94
        background-image: linear-gradient(var(--opaque-1), var(--transparent-2), var(--transparent-3), var(--transparent-4), var(--partial-2));
95
    }
96
97
    #partial-transparent-transparent-transparent-partial {
98
        background-image: linear-gradient(var(--partial-1), var(--transparent-2), var(--transparent-3), var(--transparent-4), var(--partial-2));
99
    }
100
101
    #partial-transparent-transparent-transparent-opaque {
102
        background-image: linear-gradient(var(--partial-1), var(--transparent-2), var(--transparent-3), var(--transparent-4), var(--opaque-2));
103
    }
104
105
    #opaque-transparent-transparent {
106
        background-image: linear-gradient(var(--opaque-1), var(--transparent-2), var(--transparent-3));
107
    }
108
109
    #partial-transparent-transparent {
110
        background-image: linear-gradient(var(--partial-1), var(--transparent-2), var(--transparent-3));
111
    }
112
113
    #transparent-transparent-opaque {
114
        background-image: linear-gradient(var(--transparent-1), var(--transparent-2), var(--opaque-3));
115
    }
116
117
    #transparent-transparent-partial {
118
        background-image: linear-gradient(var(--transparent-1), var(--transparent-2), var(--partial-3));
119
    }
120
121
    #transparent-transparent-transparent {
122
        background-image: linear-gradient(var(--transparent-1), var(--transparent-2), var(--transparent-3));
123
    }
124
125
    #transparent-opaque-transparent {
126
        background-image: linear-gradient(var(--transparent-1), var(--opaque-2), var(--transparent-3));
127
    }
128
    #transparent-partial-transparent {
129
        background-image: linear-gradient(var(--transparent-1), var(--partial-2), var(--transparent-3));
130
    }
131
132
</style>
133
</head>
134
<body>
135
<div id="opaque-opaque"></div>
136
<div id="partial-partial"></div>
137
<div id="transparent-transparent"></div>
138
<div id="transparent-opaque"></div>
139
<div id="transparent-partial"></div>
140
<div id="opaque-transparent"></div>
141
<div id="partial-transparent"></div>
142
<div id="opaque-transparent-opaque"></div>
143
<div id="opaque-transparent-partial"></div>
144
<div id="partial-transparent-partial"></div>
145
<div id="partial-transparent-opaque"></div>
146
<div id="opaque-transparent-transparent-opaque"></div>
147
<div id="opaque-transparent-transparent-partial"></div>
148
<div id="partial-transparent-transparent-partial"></div>
149
<div id="partial-transparent-transparent-opaque"></div>
150
<div id="opaque-transparent-transparent-transparent-opaque"></div>
151
<div id="opaque-transparent-transparent-transparent-partial"></div>
152
<div id="partial-transparent-transparent-transparent-partial"></div>
153
<div id="partial-transparent-transparent-transparent-opaque"></div>
154
<div id="opaque-transparent-transparent"></div>
155
<div id="partial-transparent-transparent"></div>
156
<div id="transparent-transparent-opaque"></div>
157
<div id="transparent-transparent-partial"></div>
158
<div id="transparent-transparent-transparent"></div>
159
<div id="transparent-opaque-transparent"></div>
160
<div id="transparent-partial-transparent"></div>
161
</body>
162
</html>

Return to Bug 234653