Bug 1323912 - Part 3. Pass opacity in gradient-mask painting path. draft
authorcku <cku@mozilla.com>
Wed, 04 Jan 2017 01:05:05 +0800
changeset 456118 1cccfb8fb4270f4c526dcb78cce7cbf234a577c3
parent 456117 47b07f413fde4c3ba38f8dab6aa29e5aed6fbdd8
child 456119 d09f4c0a6c3f97351805560bcf4b2e9df11681ec
push id40410
push userbmo:cku@mozilla.com
push dateThu, 05 Jan 2017 02:50:43 +0000
bugs1323912
milestone53.0a1
Bug 1323912 - Part 3. Pass opacity in gradient-mask painting path. MozReview-Commit-ID: E2RdOHGoia8
layout/painting/nsCSSRendering.cpp
layout/painting/nsCSSRendering.h
--- a/layout/painting/nsCSSRendering.cpp
+++ b/layout/painting/nsCSSRendering.cpp
@@ -2781,17 +2781,18 @@ void
 nsCSSRendering::PaintGradient(nsPresContext* aPresContext,
                               nsRenderingContext& aRenderingContext,
                               nsStyleGradient* aGradient,
                               const nsRect& aDirtyRect,
                               const nsRect& aDest,
                               const nsRect& aFillArea,
                               const nsSize& aRepeatSize,
                               const CSSIntRect& aSrc,
-                              const nsSize& aIntrinsicSize)
+                              const nsSize& aIntrinsicSize,
+                              float aOpacity)
 {
   PROFILER_LABEL("nsCSSRendering", "PaintGradient",
     js::ProfileEntry::Category::GRAPHICS);
 
   Telemetry::AutoTimer<Telemetry::GRADIENT_DURATION, Telemetry::Microsecond> gradientTimer;
   if (aDest.IsEmpty() || aFillArea.IsEmpty()) {
     return;
   }
@@ -3130,16 +3131,17 @@ nsCSSRendering::PaintGradient(nsPresCont
   // which is a lookup table used to evaluate the gradient. This surface can use
   // much memory (ram and/or GPU ram) and can be expensive to create. So we cache it.
   // The cache key correlates 1:1 with the arguments for CreateGradientStops (also the implied backend type)
   // Note that GradientStop is a simple struct with a stop value (while GradientStops has the surface).
   nsTArray<gfx::GradientStop> rawStops(stops.Length());
   rawStops.SetLength(stops.Length());
   for(uint32_t i = 0; i < stops.Length(); i++) {
     rawStops[i].color = stops[i].mColor;
+    rawStops[i].color.a *= aOpacity;
     rawStops[i].offset = stopScale * (stops[i].mPosition - stopOrigin);
   }
   RefPtr<mozilla::gfx::GradientStops> gs =
     gfxGradientCache::GetOrCreateGradientStops(ctx->GetDrawTarget(),
                                                rawStops,
                                                isRepeat ? gfx::ExtendMode::REPEAT : gfx::ExtendMode::CLAMP);
   gradientPattern->SetColorStops(gs);
 
@@ -3205,16 +3207,17 @@ nsCSSRendering::PaintGradient(nsPresCont
       ctx->Rectangle(fillRect);
 
       gfxRect dirtyFillRect = fillRect.Intersect(dirtyAreaToFill);
       gfxRect fillRectRelativeToTile = dirtyFillRect - tileRect.TopLeft();
       Color edgeColor;
       if (aGradient->mShape == NS_STYLE_GRADIENT_SHAPE_LINEAR && !isRepeat &&
           RectIsBeyondLinearGradientEdge(fillRectRelativeToTile, matrix, stops,
                                          gradientStart, gradientEnd, &edgeColor)) {
+        edgeColor.a = aOpacity;
         ctx->SetColor(edgeColor);
       } else {
         ctx->SetMatrix(
           ctx->CurrentMatrix().Copy().Translate(tileRect.TopLeft()));
         ctx->SetPattern(gradientPattern);
       }
       ctx->Fill();
       ctx->SetMatrix(ctm);
@@ -5703,17 +5706,18 @@ nsImageRenderer::Draw(nsPresContext*    
                                            ConvertImageRendererToDrawFlags(mFlags),
                                            mExtendMode, aOpacity);
       break;
     }
     case eStyleImageType_Gradient:
     {
       nsCSSRendering::PaintGradient(aPresContext, aRenderingContext,
                                     mGradientData, aDirtyRect,
-                                    aDest, aFill, aRepeatSize, aSrc, mSize);
+                                    aDest, aFill, aRepeatSize, aSrc, mSize,
+                                    aOpacity);
       break;
     }
     case eStyleImageType_Element:
     {
       RefPtr<gfxDrawable> drawable = DrawableForElement(aDest,
                                                           aRenderingContext);
       if (!drawable) {
         NS_WARNING("Could not create drawable for element");
--- a/layout/painting/nsCSSRendering.h
+++ b/layout/painting/nsCSSRendering.h
@@ -474,17 +474,18 @@ struct nsCSSRendering {
   static void PaintGradient(nsPresContext* aPresContext,
                             nsRenderingContext& aRenderingContext,
                             nsStyleGradient* aGradient,
                             const nsRect& aDirtyRect,
                             const nsRect& aDest,
                             const nsRect& aFill,
                             const nsSize& aRepeatSize,
                             const mozilla::CSSIntRect& aSrc,
-                            const nsSize& aIntrinsiceSize);
+                            const nsSize& aIntrinsiceSize,
+                            float aOpacity = 1.0);
 
   /**
    * Find the frame whose background style should be used to draw the
    * canvas background. aForFrame must be the frame for the root element
    * whose background style should be used. This function will return
    * aForFrame unless the <body> background should be propagated, in
    * which case we return the frame associated with the <body>'s background.
    */