Bug 1273706 - Part 9: Expose nsComputedDOMStyle::SetValueToStyleImage as a static method so that we can compute serialized computed values for gradients. draft
authorJonathan Chan <jyc@eqv.io>
Mon, 15 Aug 2016 00:48:18 -0700
changeset 400597 21b2cd5b5e0f05a77762e8545c5a7b4d3634ee2f
parent 400596 419101843f71c2ec152ef8d7df5693265f219aa1
child 400598 9e47e0dc1245e1062fbf1a834ed3173a662f4133
push id26211
push userjchan@mozilla.com
push dateMon, 15 Aug 2016 08:07:32 +0000
bugs1273706
milestone51.0a1
Bug 1273706 - Part 9: Expose nsComputedDOMStyle::SetValueToStyleImage as a static method so that we can compute serialized computed values for gradients. SetValueToStyleImage doesn't use any member variables in itself or in the methods it calls, but it used various functions that were also non-static. The reason they were non-static is because in the call chain is a function that takes a member function pointer, which requires an object pointer, SetValueToCoord. The member function pointer argument is nullptr by default and not used by any of the functions used by SetValueToStyleImage. SetValueToCoord is modified to take a class object pointer argument and calls are updated appropriately to pass either nullptr or this. This is a little unpleasant, but its a useful method that a later patch needs to use (CSSComputedValue::AppendToString). MozReview-Commit-ID: Kc6KrZK2Dn5
layout/style/nsComputedDOMStyle.cpp
layout/style/nsComputedDOMStyle.h
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -926,17 +926,17 @@ already_AddRefed<CSSValue>
 nsComputedDOMStyle::DoGetStackSizing()
 {
   RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
   val->SetIdent(StyleXUL()->mStretchStack ? eCSSKeyword_stretch_to_fit :
                 eCSSKeyword_ignore);
   return val.forget();
 }
 
-void
+/* static */ void
 nsComputedDOMStyle::SetToRGBAColor(nsROCSSPrimitiveValue* aValue,
                                    nscolor aColor)
 {
   if (NS_GET_A(aColor) == 0) {
     aValue->SetIdent(eCSSKeyword_transparent);
     return;
   }
 
@@ -1222,30 +1222,29 @@ nsComputedDOMStyle::DoGetTransformOrigin
 
   /* Store things as a value list */
   RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(false);
 
   /* Now, get the values. */
   const nsStyleDisplay* display = StyleDisplay();
 
   RefPtr<nsROCSSPrimitiveValue> width = new nsROCSSPrimitiveValue;
-  SetValueToCoord(width, display->mTransformOrigin[0], false,
+  SetValueToCoord(width, display->mTransformOrigin[0], false, this,
                   &nsComputedDOMStyle::GetFrameBoundsWidthForTransform);
   valueList->AppendCSSValue(width.forget());
 
   RefPtr<nsROCSSPrimitiveValue> height = new nsROCSSPrimitiveValue;
-  SetValueToCoord(height, display->mTransformOrigin[1], false,
+  SetValueToCoord(height, display->mTransformOrigin[1], false, this,
                   &nsComputedDOMStyle::GetFrameBoundsHeightForTransform);
   valueList->AppendCSSValue(height.forget());
 
   if (display->mTransformOrigin[2].GetUnit() != eStyleUnit_Coord ||
       display->mTransformOrigin[2].GetCoordValue() != 0) {
     RefPtr<nsROCSSPrimitiveValue> depth = new nsROCSSPrimitiveValue;
-    SetValueToCoord(depth, display->mTransformOrigin[2], false,
-                    nullptr);
+    SetValueToCoord(depth, display->mTransformOrigin[2], false);
     valueList->AppendCSSValue(depth.forget());
   }
 
   return valueList.forget();
 }
 
 /* Convert the stored representation into a list of two values and then hand
  * it back.
@@ -1259,22 +1258,22 @@ nsComputedDOMStyle::DoGetPerspectiveOrig
 
   /* Store things as a value list */
   RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(false);
 
   /* Now, get the values. */
   const nsStyleDisplay* display = StyleDisplay();
 
   RefPtr<nsROCSSPrimitiveValue> width = new nsROCSSPrimitiveValue;
-  SetValueToCoord(width, display->mPerspectiveOrigin[0], false,
+  SetValueToCoord(width, display->mPerspectiveOrigin[0], false, this,
                   &nsComputedDOMStyle::GetFrameBoundsWidthForTransform);
   valueList->AppendCSSValue(width.forget());
 
   RefPtr<nsROCSSPrimitiveValue> height = new nsROCSSPrimitiveValue;
-  SetValueToCoord(height, display->mPerspectiveOrigin[1], false,
+  SetValueToCoord(height, display->mPerspectiveOrigin[1], false, this,
                   &nsComputedDOMStyle::GetFrameBoundsHeightForTransform);
   valueList->AppendCSSValue(height.forget());
 
   return valueList.forget();
 }
 
 already_AddRefed<CSSValue>
 nsComputedDOMStyle::DoGetPerspective()
@@ -1914,17 +1913,17 @@ AppendCSSGradientToBoxPosition(const nsS
     aString.AppendLiteral(" right");
   } else if (xValue != 0.5f) { // do not write "center" keyword
     NS_NOTREACHED("invalid box position");
   }
 
   aNeedSep = true;
 }
 
-void
+/* static */ void
 nsComputedDOMStyle::GetCSSGradientString(const nsStyleGradient* aGradient,
                                          nsAString& aString)
 {
   if (!aGradient->mLegacySyntax) {
     aString.Truncate();
   } else {
     aString.AssignLiteral("-moz-");
   }
@@ -2045,17 +2044,17 @@ nsComputedDOMStyle::GetCSSGradientString
     }
     needSep = true;
   }
 
   aString.Append(')');
 }
 
 // -moz-image-rect(<uri>, <top>, <right>, <bottom>, <left>)
