Bug 1620328 - Set conic-gradient angle range on Skia. r=lsalzman
authorTim Nguyen <ntim.bugs@gmail.com>
Sun, 08 Mar 2020 21:46:06 +0000
changeset 517487 24dc59fa7381d59c6c72e45bd65199fb71bf3043
parent 517486 f714fc6d0d908979703f4c04961c79a808ec05fd
child 517488 cad7268d33b0b922373221a1f34b4fbdb7884288
push id37195
push useraiakab@mozilla.com
push dateMon, 09 Mar 2020 09:18:41 +0000
treeherdermozilla-central@7ac664c14598 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerslsalzman
bugs1620328
milestone75.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1620328 - Set conic-gradient angle range on Skia. r=lsalzman Differential Revision: https://phabricator.services.mozilla.com/D65910
gfx/2d/2D.h
gfx/2d/DrawTargetSkia.cpp
gfx/2d/DrawTargetWrapAndRecord.cpp
gfx/2d/PatternHelpers.h
gfx/2d/RecordedEvent.h
gfx/2d/RecordedEventImpl.h
gfx/thebes/gfxPattern.cpp
gfx/thebes/gfxPattern.h
layout/painting/nsCSSRenderingGradients.cpp
--- a/gfx/2d/2D.h
+++ b/gfx/2d/2D.h
@@ -293,24 +293,32 @@ class RadialGradientPattern : public Pat
 /**
  * This class is used for Conic Gradient Patterns, the gradient stops are
  * stored in a separate object and are backend dependent. This class itself
  * may be used on the stack.
  */
 class ConicGradientPattern : public Pattern {
  public:
   /// For constructor parameter description, see member data documentation.
-  ConicGradientPattern(const Point& aCenter, Float aAngle,
-                       GradientStops* aStops, const Matrix& aMatrix = Matrix())
-      : mCenter(aCenter), mAngle(aAngle), mStops(aStops), mMatrix(aMatrix) {}
+  ConicGradientPattern(const Point& aCenter, Float aAngle, Float aStartOffset,
+                       Float aEndOffset, GradientStops* aStops,
+                       const Matrix& aMatrix = Matrix())
+      : mCenter(aCenter),
+        mAngle(aAngle),
+        mStartOffset(aStartOffset),
+        mEndOffset(aEndOffset),
+        mStops(aStops),
+        mMatrix(aMatrix) {}
 
   PatternType GetType() const override { return PatternType::CONIC_GRADIENT; }
 
   Point mCenter;  //!< Center of the gradient
   Float mAngle;   //!< Start angle of gradient
+  Float mStartOffset;  // Offset of first stop
+  Float mEndOffset;    // Offset of last stop
   RefPtr<GradientStops>
       mStops;      /**< GradientStops object for this gradient, this
                         should match the backend type of the draw target
                         this pattern will be used with. */
   Matrix mMatrix;  //!< A matrix that transforms the pattern into user space
 };
 
 /**
--- a/gfx/2d/DrawTargetSkia.cpp
+++ b/gfx/2d/DrawTargetSkia.cpp
@@ -522,19 +522,22 @@ static void SetPaintPattern(SkPaint& aPa
 
         // Skia's sweep gradient angles are relative to the x-axis, not the
         // y-axis.
         Float angle = (pat.mAngle * 180.0 / M_PI) - 90.0;
         if (angle != 0.0) {
           mat.preRotate(angle, cx, cy);
         }
 
+        SkTileMode mode = ExtendModeToTileMode(stops->mExtendMode, Axis::BOTH);
         sk_sp<SkShader> shader = SkGradientShader::MakeSweep(
             cx, cy, &stops->mColors.front(), &stops->mPositions.front(),
-            stops->mCount, 0, &mat);
+            stops->mCount, mode, 360 * pat.mStartOffset, 360 * pat.mEndOffset,
+            0, &mat);
+
         if (shader) {
           aPaint.setShader(shader);
         } else {
           aPaint.setColor(SK_ColorTRANSPARENT);
         }
       }
       break;
     }
--- a/gfx/2d/DrawTargetWrapAndRecord.cpp
+++ b/gfx/2d/DrawTargetWrapAndRecord.cpp
@@ -257,18 +257,19 @@ struct AdjustedPattern final {
             radGradPat->mRadius2, GetGradientStops(radGradPat->mStops),
             radGradPat->mMatrix);
         return mPattern;
       }
       case PatternType::CONIC_GRADIENT: {
         ConicGradientPattern* conGradPat =
             static_cast<ConicGradientPattern*>(mOrigPattern);
         mPattern = new (mConGradPat) ConicGradientPattern(
-            conGradPat->mCenter, conGradPat->mAngle,
-            GetGradientStops(conGradPat->mStops), conGradPat->mMatrix);
+            conGradPat->mCenter, conGradPat->mAngle, conGradPat->mStartOffset,
+            conGradPat->mEndOffset, GetGradientStops(conGradPat->mStops),
+            conGradPat->mMatrix);
         return mPattern;
       }
       default:
         return new (mColPat) ColorPattern(Color());
     }
 
     return mPattern;
   }
--- a/gfx/2d/PatternHelpers.h
+++ b/gfx/2d/PatternHelpers.h
@@ -86,21 +86,21 @@ class GeneralPattern final {
       Float aRadius2, GradientStops* aStops, const Matrix& aMatrix = Matrix()) {
     MOZ_ASSERT(!mPattern);
     mPattern = new (mRadialGradientPattern.addr()) RadialGradientPattern(
         aCenter1, aCenter2, aRadius1, aRadius2, aStops, aMatrix);
     return mRadialGradientPattern.addr();
   }
 
   ConicGradientPattern* InitConicGradientPattern(
-      const Point& aCenter, Float aAngle, GradientStops* aStops,
-      const Matrix& aMatrix = Matrix()) {
+      const Point& aCenter, Float aAngle, Float aStartOffset, Float aEndOffset,
+      GradientStops* aStops, const Matrix& aMatrix = Matrix()) {
     MOZ_ASSERT(!mPattern);
-    mPattern = new (mConicGradientPattern.addr())
-        ConicGradientPattern(aCenter, aAngle, aStops, aMatrix);
+    mPattern = new (mConicGradientPattern.addr()) ConicGradientPattern(
+        aCenter, aAngle, aStartOffset, aEndOffset, aStops, aMatrix);
     return mConicGradientPattern.addr();
   }
 
   SurfacePattern* InitSurfacePattern(
       SourceSurface* aSourceSurface, ExtendMode aExtendMode,
       const Matrix& aMatrix = Matrix(),
       SamplingFilter aSamplingFilter = SamplingFilter::GOOD,
       const IntRect& aSamplingRect = IntRect()) {
--- a/gfx/2d/RecordedEvent.h
+++ b/gfx/2d/RecordedEvent.h
@@ -128,16 +128,18 @@ struct RadialGradientPatternStorage {
   Float mRadius2;
   ReferencePtr mStops;
   Matrix mMatrix;
 };
 
 struct ConicGradientPatternStorage {
   Point mCenter;
   Float mAngle;
+  Float mStartOffset;
+  Float mEndOffset;
   ReferencePtr mStops;
   Matrix mMatrix;
 };
 
 struct SurfacePatternStorage {
   ExtendMode mExtend;
   SamplingFilter mSamplingFilter;
   ReferencePtr mSurface;
--- a/gfx/2d/RecordedEventImpl.h
+++ b/gfx/2d/RecordedEventImpl.h
@@ -1675,16 +1675,18 @@ inline void RecordedEvent::StorePattern(
     case PatternType::CONIC_GRADIENT: {
       ConicGradientPatternStorage* store =
           reinterpret_cast<ConicGradientPatternStorage*>(
               &aDestination.mStorage);
       const ConicGradientPattern* pat =
           static_cast<const ConicGradientPattern*>(&aSource);
       store->mCenter = pat->mCenter;
       store->mAngle = pat->mAngle;
+      store->mStartOffset = pat->mStartOffset;
+      store->mEndOffset = pat->mEndOffset;
       store->mMatrix = pat->mMatrix;
       store->mStops = pat->mStops.get();
       return;
     }
     case PatternType::SURFACE: {
       SurfacePatternStorage* store =
           reinterpret_cast<SurfacePatternStorage*>(&aDestination.mStorage);
       const SurfacePattern* pat = static_cast<const SurfacePattern*>(&aSource);
@@ -1827,17 +1829,18 @@ inline void RecordedEvent::OutputSimpleP
               << store->mCenter2.y << ") Radius 2: " << store->mRadius2;
       return;
     }
     case PatternType::CONIC_GRADIENT: {
       const ConicGradientPatternStorage* store =
           reinterpret_cast<const ConicGradientPatternStorage*>(
               &aStorage.mStorage);
       aOutput << "ConicGradient (Center: (" << store->mCenter.x << ", "
-              << store->mCenter.y << ") Angle: " << store->mAngle;
+              << store->mCenter.y << ") Angle: " << store->mAngle
+              << " Range:" << store->mStartOffset << " - " << store->mEndOffset;
       return;
     }
     case PatternType::SURFACE: {
       const SurfacePatternStorage* store =
           reinterpret_cast<const SurfacePatternStorage*>(&aStorage.mStorage);
       aOutput << "Surface (0x" << store->mSurface << ")";
       return;
     }
@@ -2178,17 +2181,18 @@ struct GenericPattern {
                             : nullptr,
             storage->mMatrix);
         return mPattern;
       }
       case PatternType::CONIC_GRADIENT: {
         ConicGradientPatternStorage* storage =
             reinterpret_cast<ConicGradientPatternStorage*>(&mStorage->mStorage);
         mPattern = new (mConGradPat) ConicGradientPattern(
-            storage->mCenter, storage->mAngle,
+            storage->mCenter, storage->mAngle, storage->mStartOffset,
+            storage->mEndOffset,
             storage->mStops ? mTranslator->LookupGradientStops(storage->mStops)
                             : nullptr,
             storage->mMatrix);
         return mPattern;
       }
       default:
         return new (mColPat) ColorPattern(Color());
     }
--- a/gfx/thebes/gfxPattern.cpp
+++ b/gfx/thebes/gfxPattern.cpp
@@ -33,19 +33,21 @@ gfxPattern::gfxPattern(gfxFloat x0, gfxF
 gfxPattern::gfxPattern(gfxFloat cx0, gfxFloat cy0, gfxFloat radius0,
                        gfxFloat cx1, gfxFloat cy1, gfxFloat radius1)
     : mExtend(ExtendMode::CLAMP) {
   mGfxPattern.InitRadialGradientPattern(Point(cx0, cy0), Point(cx1, cy1),
                                         radius0, radius1, nullptr);
 }
 
 // conic
-gfxPattern::gfxPattern(gfxFloat cx, gfxFloat cy, gfxFloat angle)
+gfxPattern::gfxPattern(gfxFloat cx, gfxFloat cy, gfxFloat angle,
+                       gfxFloat startOffset, gfxFloat endOffset)
     : mExtend(ExtendMode::CLAMP) {
-  mGfxPattern.InitConicGradientPattern(Point(cx, cy), angle, nullptr);
+  mGfxPattern.InitConicGradientPattern(Point(cx, cy), angle, startOffset,
+                                       endOffset, nullptr);
 }
 
 // Azure
 gfxPattern::gfxPattern(SourceSurface* aSurface,
                        const Matrix& aPatternToUserSpace)
     : mPatternToUserSpace(aPatternToUserSpace), mExtend(ExtendMode::CLAMP) {
   mGfxPattern.InitSurfacePattern(
       aSurface, mExtend, Matrix(),  // matrix is overridden in GetPattern()
--- a/gfx/thebes/gfxPattern.h
+++ b/gfx/thebes/gfxPattern.h
@@ -21,17 +21,18 @@ class gfxPattern final {
   NS_INLINE_DECL_REFCOUNTING(gfxPattern)
 
  public:
   explicit gfxPattern(const mozilla::gfx::Color& aColor);
   // gradients
   gfxPattern(gfxFloat x0, gfxFloat y0, gfxFloat x1, gfxFloat y1);  // linear
   gfxPattern(gfxFloat cx0, gfxFloat cy0, gfxFloat radius0, gfxFloat cx1,
              gfxFloat cy1, gfxFloat radius1);            // radial
-  gfxPattern(gfxFloat cx, gfxFloat cy, gfxFloat angle);  // conic
+  gfxPattern(gfxFloat cx, gfxFloat cy, gfxFloat angle, gfxFloat startOffset,
+             gfxFloat endOffset);  // conic
   gfxPattern(mozilla::gfx::SourceSurface* aSurface,
              const mozilla::gfx::Matrix& aPatternToUserSpace);
 
   void AddColorStop(gfxFloat offset, const mozilla::gfx::Color& c);
   void SetColorStops(mozilla::gfx::GradientStops* aStops);
 
   // This should only be called on a cairo pattern that we want to use with
   // Azure. We will read back the color stops from cairo and try to look
--- a/layout/painting/nsCSSRenderingGradients.cpp
+++ b/layout/painting/nsCSSRenderingGradients.cpp
@@ -892,17 +892,17 @@ void nsCSSGradientRenderer::Paint(gfxCon
     }
     stopDelta = 0.0;
   }
 
   // Don't normalize non-repeating or degenerate gradients below 0..1
   // This keeps the gradient line as large as the box and doesn't
   // lets us avoiding having to get padding correct for stops
   // at 0 and 1
-  if (!mGradient->Repeating() || stopDelta == 0.0) {
+  if (!mGradient->Repeating() || (!mGradient->IsConic() && stopDelta == 0.0)) {
     stopOrigin = std::min(stopOrigin, 0.0);
     stopEnd = std::max(stopEnd, 1.0);
   }
   stopScale = 1.0 / (stopEnd - stopOrigin);
 
   // Create the gradient pattern.
   RefPtr<gfxPattern> gradientPattern;
   gfxPoint gradientStart;
@@ -946,17 +946,18 @@ void nsCSSGradientRenderer::Paint(gfxCon
       // Recall that this is the transform from user space to pattern space.
       // So to stretch the ellipse by factor of P vertically, we scale
       // user coordinates by 1/P.
       matrix.PreTranslate(mLineStart);
       matrix.PreScale(1.0, mRadiusX / mRadiusY);
       matrix.PreTranslate(-mLineStart);
     }
   } else {
-    gradientPattern = new gfxPattern(mCenter.x, mCenter.y, mAngle);
+    gradientPattern =
+        new gfxPattern(mCenter.x, mCenter.y, mAngle, stopOrigin, stopEnd);
   }
   // Use a pattern transform to take account of source and dest rects
   matrix.PreTranslate(gfxPoint(mPresContext->CSSPixelsToDevPixels(aSrc.x),
                                mPresContext->CSSPixelsToDevPixels(aSrc.y)));
   matrix.PreScale(
       gfxFloat(nsPresContext::CSSPixelsToAppUnits(aSrc.width)) / aDest.width,
       gfxFloat(nsPresContext::CSSPixelsToAppUnits(aSrc.height)) / aDest.height);
   gradientPattern->SetMatrix(matrix);