Bug 1276085: stylo: Support creating and setting gradient stops from Servo r=heycam
authorEmilio Cobos Álvarez <ecoal95@gmail.com>
Fri, 27 May 2016 00:18:09 +0200
changeset 299879 e1b8a20047e913034bc74175b430ea1d544025e7
parent 299878 698ef7cd0e60a14ccdfd929c457ce218e11929a8
child 299880 ae72a7d642b32cea0e425eb14cb6a51de68b67c6
push id77732
push userecoal95@gmail.com
push dateWed, 01 Jun 2016 08:36:33 +0000
treeherdermozilla-inbound@e1b8a20047e9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersheycam
bugs1276085
milestone49.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 1276085: stylo: Support creating and setting gradient stops from Servo r=heycam MozReview-Commit-ID: Gh6CMrf1PE5
layout/style/ServoBindings.cpp
layout/style/ServoBindings.h
layout/style/nsRuleNode.cpp
layout/style/nsStyleStruct.h
--- a/layout/style/ServoBindings.cpp
+++ b/layout/style/ServoBindings.cpp
@@ -328,16 +328,88 @@ Gecko_SetMozBinding(nsStyleDisplay* aDis
 }
 
 void
 Gecko_CopyMozBindingFrom(nsStyleDisplay* aDest, const nsStyleDisplay* aSrc)
 {
   aDest->mBinding = aSrc->mBinding;
 }
 
+
+void
+Gecko_SetNullImageValue(nsStyleImage* aImage)
+{
+  MOZ_ASSERT(aImage);
+  aImage->SetNull();
+}
+
+void
+Gecko_SetGradientImageValue(nsStyleImage* aImage, nsStyleGradient* aGradient)
+{
+  MOZ_ASSERT(aImage);
+  aImage->SetGradientData(aGradient);
+}
+
+void
+Gecko_CopyImageValueFrom(nsStyleImage* aImage, const nsStyleImage* aOther)
+{
+  MOZ_ASSERT(aImage);
+  MOZ_ASSERT(aOther);
+
+  *aImage = *aOther;
+}
+
+nsStyleGradient*
+Gecko_CreateGradient(uint8_t aShape,
+                     uint8_t aSize,
+                     bool aRepeating,
+                     bool aLegacySyntax,
+                     uint32_t aStopCount)
+{
+  nsStyleGradient* result = new nsStyleGradient();
+
+  result->mShape = aShape;
+  result->mSize = aSize;
+  result->mRepeating = aRepeating;
+  result->mLegacySyntax = aLegacySyntax;
+
+  result->mAngle.SetNoneValue();
+  result->mBgPosX.SetNoneValue();
+  result->mBgPosY.SetNoneValue();
+  result->mRadiusX.SetNoneValue();
+  result->mRadiusY.SetNoneValue();
+
+  nsStyleGradientStop dummyStop;
+  dummyStop.mLocation.SetNoneValue();
+  dummyStop.mColor = NS_RGB(0, 0, 0);
+  dummyStop.mIsInterpolationHint = 0;
+
+  for (uint32_t i = 0; i < aStopCount; i++) {
+    result->mStops.AppendElement(dummyStop);
+  }
+
+  return result;
+}
+
+void
+Gecko_SetGradientStop(nsStyleGradient* aGradient,
+                      uint32_t aIndex,
+                      const nsStyleCoord* aLocation,
+                      nscolor aColor,
+                      bool aIsInterpolationHint)
+{
+  MOZ_ASSERT(aGradient);
+  MOZ_ASSERT(aLocation);
+  MOZ_ASSERT(aIndex < aGradient->mStops.Length());
+
+  aGradient->mStops[aIndex].mColor = aColor;
+  aGradient->mStops[aIndex].mLocation = *aLocation;
+  aGradient->mStops[aIndex].mIsInterpolationHint = aIsInterpolationHint;
+}
+
 #define STYLE_STRUCT(name, checkdata_cb)                                      \
                                                                               \
 void                                                                          \
 Gecko_Construct_nsStyle##name(nsStyle##name* ptr)                             \
 {                                                                             \
   new (ptr) nsStyle##name(StyleStructContext::ServoContext());                \
 }                                                                             \
                                                                               \
