22
22
#include " nsContentUtils.h"
23
23
#include " SVGAnimatedTransformList.h"
24
24
25
+ // XXX Tight coupling with content classes ahead!
26
+
25
27
using namespace mozilla ::dom;
26
28
using namespace mozilla ::dom::SVGGradientElement_Binding;
27
29
using namespace mozilla ::dom::SVGUnitTypes_Binding;
@@ -208,53 +210,21 @@ dom::SVGRadialGradientElement* SVGGradientFrame::GetRadialGradientWithLength(
208
210
// ----------------------------------------------------------------------
209
211
// SVGPaintServerFrame methods:
210
212
211
- // helpers
212
-
213
- static ColorStop GetStopInformation (const nsIFrame* aStopFrame,
214
- float aGraphicOpacity,
215
- float & aLastPosition) {
213
+ // helper
214
+ static void GetStopInformation (nsIFrame* aStopFrame, float * aOffset,
215
+ nscolor* aStopColor, float * aStopOpacity) {
216
216
nsIContent* stopContent = aStopFrame->GetContent ();
217
217
MOZ_ASSERT (stopContent && stopContent->IsSVGElement (nsGkAtoms::stop));
218
218
219
- float position;
220
219
static_cast <SVGStopElement*>(stopContent)
221
- ->GetAnimatedNumberValues (&position, nullptr );
222
-
223
- position = clamped (position, 0 .0f , 1 .0f );
224
-
225
- if (position < aLastPosition) {
226
- position = aLastPosition;
227
- } else {
228
- aLastPosition = position;
229
- }
230
-
231
- const auto * svgReset = aStopFrame->StyleSVGReset ();
220
+ ->GetAnimatedNumberValues (aOffset, nullptr );
232
221
233
- sRGBColor stopColor =
234
- sRGBColor::FromABGR (svgReset->mStopColor .CalcColor (aStopFrame));
235
- stopColor.a *= svgReset->mStopOpacity * aGraphicOpacity;
236
-
237
- return ColorStop (position, false ,
238
- StyleAbsoluteColor::FromColor (stopColor.ToABGR ()));
222
+ const nsStyleSVGReset* styleSVGReset = aStopFrame->StyleSVGReset ();
223
+ *aOffset = mozilla::clamped (*aOffset, 0 .0f , 1 .0f );
224
+ *aStopColor = styleSVGReset->mStopColor .CalcColor (aStopFrame);
225
+ *aStopOpacity = styleSVGReset->mStopOpacity ;
239
226
}
240
227
241
- class MOZ_STACK_CLASS SVGColorStopInterpolator
242
- : public ColorStopInterpolator<SVGColorStopInterpolator> {
243
- public:
244
- SVGColorStopInterpolator (
245
- gfxPattern* aGradient, const nsTArray<ColorStop>& aStops,
246
- const StyleColorInterpolationMethod& aStyleColorInterpolationMethod)
247
- : ColorStopInterpolator(aStops, aStyleColorInterpolationMethod),
248
- mGradient (aGradient) {}
249
-
250
- void CreateStop (float aPosition, DeviceColor aColor) {
251
- mGradient ->AddColorStop (aPosition, aColor);
252
- }
253
-
254
- private:
255
- gfxPattern* mGradient ;
256
- };
257
-
258
228
already_AddRefed<gfxPattern> SVGGradientFrame::GetPaintServerPattern (
259
229
nsIFrame* aSource, const DrawTarget* aDrawTarget,
260
230
const gfxMatrix& aContextMatrix, StyleSVGPaint nsStyleSVG::*aFillOrStroke,
@@ -270,21 +240,29 @@ already_AddRefed<gfxPattern> SVGGradientFrame::GetPaintServerPattern(
270
240
mSource = aSource->IsTextFrame () ? aSource->GetParent () : aSource;
271
241
}
272
242
273
- AutoTArray<ColorStop , 8 > stops ;
274
- GetStops (&stops, aGraphicOpacity );
243
+ AutoTArray<nsIFrame* , 8 > stopFrames ;
244
+ GetStopFrames (&stopFrames );
275
245
276
- uint32_t nStops = stops .Length ();
246
+ uint32_t nStops = stopFrames .Length ();
277
247
278
248
// SVG specification says that no stops should be treated like
279
249
// the corresponding fill or stroke had "none" specified.
280
250
if (nStops == 0 ) {
251
+ RefPtr<gfxPattern> pattern = new gfxPattern (DeviceColor ());
281
252
return do_AddRef (new gfxPattern (DeviceColor ()));
282
253
}
283
254
284
255
if (nStops == 1 || GradientVectorLengthIsZero ()) {
256
+ auto * lastStopFrame = stopFrames[nStops - 1 ];
257
+ const auto * svgReset = lastStopFrame->StyleSVGReset ();
285
258
// The gradient paints a single colour, using the stop-color of the last
286
259
// gradient step if there are more than one.
287
- return do_AddRef (new gfxPattern (ToDeviceColor (stops.LastElement ().mColor )));
260
+ float stopOpacity = svgReset->mStopOpacity ;
261
+ nscolor stopColor = svgReset->mStopColor .CalcColor (lastStopFrame);
262
+
263
+ sRGBColor stopColor2 = sRGBColor::FromABGR (stopColor);
264
+ stopColor2.a *= stopOpacity * aGraphicOpacity;
265
+ return do_AddRef (new gfxPattern (ToDeviceColor (stopColor2)));
288
266
}
289
267
290
268
// Get the transform list (if there is one). We do this after the returns
@@ -323,16 +301,23 @@ already_AddRefed<gfxPattern> SVGGradientFrame::GetPaintServerPattern(
323
301
324
302
gradient->SetMatrix (patternMatrix);
325
303
326
- if (StyleSVG ()->mColorInterpolation == StyleColorInterpolation::Linearrgb) {
327
- static constexpr auto interpolationMethod = StyleColorInterpolationMethod{
328
- StyleColorSpace::SrgbLinear, StyleHueInterpolationMethod::Shorter};
329
- SVGColorStopInterpolator interpolator (gradient, stops, interpolationMethod);
330
- interpolator.CreateStops ();
331
- } else {
332
- // setup standard sRGB stops
333
- for (const auto & stop : stops) {
334
- gradient->AddColorStop (stop.mPosition , ToDeviceColor (stop.mColor ));
335
- }
304
+ // setup stops
305
+ float lastOffset = 0 .0f ;
306
+
307
+ for (uint32_t i = 0 ; i < nStops; i++) {
308
+ float offset, stopOpacity;
309
+ nscolor stopColor;
310
+
311
+ GetStopInformation (stopFrames[i], &offset, &stopColor, &stopOpacity);
312
+
313
+ if (offset < lastOffset)
314
+ offset = lastOffset;
315
+ else
316
+ lastOffset = offset;
317
+
318
+ sRGBColor stopColor2 = sRGBColor::FromABGR (stopColor);
319
+ stopColor2.a *= stopOpacity * aGraphicOpacity;
320
+ gradient->AddColorStop (offset, ToDeviceColor (stopColor2));
336
321
}
337
322
338
323
return gradient.forget ();
@@ -366,16 +351,15 @@ SVGGradientFrame* SVGGradientFrame::GetReferencedGradient() {
366
351
return do_QueryFrame (SVGObserverUtils::GetAndObserveTemplate (this , GetHref));
367
352
}
368
353
369
- void SVGGradientFrame::GetStops (nsTArray<ColorStop >* aStops,
370
- float aGraphicOpacity) {
371
- float lastPosition = 0 . 0f ;
372
- for ( const auto * stopFrame : mFrames ) {
354
+ void SVGGradientFrame::GetStopFrames (nsTArray<nsIFrame* >* aStopFrames) {
355
+ nsIFrame* stopFrame = nullptr ;
356
+ for (stopFrame = mFrames . FirstChild (); stopFrame ;
357
+ stopFrame = stopFrame-> GetNextSibling () ) {
373
358
if (stopFrame->IsSVGStopFrame ()) {
374
- aStops->AppendElement (
375
- GetStopInformation (stopFrame, aGraphicOpacity, lastPosition));
359
+ aStopFrames->AppendElement (stopFrame);
376
360
}
377
361
}
378
- if (aStops ->Length () > 0 ) {
362
+ if (aStopFrames ->Length () > 0 ) {
379
363
return ;
380
364
}
381
365
@@ -393,7 +377,7 @@ void SVGGradientFrame::GetStops(nsTArray<ColorStop>* aStops,
393
377
394
378
SVGGradientFrame* next = GetReferencedGradient ();
395
379
if (next) {
396
- next->GetStops (aStops, aGraphicOpacity );
380
+ next->GetStopFrames (aStopFrames );
397
381
}
398
382
}
399
383
0 commit comments