-void
+/* static */ void
 nsComputedDOMStyle::GetImageRectString(nsIURI* aURI,
                                        const nsStyleSides& aCropRect,
                                        nsString& aString)
 {
   RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(true);
 
   // <uri>
   RefPtr<nsROCSSPrimitiveValue> valURI = new nsROCSSPrimitiveValue;
@@ -2072,42 +2071,44 @@ nsComputedDOMStyle::GetImageRectString(n
   nsAutoString argumentString;
   valueList->GetCssText(argumentString);
 
   aString = NS_LITERAL_STRING("-moz-image-rect(") +
             argumentString +
             NS_LITERAL_STRING(")");
 }
 
+namespace mozilla {
+
 void
-nsComputedDOMStyle::SetValueToStyleImage(const nsStyleImage& aStyleImage,
-                                         nsROCSSPrimitiveValue* aValue)
+SetValueToStyleImage(const nsStyleImage& aStyleImage,
+                     nsROCSSPrimitiveValue* aValue)
 {
   switch (aStyleImage.GetType()) {
     case eStyleImageType_Image:
     {
       imgIRequest *req = aStyleImage.GetImageData();
       nsCOMPtr<nsIURI> uri;
       req->GetURI(getter_AddRefs(uri));
 
       const UniquePtr<nsStyleSides>& cropRect = aStyleImage.GetCropRect();
       if (cropRect) {
         nsAutoString imageRectString;
-        GetImageRectString(uri, *cropRect, imageRectString);
+        nsComputedDOMStyle::GetImageRectString(uri, *cropRect, imageRectString);
         aValue->SetString(imageRectString);
       } else {
         aValue->SetURI(uri);
       }
       break;
     }
     case eStyleImageType_Gradient:
     {
       nsAutoString gradientString;
-      GetCSSGradientString(aStyleImage.GetGradientData(),
-                           gradientString);
+      nsComputedDOMStyle::GetCSSGradientString(aStyleImage.GetGradientData(),
+                                               gradientString);
       aValue->SetString(gradientString);
       break;
     }
     case eStyleImageType_Element:
     {
       nsAutoString elementId;
       nsStyleUtil::AppendEscapedCSSIdent(
         nsDependentString(aStyleImage.GetElementId()), elementId);
@@ -2121,16 +2122,18 @@ nsComputedDOMStyle::SetValueToStyleImage
       aValue->SetIdent(eCSSKeyword_none);
       break;
     default:
       NS_NOTREACHED("unexpected image type");
       break;
   }
 }
 
+} // namespace mozilla
+
 already_AddRefed<CSSValue>
 nsComputedDOMStyle::DoGetImageLayerImage(const nsStyleImageLayers& aLayers)
 {
   RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(true);
 
   for (uint32_t i = 0, i_end = aLayers.mImageCount; i < i_end; ++i) {
     RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
 
@@ -2145,17 +2148,17 @@ nsComputedDOMStyle::DoGetImageLayerImage
     //    Instead, we store the local URI in one place -- on Layer::mSourceURI.
     //    Hence, we must serialize using mSourceURI (instead of
     //    SetValueToStyleImage()/mImage) in this case.
     if (aLayers.mLayers[i].mSourceURI.IsLocalRef()) {
       // This is how we represent a 'mask-image' reference for a local URI,
       // such as 'mask-image:url(#mymask)' or 'mask:url(#mymask)'
       SetValueToFragmentOrURL(&aLayers.mLayers[i].mSourceURI, val);
     } else {
-      SetValueToStyleImage(image, val);
+      mozilla::SetValueToStyleImage(image, val);
     }
 
     valueList->AppendCSSValue(val.forget());
   }
 
   return valueList.forget();
 }
 
@@ -2528,34 +2531,34 @@ nsComputedDOMStyle::AppendGridLineNames(
 }
 
 already_AddRefed<CSSValue>
 nsComputedDOMStyle::GetGridTrackSize(const nsStyleCoord& aMinValue,
                                      const nsStyleCoord& aMaxValue)
 {
   if (aMinValue == aMaxValue) {
     RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
-    SetValueToCoord(val, aMinValue, true,
-                    nullptr, nsCSSProps::kGridTrackBreadthKTable);
+    SetValueToCoord(val, aMinValue, true, nullptr, nullptr,
+                    nsCSSProps::kGridTrackBreadthKTable);
     return val.forget();
   }
 
   RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
   nsAutoString argumentStr, minmaxStr;
   minmaxStr.AppendLiteral("minmax(");
 
-  SetValueToCoord(val, aMinValue, true,
-                  nullptr, nsCSSProps::kGridTrackBreadthKTable);
+  SetValueToCoord(val, aMinValue, true, nullptr, nullptr,
+                  nsCSSProps::kGridTrackBreadthKTable);
   val->GetCssText(argumentStr);
   minmaxStr.Append(argumentStr);
 
   minmaxStr.AppendLiteral(", ");
 
-  SetValueToCoord(val, aMaxValue, true,
-                  nullptr, nsCSSProps::kGridTrackBreadthKTable);
+  SetValueToCoord(val, aMaxValue, true, nullptr, nullptr,
+                  nsCSSProps::kGridTrackBreadthKTable);
   val->GetCssText(argumentStr);
   minmaxStr.Append(argumentStr);
 
   minmaxStr.Append(char16_t(')'));
   val->SetString(minmaxStr);
   return val.forget();
 }
 
@@ -3587,17 +3590,17 @@ nsComputedDOMStyle::DoGetLineHeight()
 {
   RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
 
   nscoord lineHeight;
   if (GetLineHeightCoord(lineHeight)) {
     val->SetAppUnits(lineHeight);
   } else {
     SetValueToCoord(val, StyleText()->mLineHeight, true,
-                    nullptr, nsCSSProps::kLineHeightKTable);
+                    nullptr, nullptr, nsCSSProps::kLineHeightKTable);
   }
 
   return val.forget();
 }
 
 already_AddRefed<CSSValue>
 nsComputedDOMStyle::DoGetRubyAlign()
 {
@@ -3616,16 +3619,17 @@ nsComputedDOMStyle::DoGetRubyPosition()
   return val.forget();
 }
 
 already_AddRefed<CSSValue>
 nsComputedDOMStyle::DoGetVerticalAlign()
 {
   RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
   SetValueToCoord(val, StyleDisplay()->mVerticalAlign, false,
+                  this,
                   &nsComputedDOMStyle::GetLineHeightCoord,
                   nsCSSProps::kVerticalAlignKTable);
   return val.forget();
 }
 
 already_AddRefed<CSSValue>
 nsComputedDOMStyle::CreateTextAlignValue(uint8_t aAlign, bool aAlignTrue,
                                          const KTableEntry aTable[])
@@ -3835,17 +3839,17 @@ nsComputedDOMStyle::DoGetTextEmphasisSty
   valueList->AppendCSSValue(shapeVal.forget());
   return valueList.forget();
 }
 
 already_AddRefed<CSSValue>
 nsComputedDOMStyle::DoGetTextIndent()
 {
   RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
-  SetValueToCoord(val, StyleText()->mTextIndent, false,
+  SetValueToCoord(val, StyleText()->mTextIndent, false, this,
                   &nsComputedDOMStyle::GetCBContentWidth);
   return val.forget();
 }
 
 already_AddRefed<CSSValue>
 nsComputedDOMStyle::DoGetTextOrientation()
 {
   RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
@@ -4204,31 +4208,31 @@ nsComputedDOMStyle::DoGetBoxSizing()
 
 already_AddRefed<CSSValue>
 nsComputedDOMStyle::DoGetBorderImageSource()
 {
   const nsStyleBorder* border = StyleBorder();
 
   RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
   const nsStyleImage& image = border->mBorderImageSource;
-  SetValueToStyleImage(image, val);
+  mozilla::SetValueToStyleImage(image, val);
 
   return val.forget();
 }
 
 already_AddRefed<CSSValue>
 nsComputedDOMStyle::DoGetBorderImageSlice()
 {
   RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(false);
 
   const nsStyleBorder* border = StyleBorder();
   // Four slice numbers.
   NS_FOR_CSS_SIDES (side) {
     RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
-    SetValueToCoord(val, border->mBorderImageSlice.Get(side), true, nullptr);
+    SetValueToCoord(val, border->mBorderImageSlice.Get(side), true);
     valueList->AppendCSSValue(val.forget());
   }
 
   // Fill keyword.
   if (NS_STYLE_BORDER_IMAGE_SLICE_FILL == border->mBorderImageFill) {
     RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
     val->SetIdent(eCSSKeyword_fill);
     valueList->AppendCSSValue(val.forget());
@@ -4240,34 +4244,34 @@ nsComputedDOMStyle::DoGetBorderImageSlic
 already_AddRefed<CSSValue>
 nsComputedDOMStyle::DoGetBorderImageWidth()
 {
   const nsStyleBorder* border = StyleBorder();
   RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(false);
   NS_FOR_CSS_SIDES (side) {
     RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
     SetValueToCoord(val, border->mBorderImageWidth.Get(side),
-                    true, nullptr);
+                    true);
     valueList->AppendCSSValue(val.forget());
   }
 
   return valueList.forget();
 }
 
 already_AddRefed<CSSValue>
 nsComputedDOMStyle::DoGetBorderImageOutset()
 {
   RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(false);
 
   const nsStyleBorder* border = StyleBorder();
   // four slice numbers
   NS_FOR_CSS_SIDES (side) {
     RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
     SetValueToCoord(val, border->mBorderImageOutset.Get(side),
-                    true, nullptr);
+                    true);
     valueList->AppendCSSValue(val.forget());
   }
 
   return valueList.forget();
 }
 
 already_AddRefed<CSSValue>
 nsComputedDOMStyle::DoGetBorderImageRepeat()
@@ -4304,17 +4308,17 @@ nsComputedDOMStyle::DoGetFlexBasis()
   //     if (my flex container is horizontal) {
   //       percentageBaseGetter = &nsComputedDOMStyle::GetCBContentWidth;
   //     } else {
   //       percentageBaseGetter = &nsComputedDOMStyle::GetCBContentHeight;
   //     }
   //   }
 
   SetValueToCoord(val, StylePosition()->mFlexBasis, true,
-                  nullptr, nsCSSProps::kWidthKTable);
+                  nullptr, nullptr, nsCSSProps::kWidthKTable);
   return val.forget();
 }
 
 already_AddRefed<CSSValue>
 nsComputedDOMStyle::DoGetFlexDirection()
 {
   RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
   val->SetIdent(
@@ -4786,17 +4790,17 @@ nsComputedDOMStyle::DoGetHeight()
       StyleCoordToNSCoord(positionData->mMinHeight,
                           &nsComputedDOMStyle::GetCBContentHeight, 0, true);
 
     nscoord maxHeight =
       StyleCoordToNSCoord(positionData->mMaxHeight,
                           &nsComputedDOMStyle::GetCBContentHeight,
                           nscoord_MAX, true);
 
-    SetValueToCoord(val, positionData->mHeight, true, nullptr,
+    SetValueToCoord(val, positionData->mHeight, true, nullptr, nullptr,
                     nsCSSProps::kWidthKTable, minHeight, maxHeight);
   }
 
   return val.forget();
 }
 
 already_AddRefed<CSSValue>
 nsComputedDOMStyle::DoGetWidth()
@@ -4830,38 +4834,38 @@ nsComputedDOMStyle::DoGetWidth()
       StyleCoordToNSCoord(positionData->mMinWidth,
                           &nsComputedDOMStyle::GetCBContentWidth, 0, true);
 
     nscoord maxWidth =
       StyleCoordToNSCoord(positionData->mMaxWidth,
                           &nsComputedDOMStyle::GetCBContentWidth,
                           nscoord_MAX, true);
 
-    SetValueToCoord(val, positionData->mWidth, true, nullptr,
+    SetValueToCoord(val, positionData->mWidth, true, nullptr, nullptr,
                     nsCSSProps::kWidthKTable, minWidth, maxWidth);
   }
 
   return val.forget();
 }
 
 already_AddRefed<CSSValue>
 nsComputedDOMStyle::DoGetMaxHeight()
 {
   RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
-  SetValueToCoord(val, StylePosition()->mMaxHeight, true,
+  SetValueToCoord(val, StylePosition()->mMaxHeight, true, this,
                   &nsComputedDOMStyle::GetCBContentHeight,
                   nsCSSProps::kWidthKTable);
   return val.forget();
 }
 
 already_AddRefed<CSSValue>
 nsComputedDOMStyle::DoGetMaxWidth()
 {
   RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
-  SetValueToCoord(val, StylePosition()->mMaxWidth, true,
+  SetValueToCoord(val, StylePosition()->mMaxWidth, true, this,
                   &nsComputedDOMStyle::GetCBContentWidth,
                   nsCSSProps::kWidthKTable);
   return val.forget();
 }
 
 already_AddRefed<CSSValue>
 nsComputedDOMStyle::DoGetMinHeight()
 {
@@ -4871,17 +4875,17 @@ nsComputedDOMStyle::DoGetMinHeight()
   if (eStyleUnit_Auto == minHeight.GetUnit()) {
     // In non-flexbox contexts, "min-height: auto" means "min-height: 0"
     // XXXdholbert For flex items, we should set |minHeight| to the
     // -moz-min-content keyword, instead of 0, once we support -moz-min-content
     // as a height value.
     minHeight.SetCoordValue(0);
   }
 
-  SetValueToCoord(val, minHeight, true,
+  SetValueToCoord(val, minHeight, true, this,
                   &nsComputedDOMStyle::GetCBContentHeight,
                   nsCSSProps::kWidthKTable);
   return val.forget();
 }
 
 already_AddRefed<CSSValue>
 nsComputedDOMStyle::DoGetMinWidth()
 {
@@ -4899,17 +4903,17 @@ nsComputedDOMStyle::DoGetMinWidth()
                  flexContainer->GetType() == nsGkAtoms::flexContainerFrame,
                  "IsFlexItem() lied...?");
 
       if (static_cast<nsFlexContainerFrame*>(flexContainer)->IsHorizontal()) {
         minWidth.SetIntValue(NS_STYLE_WIDTH_MIN_CONTENT, eStyleUnit_Enumerated);
       }
     }
   }
-  SetValueToCoord(val, minWidth, true,
+  SetValueToCoord(val, minWidth, true, this,
                   &nsComputedDOMStyle::GetCBContentWidth,
                   nsCSSProps::kWidthKTable);
   return val.forget();
 }
 
 already_AddRefed<CSSValue>
 nsComputedDOMStyle::DoGetMixBlendMode()
 {
@@ -4958,17 +4962,17 @@ nsComputedDOMStyle::DoGetRight()
 }
 
 already_AddRefed<CSSValue>
 nsComputedDOMStyle::DoGetTop()
 {
   return GetOffsetWidthFor(NS_SIDE_TOP);
 }
 
-nsDOMCSSValueList*
+/* static */ nsDOMCSSValueList*
 nsComputedDOMStyle::GetROCSSValueList(bool aCommaDelimited)
 {
   return new nsDOMCSSValueList(aCommaDelimited, true);
 }
 
 already_AddRefed<CSSValue>
 nsComputedDOMStyle::GetOffsetWidthFor(mozilla::css::Side aSide)
 {
@@ -5271,41 +5275,45 @@ nsComputedDOMStyle::GetBorderStyleFor(mo
 {
   RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
   val->SetIdent(
     nsCSSProps::ValueToKeywordEnum(StyleBorder()->GetBorderStyle(aSide),
                                    nsCSSProps::kBorderStyleKTable));
   return val.forget();
 }
 
-void
+/* static */ void
 nsComputedDOMStyle::SetValueToCoord(nsROCSSPrimitiveValue* aValue,
                                     const nsStyleCoord& aCoord,
                                     bool aClampNegativeCalc,
+                                    nsComputedDOMStyle* aThis,
                                     PercentageBaseGetter aPercentageBaseGetter,
                                     const KTableEntry aTable[],
                                     nscoord aMinAppUnits,
                                     nscoord aMaxAppUnits)
 {
   NS_PRECONDITION(aValue, "Must have a value to work with");
+  MOZ_ASSERT(!!aThis == !!aPercentageBaseGetter,
+             "Must either have both aThis and aPercentageBaseGetter or "
+             "neither.");
 
   switch (aCoord.GetUnit()) {
     case eStyleUnit_Normal:
       aValue->SetIdent(eCSSKeyword_normal);
       break;
 
     case eStyleUnit_Auto:
       aValue->SetIdent(eCSSKeyword_auto);
       break;
 
     case eStyleUnit_Percent:
       {
         nscoord percentageBase;
         if (aPercentageBaseGetter &&
-            (this->*aPercentageBaseGetter)(percentageBase)) {
+            (aThis->*aPercentageBaseGetter)(percentageBase)) {
           nscoord val = NSCoordSaturatingMultiply(percentageBase,
                                                   aCoord.GetPercentValue());
           aValue->SetAppUnits(std::max(aMinAppUnits, std::min(val, aMaxAppUnits)));
         } else {
           aValue->SetPercent(aCoord.GetPercentValue());
         }
       }
       break;
@@ -5341,17 +5349,17 @@ nsComputedDOMStyle::SetValueToCoord(nsRO
         nscoord val = nsRuleNode::ComputeCoordPercentCalc(aCoord, 0);
         if (aClampNegativeCalc && val < 0) {
           MOZ_ASSERT(aCoord.IsCalcUnit(),
                      "parser should have rejected value");
           val = 0;
         }
         aValue->SetAppUnits(std::max(aMinAppUnits, std::min(val, aMaxAppUnits)));
       } else if (aPercentageBaseGetter &&
-                 (this->*aPercentageBaseGetter)(percentageBase)) {
+                 (aThis->*aPercentageBaseGetter)(percentageBase)) {
         nscoord val =
           nsRuleNode::ComputeCoordPercentCalc(aCoord, percentageBase);
         if (aClampNegativeCalc && val < 0) {
           MOZ_ASSERT(aCoord.IsCalcUnit(),
                      "parser should have rejected value");
           val = 0;
         }
         aValue->SetAppUnits(std::max(aMinAppUnits, std::min(val, aMaxAppUnits)));
@@ -5955,17 +5963,17 @@ nsComputedDOMStyle::CreatePrimitiveValue
       const nsTArray<nsStyleCoord>& radii = aStyleBasicShape->Coordinates();
       MOZ_ASSERT(radii.Length() ==
                  (type == StyleBasicShapeType::Circle ? 1 : 2),
                  "wrong number of radii");
       for (size_t i = 0; i < radii.Length(); ++i) {
         nsAutoString radius;
         RefPtr<nsROCSSPrimitiveValue> value = new nsROCSSPrimitiveValue;
         bool clampNegativeCalc = true;
-        SetValueToCoord(value, radii[i], clampNegativeCalc, nullptr,
+        SetValueToCoord(value, radii[i], clampNegativeCalc, nullptr, nullptr,
                         nsCSSProps::kShapeRadiusKTable);
         value->GetCssText(radius);
         shapeFunctionString.Append(radius);
         shapeFunctionString.Append(' ');
       }
       shapeFunctionString.AppendLiteral("at ");
 
       RefPtr<nsDOMCSSValueList> position = GetROCSSValueList(false);
--- a/layout/style/nsComputedDOMStyle.h
+++ b/layout/style/nsComputedDOMStyle.h
@@ -16,16 +16,17 @@
 #include "nsCSSProps.h"
 #include "nsDOMCSSDeclaration.h"
 #include "nsStyleContext.h"
 #include "nsIWeakReferenceUtils.h"
 #include "mozilla/gfx/Types.h"
 #include "nsCoord.h"
 #include "nsColor.h"
 #include "nsIContent.h"
+#include "nsStyleImage.h"
 #include "nsStyleStruct.h"
 
 namespace mozilla {
 namespace dom {
 class Element;
 } // namespace dom
 struct ComputedGridTrackInfo;
 } // namespace mozilla
@@ -39,16 +40,21 @@ class nsROCSSPrimitiveValue;
 class nsStyleCoord;
 class nsStyleCorners;
 struct nsStyleFilter;
 class nsStyleGradient;
 struct nsStyleImage;
 class nsStyleSides;
 struct nsTimingFunction;
 
+namespace mozilla {
+  void SetValueToStyleImage(const nsStyleImage& aStyleImage,
+                            nsROCSSPrimitiveValue* aValue);
+} // namespace mozilla
+
 class nsComputedDOMStyle final : public nsDOMCSSDeclaration
                                , public nsStubMutationObserver
 {
 private:
   // Convenience typedefs:
   typedef nsCSSProps::KTableEntry KTableEntry;
   typedef mozilla::dom::CSSValue CSSValue;
 
@@ -202,21 +208,28 @@ private:
                                                bool aIsBoxShadow);
 
   already_AddRefed<CSSValue> GetBackgroundList(
     uint8_t nsStyleImageLayers::Layer::* aMember,
     uint32_t nsStyleImageLayers::* aCount,
     const nsStyleImageLayers& aLayers,
     const KTableEntry aTable[]);
 
-  void GetCSSGradientString(const nsStyleGradient* aGradient,
-                            nsAString& aString);
-  void GetImageRectString(nsIURI* aURI,
-                          const nsStyleSides& aCropRect,
-                          nsString& aString);
+  // SetValueToStyleImage uses GetCSSGradientString and GetImageRectString. We
+  // would make it a private member function except that it's used by
+  // CSSComputedValue, which has a member function called by this class, and we
+  // can't forward-declare member functions.
+  friend void mozilla::SetValueToStyleImage(const nsStyleImage& aStyleImage,
+                                            nsROCSSPrimitiveValue* aValue);
+
+  static void GetCSSGradientString(const nsStyleGradient* aGradient,
+                                   nsAString& aString);
+  static void GetImageRectString(nsIURI* aURI,
+                                 const nsStyleSides& aCropRect,
+                                 nsString& aString);
   already_AddRefed<CSSValue> GetScrollSnapPoints(const nsStyleCoord& aCoord);
   void AppendTimingFunction(nsDOMCSSValueList *aValueList,
                             const nsTimingFunction& aTimingFunction);
 
   /* Properties queryable as CSSValues.
    * To avoid a name conflict with nsIDOM*CSS2Properties, these are all
    * DoGetXXX instead of GetXXX.
    */
@@ -574,22 +587,20 @@ private:
   already_AddRefed<CSSValue> DoGetClipPath();
   already_AddRefed<CSSValue> DoGetFilter();
   already_AddRefed<CSSValue> DoGetMaskType();
   already_AddRefed<CSSValue> DoGetPaintOrder();
 
   /* Custom properties */
   already_AddRefed<CSSValue> DoGetCustomProperty(const nsAString& aPropertyName);
 
-  nsDOMCSSValueList* GetROCSSValueList(bool aCommaDelimited);
+  static nsDOMCSSValueList* GetROCSSValueList(bool aCommaDelimited);
 
   /* Helper functions */
-  void SetToRGBAColor(nsROCSSPrimitiveValue* aValue, nscolor aColor);
-  void SetValueToStyleImage(const nsStyleImage& aStyleImage,
-                            nsROCSSPrimitiveValue* aValue);
+  static void SetToRGBAColor(nsROCSSPrimitiveValue* aValue, nscolor aColor);
   void SetValueToPositionCoord(
     const nsStyleImageLayers::Position::PositionCoord& aCoord,
     nsROCSSPrimitiveValue* aValue);
   void SetValueToPosition(const nsStyleImageLayers::Position& aPosition,
                           nsDOMCSSValueList* aValueList);
   void SetValueToFragmentOrURL(const FragmentOrURL* aFragmentOrURL,
                                nsROCSSPrimitiveValue* aValue);
 
@@ -608,23 +619,24 @@ private:
    * if not null, is the keyword table to handle eStyleUnit_Enumerated.  When
    * calling SetAppUnits on aValue (for coord or percent values), the value
    * passed in will be clamped to be no less than aMinAppUnits and no more than
    * aMaxAppUnits.
    *
    * XXXbz should caller pass in some sort of bitfield indicating which units
    * can be expected or something?
    */
-  void SetValueToCoord(nsROCSSPrimitiveValue* aValue,
-                       const nsStyleCoord& aCoord,
-                       bool aClampNegativeCalc,
-                       PercentageBaseGetter aPercentageBaseGetter = nullptr,
-                       const KTableEntry aTable[] = nullptr,
-                       nscoord aMinAppUnits = nscoord_MIN,
-                       nscoord aMaxAppUnits = nscoord_MAX);
+  static void SetValueToCoord(nsROCSSPrimitiveValue* aValue,
+                              const nsStyleCoord& aCoord,
+                              bool aClampNegativeCalc,
+                              nsComputedDOMStyle* aThis = nullptr,
+                              PercentageBaseGetter aPercentageBaseGetter = nullptr,
+                              const KTableEntry aTable[] = nullptr,
+                              nscoord aMinAppUnits = nscoord_MIN,
+                              nscoord aMaxAppUnits = nscoord_MAX);
 
   /**
    * If aCoord is a eStyleUnit_Coord returns the nscoord.  If it's
    * eStyleUnit_Percent, attempts to resolve the percentage base and returns
    * the resulting nscoord.  If it's some other unit or a percentge base can't
    * be determined, returns aDefaultValue.
    */
   nscoord StyleCoordToNSCoord(const nsStyleCoord& aCoord,