--- a/layout/style/ServoBindings.h
+++ b/layout/style/ServoBindings.h
@@ -3,16 +3,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_ServoBindings_h
 #define mozilla_ServoBindings_h
 
 #include "stdint.h"
+#include "nsColor.h"
 #include "mozilla/css/SheetParsingMode.h"
 #include "nsProxyRelease.h"
 
 /*
  * API for Servo to access Gecko data structures. This file must compile as valid
  * C code in order for the binding generator to parse it.
  *
  * Functions beginning with Gecko_ are implemented in Gecko and invoked from Servo.
@@ -28,16 +29,22 @@ namespace mozilla { namespace dom { clas
 using mozilla::dom::Element;
 typedef mozilla::dom::Element RawGeckoElement;
 class nsIDocument;
 typedef nsIDocument RawGeckoDocument;
 struct ServoNodeData;
 struct ServoComputedValues;
 struct RawServoStyleSheet;
 struct RawServoStyleSet;
+struct nsStyleList;
+struct nsStyleImage;
+struct nsStyleGradientStop;
+class nsStyleGradient;
+class nsStyleCoord;
+struct nsStyleDisplay;
 
 #define NS_DECL_THREADSAFE_FFI_REFCOUNTING(class_, name_)                     \
   static_assert(class_::HasThreadSafeRefCnt::value,                           \
                 "NS_DECL_THREADSAFE_FFI_REFCOUNTING can only be used with "   \
                 "classes that have thread-safe refcounting");                 \
   void Gecko_AddRef##name_##ArbitraryThread(class_* aPtr);                    \
   void Gecko_Release##name_##ArbitraryThread(class_* aPtr);
 #define NS_IMPL_THREADSAFE_FFI_REFCOUNTING(class_, name_)                     \
@@ -110,26 +117,42 @@ nsIAtom* Gecko_Atomize(const char* aStri
 void Gecko_AddRefAtom(nsIAtom* aAtom);
 void Gecko_ReleaseAtom(nsIAtom* aAtom);
 uint32_t Gecko_HashAtom(nsIAtom* aAtom);
 const uint16_t* Gecko_GetAtomAsUTF16(nsIAtom* aAtom, uint32_t* aLength);
 bool Gecko_AtomEqualsUTF8(nsIAtom* aAtom, const char* aString, uint32_t aLength);
 bool Gecko_AtomEqualsUTF8IgnoreCase(nsIAtom* aAtom, const char* aString, uint32_t aLength);
 
 // Counter style.
-struct nsStyleList;
 void Gecko_SetListStyleType(nsStyleList* style_struct, uint32_t type);
 void Gecko_CopyListStyleTypeFrom(nsStyleList* dst, const nsStyleList* src);
 
+// background-image style.
+// TODO: support url() values (and maybe element() too?).
+void Gecko_SetNullImageValue(nsStyleImage* image);
+void Gecko_SetGradientImageValue(nsStyleImage* image, nsStyleGradient* gradient);
+void Gecko_CopyImageValueFrom(nsStyleImage* image, const nsStyleImage* other);
+
+nsStyleGradient* Gecko_CreateGradient(uint8_t shape,
+                                      uint8_t size,
+                                      bool repeating,
+                                      bool legacy_syntax,
+                                      uint32_t stops);
+
+void Gecko_SetGradientStop(nsStyleGradient* gradient,
+                           uint32_t index,
+                           const nsStyleCoord* location,
+                           nscolor color,
+                           bool is_interpolation_hint);
+
 // Object refcounting.
 NS_DECL_HOLDER_FFI_REFCOUNTING(nsIPrincipal, Principal)
 NS_DECL_HOLDER_FFI_REFCOUNTING(nsIURI, URI)
 
 // Display style.
-struct nsStyleDisplay;
 void Gecko_SetMozBinding(nsStyleDisplay* style_struct,
                          const uint8_t* string_bytes, uint32_t string_length,
                          ThreadSafeURIHolder* base_uri,
                          ThreadSafeURIHolder* referrer,
                          ThreadSafePrincipalHolder* principal);
 void Gecko_CopyMozBindingFrom(nsStyleDisplay* des, const nsStyleDisplay* src);
 
 // Styleset and Stylesheet management.
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -677,17 +677,17 @@ struct LengthPercentPairCalcOps : public
     }
     return result_type(NSCoordSaturatingMultiply(aValue1.mLength, aValue2),
                        aValue1.mPercent * aValue2);
   }
 
 };
 
 static void
-SpecifiedCalcToComputedCalc(const nsCSSValue& aValue, nsStyleCoord& aCoord, 
+SpecifiedCalcToComputedCalc(const nsCSSValue& aValue, nsStyleCoord& aCoord,
                             nsStyleContext* aStyleContext,
                             RuleNodeCacheConditions& aConditions)
 {
   LengthPercentPairCalcOps ops(aStyleContext, aStyleContext->PresContext(),
                                aConditions);
   nsRuleNode::ComputedCalc vals = ComputeCalc(aValue, ops);
 
   nsStyleCoord::Calc* calcObj = new nsStyleCoord::Calc;
@@ -961,17 +961,17 @@ SetPairCoords(const nsCSSValue& aValue,
 {
   const nsCSSValue& valX =
     aValue.GetUnit() == eCSSUnit_Pair ? aValue.GetPairValue().mXValue : aValue;
   const nsCSSValue& valY =
     aValue.GetUnit() == eCSSUnit_Pair ? aValue.GetPairValue().mYValue : aValue;
 
   bool cX = SetCoord(valX, aCoordX, aParentX, aMask, aStyleContext,
                        aPresContext, aConditions);
-  mozilla::DebugOnly<bool> cY = SetCoord(valY, aCoordY, aParentY, aMask, 
+  mozilla::DebugOnly<bool> cY = SetCoord(valY, aCoordY, aParentY, aMask,
                        aStyleContext, aPresContext, aConditions);
   MOZ_ASSERT(cX == cY, "changed one but not the other");
   return cX;
 }
 
 static bool SetColor(const nsCSSValue& aValue, const nscolor aParentColor,
                        nsPresContext* aPresContext, nsStyleContext *aContext,
                        nscolor& aResult, RuleNodeCacheConditions& aConditions)
@@ -1240,21 +1240,19 @@ static void SetStyleImage(nsStyleContext
         SetStyleImageToImageRect(aStyleContext, aValue, aResult);
       } else {
         NS_NOTREACHED("-moz-image-rect() is the only expected function");
       }
       break;
     case eCSSUnit_Gradient:
     {
       nsStyleGradient* gradient = new nsStyleGradient();
-      if (gradient) {
-        SetGradient(aValue, aStyleContext->PresContext(), aStyleContext,
-                    *gradient, aConditions);
-        aResult.SetGradientData(gradient);
-      }
+      SetGradient(aValue, aStyleContext->PresContext(), aStyleContext,
+                  *gradient, aConditions);
+      aResult.SetGradientData(gradient);
       break;
     }
     case eCSSUnit_Element:
       aResult.SetElementId(aValue.GetStringBufferValue());
       break;
     case eCSSUnit_Initial:
     case eCSSUnit_Unset:
     case eCSSUnit_None:
@@ -2865,18 +2863,18 @@ ComputeScriptLevelSize(const nsStyleFont
 }
 
 
 /* static */ nscoord
 nsRuleNode::CalcFontPointSize(int32_t aHTMLSize, int32_t aBasePointSize,
                               nsPresContext* aPresContext,
                               nsFontSizeType aFontSizeType)
 {
-#define sFontSizeTableMin  9 
-#define sFontSizeTableMax 16 
+#define sFontSizeTableMin  9
+#define sFontSizeTableMax 16
 
 // This table seems to be the one used by MacIE5. We hope its adoption in Mozilla
 // and eventually in WinIE5.5 will help to establish a standard rendering across
 // platforms and browsers. For now, it is used only in Strict mode. More can be read
 // in the document written by Todd Farhner at:
 // http://style.verso.com/font_size_intervals/altintervals.html
 //
   static int32_t sStrictFontSizeTable[sFontSizeTableMax - sFontSizeTableMin + 1][8] =
@@ -2994,17 +2992,17 @@ nsRuleNode::CalcFontPointSize(int32_t aH
 }
 
 
 //------------------------------------------------------------------------------
 //
 //------------------------------------------------------------------------------
 
 /* static */ nscoord
-nsRuleNode::FindNextSmallerFontSize(nscoord aFontSize, int32_t aBasePointSize, 
+nsRuleNode::FindNextSmallerFontSize(nscoord aFontSize, int32_t aBasePointSize,
                                     nsPresContext* aPresContext,
                                     nsFontSizeType aFontSizeType)
 {
   int32_t index;
   int32_t indexMin;
   int32_t indexMax;
   float relativePosition;
   nscoord smallerSize;
@@ -3018,59 +3016,59 @@ nsRuleNode::FindNextSmallerFontSize(nsco
 
   if (aFontSizeType == eFontSize_HTML) {
     indexMin = 1;
     indexMax = 7;
   } else {
     indexMin = 0;
     indexMax = 6;
   }
-  
+
   smallestIndexFontSize = CalcFontPointSize(indexMin, aBasePointSize, aPresContext, aFontSizeType);
-  largestIndexFontSize = CalcFontPointSize(indexMax, aBasePointSize, aPresContext, aFontSizeType); 
+  largestIndexFontSize = CalcFontPointSize(indexMax, aBasePointSize, aPresContext, aFontSizeType);
   if (aFontSize > smallestIndexFontSize) {
     if (aFontSize < NSToCoordRound(float(largestIndexFontSize) * 1.5)) { // smaller will be in HTML table
       // find largest index smaller than current
       for (index = indexMax; index >= indexMin; index--) {
         indexFontSize = CalcFontPointSize(index, aBasePointSize, aPresContext, aFontSizeType);
         if (indexFontSize < aFontSize)
           break;
-      } 
+      }
       // set up points beyond table for interpolation purposes
       if (indexFontSize == smallestIndexFontSize) {
         smallerIndexFontSize = indexFontSize - onePx;
         largerIndexFontSize = CalcFontPointSize(index+1, aBasePointSize, aPresContext, aFontSizeType);
       } else if (indexFontSize == largestIndexFontSize) {
         smallerIndexFontSize = CalcFontPointSize(index-1, aBasePointSize, aPresContext, aFontSizeType);
         largerIndexFontSize = NSToCoordRound(float(largestIndexFontSize) * 1.5);
       } else {
         smallerIndexFontSize = CalcFontPointSize(index-1, aBasePointSize, aPresContext, aFontSizeType);
         largerIndexFontSize = CalcFontPointSize(index+1, aBasePointSize, aPresContext, aFontSizeType);
       }
       // compute the relative position of the parent size between the two closest indexed sizes
-      relativePosition = float(aFontSize - indexFontSize) / float(largerIndexFontSize - indexFontSize);            
+      relativePosition = float(aFontSize - indexFontSize) / float(largerIndexFontSize - indexFontSize);
       // set the new size to have the same relative position between the next smallest two indexed sizes
-      smallerSize = smallerIndexFontSize + NSToCoordRound(relativePosition * (indexFontSize - smallerIndexFontSize));      
+      smallerSize = smallerIndexFontSize + NSToCoordRound(relativePosition * (indexFontSize - smallerIndexFontSize));
     }
     else {  // larger than HTML table, drop by 33%
       smallerSize = NSToCoordRound(float(aFontSize) / 1.5);
     }
   }
   else { // smaller than HTML table, drop by 1px
     smallerSize = std::max(aFontSize - onePx, onePx);
   }
   return smallerSize;
 }
 
 //------------------------------------------------------------------------------
 //
 //------------------------------------------------------------------------------
 
 /* static */ nscoord
-nsRuleNode::FindNextLargerFontSize(nscoord aFontSize, int32_t aBasePointSize, 
+nsRuleNode::FindNextLargerFontSize(nscoord aFontSize, int32_t aBasePointSize,
                                    nsPresContext* aPresContext,
                                    nsFontSizeType aFontSizeType)
 {
   int32_t index;
   int32_t indexMin;
   int32_t indexMax;
   float relativePosition;
   nscoord adjustment;
@@ -3085,23 +3083,23 @@ nsRuleNode::FindNextLargerFontSize(nscoo
 
   if (aFontSizeType == eFontSize_HTML) {
     indexMin = 1;
     indexMax = 7;
   } else {
     indexMin = 0;
     indexMax = 6;
   }
-  
+
   smallestIndexFontSize = CalcFontPointSize(indexMin, aBasePointSize, aPresContext, aFontSizeType);
-  largestIndexFontSize = CalcFontPointSize(indexMax, aBasePointSize, aPresContext, aFontSizeType); 
+  largestIndexFontSize = CalcFontPointSize(indexMax, aBasePointSize, aPresContext, aFontSizeType);
   if (aFontSize > (smallestIndexFontSize - onePx)) {
     if (aFontSize < largestIndexFontSize) { // larger will be in HTML table
       // find smallest index larger than current
-      for (index = indexMin; index <= indexMax; index++) { 
+      for (index = indexMin; index <= indexMax; index++) {
         indexFontSize = CalcFontPointSize(index, aBasePointSize, aPresContext, aFontSizeType);
         if (indexFontSize > aFontSize)
           break;
       }
       // set up points beyond table for interpolation purposes
       if (indexFontSize == smallestIndexFontSize) {
         smallerIndexFontSize = indexFontSize - onePx;
         largerIndexFontSize = CalcFontPointSize(index+1, aBasePointSize, aPresContext, aFontSizeType);
@@ -6318,17 +6316,17 @@ nsRuleNode::ComputeDisplayData(void* aSt
                     parentDisplay->mPerspectiveOrigin[1],
                     SETCOORD_LPH | SETCOORD_INITIAL_HALF |
                       SETCOORD_BOX_POSITION | SETCOORD_STORE_CALC |
                       SETCOORD_UNSET_INITIAL,
                     aContext, mPresContext, conditions);
     NS_ASSERTION(result, "Malformed -moz-perspective-origin parse!");
   }
 
-  SetCoord(*aRuleData->ValueForPerspective(), 
+  SetCoord(*aRuleData->ValueForPerspective(),
            display->mChildPerspective, parentDisplay->mChildPerspective,
            SETCOORD_LAH | SETCOORD_INITIAL_NONE | SETCOORD_NONE |
              SETCOORD_UNSET_INITIAL,
            aContext, mPresContext, conditions);
 
   SetDiscrete(*aRuleData->ValueForBackfaceVisibility(),
               display->mBackfaceVisibility, conditions,
               SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL,
@@ -6428,17 +6426,17 @@ nsRuleNode::ComputeVisibilityData(void* 
     MOZ_ASSERT(array->Item(0).IsAngularUnit(),
                "First image-orientation value is not an angle");
     MOZ_ASSERT(array->Item(1).GetUnit() == eCSSUnit_Enumerated &&
                array->Item(1).GetIntValue() == NS_STYLE_IMAGE_ORIENTATION_FLIP,
                "Second image-orientation value is not 'flip'");
     double angle = array->Item(0).GetAngleValueInRadians();
     visibility->mImageOrientation =
       nsStyleImageOrientation::CreateAsAngleAndFlip(angle, true);
-    
+
   } else if (orientation->GetUnit() == eCSSUnit_Enumerated) {
     switch (orientation->GetIntValue()) {
       case NS_STYLE_IMAGE_ORIENTATION_FLIP:
         visibility->mImageOrientation = nsStyleImageOrientation::CreateAsFlip();
         break;
       case NS_STYLE_IMAGE_ORIENTATION_FROM_IMAGE:
         visibility->mImageOrientation = nsStyleImageOrientation::CreateAsFromImage();
         break;
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -223,17 +223,17 @@ public:
   bool operator!=(const nsStyleGradient& aOther) const {
     return !(*this == aOther);
   }
 
   bool IsOpaque();
   bool HasCalc();
   uint32_t Hash(PLDHashNumber aHash);
 
-  NS_INLINE_DECL_REFCOUNTING(nsStyleGradient)
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nsStyleGradient)
 
 private:
   // Private destructor, to discourage deletion outside of Release():
   ~nsStyleGradient() {}
 
   nsStyleGradient(const nsStyleGradient& aOther) = delete;
   nsStyleGradient& operator=(const nsStyleGradient& aOther) = delete;
 };