forked from mirrors/gecko-dev
		
	 d2ed260822
			
		
	
	
		d2ed260822
		
	
	
	
	
		
			
			Summary: Really sorry for the size of the patch. It's mostly automatic s/nsIDocument/Document/ but I had to fix up in a bunch of places manually to add the right namespacing and such. Overall it's not a very interesting patch I think. nsDocument.cpp turns into Document.cpp, nsIDocument.h into Document.h and nsIDocumentInlines.h into DocumentInlines.h. I also changed a bunch of nsCOMPtr usage to RefPtr, but not all of it. While fixing up some of the bits I also removed some unneeded OwnerDoc() null checks and such, but I didn't do anything riskier than that.
		
			
				
	
	
		
			877 lines
		
	
	
	
		
			25 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			877 lines
		
	
	
	
		
			25 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 | |
| /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 | |
| /* 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/. */
 | |
| 
 | |
| /* representation of simple property values within CSS declarations */
 | |
| 
 | |
| #include "nsCSSValue.h"
 | |
| 
 | |
| #include "mozilla/CORSMode.h"
 | |
| #include "mozilla/FontPropertyTypes.h"
 | |
| #include "mozilla/ServoBindings.h"
 | |
| #include "mozilla/ServoStyleSet.h"
 | |
| #include "mozilla/ServoTypes.h"
 | |
| #include "mozilla/StyleSheetInlines.h"
 | |
| #include "mozilla/Likely.h"
 | |
| #include "mozilla/MemoryReporting.h"
 | |
| #include "mozilla/css/ImageLoader.h"
 | |
| #include "gfxFontConstants.h"
 | |
| #include "imgIRequest.h"
 | |
| #include "imgRequestProxy.h"
 | |
| #include "mozilla/dom/Document.h"
 | |
| #include "nsIURIMutator.h"
 | |
| #include "nsCSSProps.h"
 | |
| #include "nsNetUtil.h"
 | |
| #include "nsPresContext.h"
 | |
| #include "nsStyleUtil.h"
 | |
| #include "nsDeviceContext.h"
 | |
| #include "nsContentUtils.h"
 | |
| 
 | |
| using namespace mozilla;
 | |
| using namespace mozilla::css;
 | |
| using namespace mozilla::dom;
 | |
| 
 | |
| nsCSSValue::nsCSSValue(int32_t aValue, nsCSSUnit aUnit) : mUnit(aUnit) {
 | |
|   MOZ_ASSERT(aUnit == eCSSUnit_Integer || aUnit == eCSSUnit_Enumerated,
 | |
|              "not an int value");
 | |
|   if (aUnit == eCSSUnit_Integer || aUnit == eCSSUnit_Enumerated) {
 | |
|     mValue.mInt = aValue;
 | |
|   } else {
 | |
|     mUnit = eCSSUnit_Null;
 | |
|     mValue.mInt = 0;
 | |
|   }
 | |
| }
 | |
| 
 | |
| nsCSSValue::nsCSSValue(float aValue, nsCSSUnit aUnit) : mUnit(aUnit) {
 | |
|   MOZ_ASSERT(eCSSUnit_Percent <= aUnit, "not a float value");
 | |
|   if (eCSSUnit_Percent <= aUnit) {
 | |
|     mValue.mFloat = aValue;
 | |
|     MOZ_ASSERT(!mozilla::IsNaN(mValue.mFloat));
 | |
|   } else {
 | |
|     mUnit = eCSSUnit_Null;
 | |
|     mValue.mInt = 0;
 | |
|   }
 | |
| }
 | |
| 
 | |
| nsCSSValue::nsCSSValue(const nsString& aValue, nsCSSUnit aUnit) : mUnit(aUnit) {
 | |
|   MOZ_ASSERT(UnitHasStringValue(), "not a string value");
 | |
|   if (UnitHasStringValue()) {
 | |
|     mValue.mString = BufferFromString(aValue).take();
 | |
|   } else {
 | |
|     mUnit = eCSSUnit_Null;
 | |
|     mValue.mInt = 0;
 | |
|   }
 | |
| }
 | |
| 
 | |
| nsCSSValue::nsCSSValue(nsCSSValue::Array* aValue, nsCSSUnit aUnit)
 | |
|     : mUnit(aUnit) {
 | |
|   MOZ_ASSERT(UnitHasArrayValue(), "bad unit");
 | |
|   mValue.mArray = aValue;
 | |
|   mValue.mArray->AddRef();
 | |
| }
 | |
| 
 | |
| nsCSSValue::nsCSSValue(const nsCSSValue& aCopy) : mUnit(aCopy.mUnit) {
 | |
|   if (mUnit <= eCSSUnit_DummyInherit) {
 | |
|     // nothing to do, but put this important case first
 | |
|   } else if (eCSSUnit_Percent <= mUnit) {
 | |
|     mValue.mFloat = aCopy.mValue.mFloat;
 | |
|     MOZ_ASSERT(!mozilla::IsNaN(mValue.mFloat));
 | |
|   } else if (UnitHasStringValue()) {
 | |
|     mValue.mString = aCopy.mValue.mString;
 | |
|     mValue.mString->AddRef();
 | |
|   } else if (eCSSUnit_Integer <= mUnit && mUnit <= eCSSUnit_Enumerated) {
 | |
|     mValue.mInt = aCopy.mValue.mInt;
 | |
|   } else if (UnitHasArrayValue()) {
 | |
|     mValue.mArray = aCopy.mValue.mArray;
 | |
|     mValue.mArray->AddRef();
 | |
|   } else if (eCSSUnit_Pair == mUnit) {
 | |
|     mValue.mPair = aCopy.mValue.mPair;
 | |
|     mValue.mPair->AddRef();
 | |
|   } else if (eCSSUnit_List == mUnit) {
 | |
|     mValue.mList = aCopy.mValue.mList;
 | |
|     mValue.mList->AddRef();
 | |
|   } else if (eCSSUnit_SharedList == mUnit) {
 | |
|     mValue.mSharedList = aCopy.mValue.mSharedList;
 | |
|     mValue.mSharedList->AddRef();
 | |
|   } else if (eCSSUnit_PairList == mUnit) {
 | |
|     mValue.mPairList = aCopy.mValue.mPairList;
 | |
|     mValue.mPairList->AddRef();
 | |
|   } else if (eCSSUnit_AtomIdent == mUnit) {
 | |
|     mValue.mAtom = aCopy.mValue.mAtom;
 | |
|     mValue.mAtom->AddRef();
 | |
|   } else {
 | |
|     MOZ_ASSERT(false, "unknown unit");
 | |
|   }
 | |
| }
 | |
| 
 | |
| nsCSSValue& nsCSSValue::operator=(const nsCSSValue& aCopy) {
 | |
|   if (this != &aCopy) {
 | |
|     Reset();
 | |
|     new (this) nsCSSValue(aCopy);
 | |
|   }
 | |
|   return *this;
 | |
| }
 | |
| 
 | |
| nsCSSValue& nsCSSValue::operator=(nsCSSValue&& aOther) {
 | |
|   MOZ_ASSERT(this != &aOther, "Self assigment with rvalue reference");
 | |
| 
 | |
|   Reset();
 | |
|   mUnit = aOther.mUnit;
 | |
|   mValue = aOther.mValue;
 | |
|   aOther.mUnit = eCSSUnit_Null;
 | |
| 
 | |
|   return *this;
 | |
| }
 | |
| 
 | |
| bool nsCSSValue::operator==(const nsCSSValue& aOther) const {
 | |
|   if (mUnit == aOther.mUnit) {
 | |
|     if (mUnit <= eCSSUnit_DummyInherit) {
 | |
|       return true;
 | |
|     } else if (UnitHasStringValue()) {
 | |
|       return (NS_strcmp(GetBufferValue(mValue.mString),
 | |
|                         GetBufferValue(aOther.mValue.mString)) == 0);
 | |
|     } else if ((eCSSUnit_Integer <= mUnit) && (mUnit <= eCSSUnit_Enumerated)) {
 | |
|       return mValue.mInt == aOther.mValue.mInt;
 | |
|     } else if (UnitHasArrayValue()) {
 | |
|       return *mValue.mArray == *aOther.mValue.mArray;
 | |
|     } else if (eCSSUnit_Pair == mUnit) {
 | |
|       return *mValue.mPair == *aOther.mValue.mPair;
 | |
|     } else if (eCSSUnit_List == mUnit) {
 | |
|       return nsCSSValueList::Equal(mValue.mList, aOther.mValue.mList);
 | |
|     } else if (eCSSUnit_SharedList == mUnit) {
 | |
|       return *mValue.mSharedList == *aOther.mValue.mSharedList;
 | |
|     } else if (eCSSUnit_PairList == mUnit) {
 | |
|       return nsCSSValuePairList::Equal(mValue.mPairList,
 | |
|                                        aOther.mValue.mPairList);
 | |
|     } else if (eCSSUnit_AtomIdent == mUnit) {
 | |
|       return mValue.mAtom == aOther.mValue.mAtom;
 | |
|     } else {
 | |
|       return mValue.mFloat == aOther.mValue.mFloat;
 | |
|     }
 | |
|   }
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| double nsCSSValue::GetAngleValueInDegrees() const {
 | |
|   // Note that this extends the value from float to double.
 | |
|   return GetAngleValue();
 | |
| }
 | |
| 
 | |
| double nsCSSValue::GetAngleValueInRadians() const {
 | |
|   return GetAngleValueInDegrees() * M_PI / 180.0;
 | |
| }
 | |
| 
 | |
| nscoord nsCSSValue::GetPixelLength() const {
 | |
|   MOZ_ASSERT(IsPixelLengthUnit(), "not a fixed length unit");
 | |
| 
 | |
|   double scaleFactor;
 | |
|   switch (mUnit) {
 | |
|     case eCSSUnit_Pixel:
 | |
|       return nsPresContext::CSSPixelsToAppUnits(mValue.mFloat);
 | |
|     case eCSSUnit_Pica:
 | |
|       scaleFactor = 16.0;
 | |
|       break;
 | |
|     case eCSSUnit_Point:
 | |
|       scaleFactor = 4 / 3.0;
 | |
|       break;
 | |
|     case eCSSUnit_Inch:
 | |
|       scaleFactor = 96.0;
 | |
|       break;
 | |
|     case eCSSUnit_Millimeter:
 | |
|       scaleFactor = 96 / 25.4;
 | |
|       break;
 | |
|     case eCSSUnit_Centimeter:
 | |
|       scaleFactor = 96 / 2.54;
 | |
|       break;
 | |
|     case eCSSUnit_Quarter:
 | |
|       scaleFactor = 96 / 101.6;
 | |
|       break;
 | |
|     default:
 | |
|       NS_ERROR("should never get here");
 | |
|       return 0;
 | |
|   }
 | |
|   return nsPresContext::CSSPixelsToAppUnits(float(mValue.mFloat * scaleFactor));
 | |
| }
 | |
| 
 | |
| // Assert against resetting non-trivial CSS values from the parallel Servo
 | |
| // traversal, since the refcounts aren't thread-safe.
 | |
| // Note that the caller might be an OMTA thread, which is allowed to operate off
 | |
| // main thread because it owns all of the corresponding nsCSSValues and any that
 | |
| // they might be sharing members with. Since this can happen concurrently with
 | |
| // the servo traversal, we have to use a more-precise (but slower) test.
 | |
| #define DO_RELEASE(member)                                         \
 | |
|   {                                                                \
 | |
|     MOZ_ASSERT(!ServoStyleSet::IsCurrentThreadInServoTraversal()); \
 | |
|     mValue.member->Release();                                      \
 | |
|   }
 | |
| 
 | |
| void nsCSSValue::DoReset() {
 | |
|   if (UnitHasStringValue()) {
 | |
|     mValue.mString->Release();
 | |
|   } else if (UnitHasArrayValue()) {
 | |
|     DO_RELEASE(mArray);
 | |
|   } else if (eCSSUnit_Pair == mUnit) {
 | |
|     DO_RELEASE(mPair);
 | |
|   } else if (eCSSUnit_List == mUnit) {
 | |
|     DO_RELEASE(mList);
 | |
|   } else if (eCSSUnit_SharedList == mUnit) {
 | |
|     DO_RELEASE(mSharedList);
 | |
|   } else if (eCSSUnit_PairList == mUnit) {
 | |
|     DO_RELEASE(mPairList);
 | |
|   } else if (eCSSUnit_AtomIdent == mUnit) {
 | |
|     DO_RELEASE(mAtom);
 | |
|   }
 | |
|   mUnit = eCSSUnit_Null;
 | |
| }
 | |
| 
 | |
| #undef DO_RELEASE
 | |
| 
 | |
| void nsCSSValue::SetIntValue(int32_t aValue, nsCSSUnit aUnit) {
 | |
|   MOZ_ASSERT(aUnit == eCSSUnit_Integer || aUnit == eCSSUnit_Enumerated,
 | |
|              "not an int value");
 | |
|   Reset();
 | |
|   if (aUnit == eCSSUnit_Integer || aUnit == eCSSUnit_Enumerated) {
 | |
|     mUnit = aUnit;
 | |
|     mValue.mInt = aValue;
 | |
|   }
 | |
| }
 | |
| 
 | |
| void nsCSSValue::SetPercentValue(float aValue) {
 | |
|   Reset();
 | |
|   mUnit = eCSSUnit_Percent;
 | |
|   mValue.mFloat = aValue;
 | |
|   MOZ_ASSERT(!mozilla::IsNaN(mValue.mFloat));
 | |
| }
 | |
| 
 | |
| void nsCSSValue::SetFloatValue(float aValue, nsCSSUnit aUnit) {
 | |
|   MOZ_ASSERT(IsFloatUnit(aUnit), "not a float value");
 | |
|   Reset();
 | |
|   if (IsFloatUnit(aUnit)) {
 | |
|     mUnit = aUnit;
 | |
|     mValue.mFloat = aValue;
 | |
|     MOZ_ASSERT(!mozilla::IsNaN(mValue.mFloat));
 | |
|   }
 | |
| }
 | |
| 
 | |
| void nsCSSValue::SetStringValue(const nsString& aValue, nsCSSUnit aUnit) {
 | |
|   Reset();
 | |
|   mUnit = aUnit;
 | |
|   MOZ_ASSERT(UnitHasStringValue(), "not a string unit");
 | |
|   if (UnitHasStringValue()) {
 | |
|     mValue.mString = BufferFromString(aValue).take();
 | |
|   } else
 | |
|     mUnit = eCSSUnit_Null;
 | |
| }
 | |
| 
 | |
| void nsCSSValue::SetAtomIdentValue(already_AddRefed<nsAtom> aValue) {
 | |
|   Reset();
 | |
|   mUnit = eCSSUnit_AtomIdent;
 | |
|   mValue.mAtom = aValue.take();
 | |
| }
 | |
| 
 | |
| void nsCSSValue::SetIntegerCoordValue(nscoord aValue) {
 | |
|   SetFloatValue(nsPresContext::AppUnitsToFloatCSSPixels(aValue),
 | |
|                 eCSSUnit_Pixel);
 | |
| }
 | |
| 
 | |
| void nsCSSValue::SetArrayValue(nsCSSValue::Array* aValue, nsCSSUnit aUnit) {
 | |
|   Reset();
 | |
|   mUnit = aUnit;
 | |
|   MOZ_ASSERT(UnitHasArrayValue(), "bad unit");
 | |
|   mValue.mArray = aValue;
 | |
|   mValue.mArray->AddRef();
 | |
| }
 | |
| 
 | |
| void nsCSSValue::SetPairValue(const nsCSSValuePair* aValue) {
 | |
|   // pairs should not be used for null/inherit/initial values
 | |
|   MOZ_ASSERT(aValue && aValue->mXValue.GetUnit() != eCSSUnit_Null &&
 | |
|                  aValue->mYValue.GetUnit() != eCSSUnit_Null &&
 | |
|                  aValue->mXValue.GetUnit() != eCSSUnit_Inherit &&
 | |
|                  aValue->mYValue.GetUnit() != eCSSUnit_Inherit &&
 | |
|                  aValue->mXValue.GetUnit() != eCSSUnit_Initial &&
 | |
|                  aValue->mYValue.GetUnit() != eCSSUnit_Initial &&
 | |
|                  aValue->mXValue.GetUnit() != eCSSUnit_Unset &&
 | |
|                  aValue->mYValue.GetUnit() != eCSSUnit_Unset,
 | |
|              "missing or inappropriate pair value");
 | |
|   Reset();
 | |
|   mUnit = eCSSUnit_Pair;
 | |
|   mValue.mPair = new nsCSSValuePair_heap(aValue->mXValue, aValue->mYValue);
 | |
|   mValue.mPair->AddRef();
 | |
| }
 | |
| 
 | |
| void nsCSSValue::SetPairValue(const nsCSSValue& xValue,
 | |
|                               const nsCSSValue& yValue) {
 | |
|   MOZ_ASSERT(xValue.GetUnit() != eCSSUnit_Null &&
 | |
|                  yValue.GetUnit() != eCSSUnit_Null &&
 | |
|                  xValue.GetUnit() != eCSSUnit_Inherit &&
 | |
|                  yValue.GetUnit() != eCSSUnit_Inherit &&
 | |
|                  xValue.GetUnit() != eCSSUnit_Initial &&
 | |
|                  yValue.GetUnit() != eCSSUnit_Initial &&
 | |
|                  xValue.GetUnit() != eCSSUnit_Unset &&
 | |
|                  yValue.GetUnit() != eCSSUnit_Unset,
 | |
|              "inappropriate pair value");
 | |
|   Reset();
 | |
|   mUnit = eCSSUnit_Pair;
 | |
|   mValue.mPair = new nsCSSValuePair_heap(xValue, yValue);
 | |
|   mValue.mPair->AddRef();
 | |
| }
 | |
| 
 | |
| nsCSSValueList* nsCSSValue::SetListValue() {
 | |
|   Reset();
 | |
|   mUnit = eCSSUnit_List;
 | |
|   mValue.mList = new nsCSSValueList_heap;
 | |
|   mValue.mList->AddRef();
 | |
|   return mValue.mList;
 | |
| }
 | |
| 
 | |
| void nsCSSValue::SetSharedListValue(nsCSSValueSharedList* aList) {
 | |
|   Reset();
 | |
|   mUnit = eCSSUnit_SharedList;
 | |
|   mValue.mSharedList = aList;
 | |
|   mValue.mSharedList->AddRef();
 | |
| }
 | |
| 
 | |
| nsCSSValuePairList* nsCSSValue::SetPairListValue() {
 | |
|   Reset();
 | |
|   mUnit = eCSSUnit_PairList;
 | |
|   mValue.mPairList = new nsCSSValuePairList_heap;
 | |
|   mValue.mPairList->AddRef();
 | |
|   return mValue.mPairList;
 | |
| }
 | |
| 
 | |
| void nsCSSValue::SetNoneValue() {
 | |
|   Reset();
 | |
|   mUnit = eCSSUnit_None;
 | |
| }
 | |
| 
 | |
| void nsCSSValue::SetCalcValue(const nsStyleCoord::CalcValue& aCalc) {
 | |
|   RefPtr<nsCSSValue::Array> arr = nsCSSValue::Array::Create(1);
 | |
|   if (!aCalc.mHasPercent) {
 | |
|     arr->Item(0).SetIntegerCoordValue(aCalc.mLength);
 | |
|   } else {
 | |
|     nsCSSValue::Array* arr2 = nsCSSValue::Array::Create(2);
 | |
|     arr->Item(0).SetArrayValue(arr2, eCSSUnit_Calc_Plus);
 | |
|     arr2->Item(0).SetIntegerCoordValue(aCalc.mLength);
 | |
|     arr2->Item(1).SetPercentValue(aCalc.mPercent);
 | |
|   }
 | |
| 
 | |
|   SetArrayValue(arr, eCSSUnit_Calc);
 | |
| }
 | |
| 
 | |
| nsStyleCoord::CalcValue nsCSSValue::GetCalcValue() const {
 | |
|   MOZ_ASSERT(mUnit == eCSSUnit_Calc, "The unit should be eCSSUnit_Calc");
 | |
| 
 | |
|   const nsCSSValue::Array* array = GetArrayValue();
 | |
|   MOZ_ASSERT(array->Count() == 1, "There should be a 1-length array");
 | |
| 
 | |
|   const nsCSSValue& rootValue = array->Item(0);
 | |
| 
 | |
|   nsStyleCoord::CalcValue result;
 | |
| 
 | |
|   if (rootValue.GetUnit() == eCSSUnit_Pixel) {
 | |
|     result.mLength = rootValue.GetPixelLength();
 | |
|     result.mPercent = 0.0f;
 | |
|     result.mHasPercent = false;
 | |
|   } else {
 | |
|     MOZ_ASSERT(rootValue.GetUnit() == eCSSUnit_Calc_Plus,
 | |
|                "Calc unit should be eCSSUnit_Calc_Plus");
 | |
| 
 | |
|     const nsCSSValue::Array* calcPlusArray = rootValue.GetArrayValue();
 | |
|     MOZ_ASSERT(calcPlusArray->Count() == 2,
 | |
|                "eCSSUnit_Calc_Plus should have a 2-length array");
 | |
| 
 | |
|     const nsCSSValue& length = calcPlusArray->Item(0);
 | |
|     const nsCSSValue& percent = calcPlusArray->Item(1);
 | |
|     MOZ_ASSERT(length.GetUnit() == eCSSUnit_Pixel,
 | |
|                "The first value should be eCSSUnit_Pixel");
 | |
|     MOZ_ASSERT(percent.GetUnit() == eCSSUnit_Percent,
 | |
|                "The first value should be eCSSUnit_Percent");
 | |
|     result.mLength = length.GetPixelLength();
 | |
|     result.mPercent = percent.GetPercentValue();
 | |
|     result.mHasPercent = true;
 | |
|   }
 | |
| 
 | |
|   return result;
 | |
| }
 | |
| 
 | |
| // static
 | |
| already_AddRefed<nsStringBuffer> nsCSSValue::BufferFromString(
 | |
|     const nsString& aValue) {
 | |
|   RefPtr<nsStringBuffer> buffer = nsStringBuffer::FromString(aValue);
 | |
|   if (buffer) {
 | |
|     return buffer.forget();
 | |
|   }
 | |
| 
 | |
|   nsString::size_type length = aValue.Length();
 | |
| 
 | |
|   // NOTE: Alloc prouduces a new, already-addref'd (refcnt = 1) buffer.
 | |
|   // NOTE: String buffer allocation is currently fallible.
 | |
|   size_t sz = (length + 1) * sizeof(char16_t);
 | |
|   buffer = nsStringBuffer::Alloc(sz);
 | |
|   if (MOZ_UNLIKELY(!buffer)) {
 | |
|     NS_ABORT_OOM(sz);
 | |
|   }
 | |
| 
 | |
|   char16_t* data = static_cast<char16_t*>(buffer->Data());
 | |
|   nsCharTraits<char16_t>::copy(data, aValue.get(), length);
 | |
|   // Null-terminate.
 | |
|   data[length] = 0;
 | |
|   return buffer.forget();
 | |
| }
 | |
| 
 | |
| size_t nsCSSValue::SizeOfExcludingThis(
 | |
|     mozilla::MallocSizeOf aMallocSizeOf) const {
 | |
|   size_t n = 0;
 | |
| 
 | |
|   switch (GetUnit()) {
 | |
|     // No value: nothing extra to measure.
 | |
|     case eCSSUnit_Null:
 | |
|     case eCSSUnit_Auto:
 | |
|     case eCSSUnit_Inherit:
 | |
|     case eCSSUnit_Initial:
 | |
|     case eCSSUnit_Unset:
 | |
|     case eCSSUnit_None:
 | |
|     case eCSSUnit_Normal:
 | |
|     case eCSSUnit_System_Font:
 | |
|     case eCSSUnit_All:
 | |
|     case eCSSUnit_Dummy:
 | |
|     case eCSSUnit_DummyInherit:
 | |
|       break;
 | |
| 
 | |
|     // String
 | |
|     case eCSSUnit_String:
 | |
|     case eCSSUnit_Ident:
 | |
|     case eCSSUnit_Attr:
 | |
|     case eCSSUnit_Element:
 | |
|       n += mValue.mString->SizeOfIncludingThisIfUnshared(aMallocSizeOf);
 | |
|       break;
 | |
| 
 | |
|     // Array
 | |
|     case eCSSUnit_Array:
 | |
|     case eCSSUnit_Counter:
 | |
|     case eCSSUnit_Counters:
 | |
|     case eCSSUnit_Cubic_Bezier:
 | |
|     case eCSSUnit_Steps:
 | |
|     case eCSSUnit_Symbols:
 | |
|     case eCSSUnit_Function:
 | |
|     case eCSSUnit_Calc:
 | |
|     case eCSSUnit_Calc_Plus:
 | |
|       break;
 | |
| 
 | |
|     // Pair
 | |
|     case eCSSUnit_Pair:
 | |
|       n += mValue.mPair->SizeOfIncludingThis(aMallocSizeOf);
 | |
|       break;
 | |
| 
 | |
|     // List
 | |
|     case eCSSUnit_List:
 | |
|       n += mValue.mList->SizeOfIncludingThis(aMallocSizeOf);
 | |
|       break;
 | |
| 
 | |
|     // SharedList
 | |
|     case eCSSUnit_SharedList:
 | |
|       // Makes more sense not to measure, since it most cases the list
 | |
|       // will be shared.
 | |
|       break;
 | |
| 
 | |
|     // PairList
 | |
|     case eCSSUnit_PairList:
 | |
|       n += mValue.mPairList->SizeOfIncludingThis(aMallocSizeOf);
 | |
|       break;
 | |
| 
 | |
|     // Atom is always shared, and thus should not be counted.
 | |
|     case eCSSUnit_AtomIdent:
 | |
|       break;
 | |
| 
 | |
|     // Int: nothing extra to measure.
 | |
|     case eCSSUnit_Integer:
 | |
|     case eCSSUnit_Enumerated:
 | |
|       break;
 | |
| 
 | |
|     // Float: nothing extra to measure.
 | |
|     case eCSSUnit_Percent:
 | |
|     case eCSSUnit_Number:
 | |
|     case eCSSUnit_ViewportWidth:
 | |
|     case eCSSUnit_ViewportHeight:
 | |
|     case eCSSUnit_ViewportMin:
 | |
|     case eCSSUnit_ViewportMax:
 | |
|     case eCSSUnit_EM:
 | |
|     case eCSSUnit_XHeight:
 | |
|     case eCSSUnit_Char:
 | |
|     case eCSSUnit_RootEM:
 | |
|     case eCSSUnit_Point:
 | |
|     case eCSSUnit_Inch:
 | |
|     case eCSSUnit_Millimeter:
 | |
|     case eCSSUnit_Centimeter:
 | |
|     case eCSSUnit_Pica:
 | |
|     case eCSSUnit_Pixel:
 | |
|     case eCSSUnit_Quarter:
 | |
|     case eCSSUnit_Degree:
 | |
|     case eCSSUnit_Hertz:
 | |
|     case eCSSUnit_Kilohertz:
 | |
|     case eCSSUnit_Seconds:
 | |
|     case eCSSUnit_Milliseconds:
 | |
|     case eCSSUnit_FlexFraction:
 | |
|       break;
 | |
| 
 | |
|     default:
 | |
|       MOZ_ASSERT(false, "bad nsCSSUnit");
 | |
|       break;
 | |
|   }
 | |
| 
 | |
|   return n;
 | |
| }
 | |
| 
 | |
| // --- nsCSSValueList -----------------
 | |
| 
 | |
| nsCSSValueList::~nsCSSValueList() {
 | |
|   MOZ_COUNT_DTOR(nsCSSValueList);
 | |
|   NS_CSS_DELETE_LIST_MEMBER(nsCSSValueList, this, mNext);
 | |
| }
 | |
| 
 | |
| nsCSSValueList* nsCSSValueList::Clone() const {
 | |
|   nsCSSValueList* result = new nsCSSValueList(*this);
 | |
|   nsCSSValueList* dest = result;
 | |
|   const nsCSSValueList* src = this->mNext;
 | |
|   while (src) {
 | |
|     dest->mNext = new nsCSSValueList(*src);
 | |
|     dest = dest->mNext;
 | |
|     src = src->mNext;
 | |
|   }
 | |
| 
 | |
|   MOZ_ASSERT(result, "shouldn't return null; supposed to be infallible");
 | |
|   return result;
 | |
| }
 | |
| 
 | |
| void nsCSSValueList::CloneInto(nsCSSValueList* aList) const {
 | |
|   NS_ASSERTION(!aList->mNext, "Must be an empty list!");
 | |
|   aList->mValue = mValue;
 | |
|   aList->mNext = mNext ? mNext->Clone() : nullptr;
 | |
| }
 | |
| 
 | |
| /* static */ bool nsCSSValueList::Equal(const nsCSSValueList* aList1,
 | |
|                                         const nsCSSValueList* aList2) {
 | |
|   if (aList1 == aList2) {
 | |
|     return true;
 | |
|   }
 | |
| 
 | |
|   const nsCSSValueList *p1 = aList1, *p2 = aList2;
 | |
|   for (; p1 && p2; p1 = p1->mNext, p2 = p2->mNext) {
 | |
|     if (p1->mValue != p2->mValue) return false;
 | |
|   }
 | |
|   return !p1 && !p2;  // true if same length, false otherwise
 | |
| }
 | |
| 
 | |
| size_t nsCSSValueList::SizeOfIncludingThis(
 | |
|     mozilla::MallocSizeOf aMallocSizeOf) const {
 | |
|   size_t n = 0;
 | |
|   const nsCSSValueList* v = this;
 | |
|   while (v) {
 | |
|     n += aMallocSizeOf(v);
 | |
|     n += v->mValue.SizeOfExcludingThis(aMallocSizeOf);
 | |
|     v = v->mNext;
 | |
|   }
 | |
|   return n;
 | |
| }
 | |
| 
 | |
| size_t nsCSSValueList_heap::SizeOfIncludingThis(
 | |
|     mozilla::MallocSizeOf aMallocSizeOf) const {
 | |
|   // Only measure it if it's unshared, to avoid double-counting.
 | |
|   size_t n = 0;
 | |
|   if (mRefCnt <= 1) {
 | |
|     n += aMallocSizeOf(this);
 | |
|     n += mValue.SizeOfExcludingThis(aMallocSizeOf);
 | |
|     n += mNext ? mNext->SizeOfIncludingThis(aMallocSizeOf) : 0;
 | |
|   }
 | |
|   return n;
 | |
| }
 | |
| 
 | |
| // --- nsCSSValueSharedList -----------------
 | |
| 
 | |
| nsCSSValueSharedList::~nsCSSValueSharedList() {
 | |
|   if (mHead) {
 | |
|     NS_CSS_DELETE_LIST_MEMBER(nsCSSValueList, mHead, mNext);
 | |
|     delete mHead;
 | |
|   }
 | |
| }
 | |
| 
 | |
| bool nsCSSValueSharedList::operator==(
 | |
|     const nsCSSValueSharedList& aOther) const {
 | |
|   return nsCSSValueList::Equal(mHead, aOther.mHead);
 | |
| }
 | |
| 
 | |
| size_t nsCSSValueSharedList::SizeOfIncludingThis(
 | |
|     mozilla::MallocSizeOf aMallocSizeOf) const {
 | |
|   // Only measure it if it's unshared, to avoid double-counting.
 | |
|   size_t n = 0;
 | |
|   if (mRefCnt <= 1) {
 | |
|     n += aMallocSizeOf(this);
 | |
|     n += mHead->SizeOfIncludingThis(aMallocSizeOf);
 | |
|   }
 | |
|   return n;
 | |
| }
 | |
| 
 | |
| // --- nsCSSValuePair -----------------
 | |
| 
 | |
| size_t nsCSSValuePair::SizeOfExcludingThis(
 | |
|     mozilla::MallocSizeOf aMallocSizeOf) const {
 | |
|   size_t n = 0;
 | |
|   n += mXValue.SizeOfExcludingThis(aMallocSizeOf);
 | |
|   n += mYValue.SizeOfExcludingThis(aMallocSizeOf);
 | |
|   return n;
 | |
| }
 | |
| 
 | |
| size_t nsCSSValuePair_heap::SizeOfIncludingThis(
 | |
|     mozilla::MallocSizeOf aMallocSizeOf) const {
 | |
|   // Only measure it if it's unshared, to avoid double-counting.
 | |
|   size_t n = 0;
 | |
|   if (mRefCnt <= 1) {
 | |
|     n += aMallocSizeOf(this);
 | |
|     n += mXValue.SizeOfExcludingThis(aMallocSizeOf);
 | |
|     n += mYValue.SizeOfExcludingThis(aMallocSizeOf);
 | |
|   }
 | |
|   return n;
 | |
| }
 | |
| 
 | |
| // --- nsCSSValuePairList -----------------
 | |
| 
 | |
| nsCSSValuePairList::~nsCSSValuePairList() {
 | |
|   MOZ_COUNT_DTOR(nsCSSValuePairList);
 | |
|   NS_CSS_DELETE_LIST_MEMBER(nsCSSValuePairList, this, mNext);
 | |
| }
 | |
| 
 | |
| nsCSSValuePairList* nsCSSValuePairList::Clone() const {
 | |
|   nsCSSValuePairList* result = new nsCSSValuePairList(*this);
 | |
|   nsCSSValuePairList* dest = result;
 | |
|   const nsCSSValuePairList* src = this->mNext;
 | |
|   while (src) {
 | |
|     dest->mNext = new nsCSSValuePairList(*src);
 | |
|     dest = dest->mNext;
 | |
|     src = src->mNext;
 | |
|   }
 | |
| 
 | |
|   MOZ_ASSERT(result, "shouldn't return null; supposed to be infallible");
 | |
|   return result;
 | |
| }
 | |
| 
 | |
| /* static */ bool nsCSSValuePairList::Equal(const nsCSSValuePairList* aList1,
 | |
|                                             const nsCSSValuePairList* aList2) {
 | |
|   if (aList1 == aList2) {
 | |
|     return true;
 | |
|   }
 | |
| 
 | |
|   const nsCSSValuePairList *p1 = aList1, *p2 = aList2;
 | |
|   for (; p1 && p2; p1 = p1->mNext, p2 = p2->mNext) {
 | |
|     if (p1->mXValue != p2->mXValue || p1->mYValue != p2->mYValue) return false;
 | |
|   }
 | |
|   return !p1 && !p2;  // true if same length, false otherwise
 | |
| }
 | |
| 
 | |
| size_t nsCSSValuePairList::SizeOfIncludingThis(
 | |
|     mozilla::MallocSizeOf aMallocSizeOf) const {
 | |
|   size_t n = 0;
 | |
|   const nsCSSValuePairList* v = this;
 | |
|   while (v) {
 | |
|     n += aMallocSizeOf(v);
 | |
|     n += v->mXValue.SizeOfExcludingThis(aMallocSizeOf);
 | |
|     n += v->mYValue.SizeOfExcludingThis(aMallocSizeOf);
 | |
|     v = v->mNext;
 | |
|   }
 | |
|   return n;
 | |
| }
 | |
| 
 | |
| size_t nsCSSValuePairList_heap::SizeOfIncludingThis(
 | |
|     mozilla::MallocSizeOf aMallocSizeOf) const {
 | |
|   // Only measure it if it's unshared, to avoid double-counting.
 | |
|   size_t n = 0;
 | |
|   if (mRefCnt <= 1) {
 | |
|     n += aMallocSizeOf(this);
 | |
|     n += mXValue.SizeOfExcludingThis(aMallocSizeOf);
 | |
|     n += mYValue.SizeOfExcludingThis(aMallocSizeOf);
 | |
|     n += mNext ? mNext->SizeOfIncludingThis(aMallocSizeOf) : 0;
 | |
|   }
 | |
|   return n;
 | |
| }
 | |
| 
 | |
| size_t nsCSSValue::Array::SizeOfIncludingThis(
 | |
|     mozilla::MallocSizeOf aMallocSizeOf) const {
 | |
|   size_t n = aMallocSizeOf(this);
 | |
|   for (size_t i = 0; i < mCount; i++) {
 | |
|     n += mArray[i].SizeOfExcludingThis(aMallocSizeOf);
 | |
|   }
 | |
|   return n;
 | |
| }
 | |
| 
 | |
| css::URLValue::~URLValue() {
 | |
|   if (mLoadID != 0) {
 | |
|     ImageLoader::DeregisterCSSImageFromAllLoaders(this);
 | |
|   }
 | |
| }
 | |
| 
 | |
| bool css::URLValue::Equals(const URLValue& aOther) const {
 | |
|   MOZ_ASSERT(NS_IsMainThread());
 | |
| 
 | |
|   bool eq;
 | |
|   const URLExtraData* self = ExtraData();
 | |
|   const URLExtraData* other = aOther.ExtraData();
 | |
|   return GetString() == aOther.GetString() &&
 | |
|          (GetURI() == aOther.GetURI() ||  // handles null == null
 | |
|           (mURI && aOther.mURI &&
 | |
|            NS_SUCCEEDED(mURI->Equals(aOther.mURI, &eq)) && eq)) &&
 | |
|          (self->BaseURI() == other->BaseURI() ||
 | |
|           (NS_SUCCEEDED(self->BaseURI()->Equals(other->BaseURI(), &eq)) &&
 | |
|            eq)) &&
 | |
|          self->Principal()->Equals(other->Principal()) &&
 | |
|          IsLocalRef() == aOther.IsLocalRef();
 | |
| }
 | |
| 
 | |
| bool css::URLValue::DefinitelyEqualURIs(const URLValue& aOther) const {
 | |
|   if (ExtraData()->BaseURI() != aOther.ExtraData()->BaseURI()) {
 | |
|     return false;
 | |
|   }
 | |
|   return GetString() == aOther.GetString();
 | |
| }
 | |
| 
 | |
| bool css::URLValue::DefinitelyEqualURIsAndPrincipal(
 | |
|     const URLValue& aOther) const {
 | |
|   return ExtraData()->Principal() == aOther.ExtraData()->Principal() &&
 | |
|          DefinitelyEqualURIs(aOther);
 | |
| }
 | |
| 
 | |
| nsDependentCSubstring css::URLValue::GetString() const {
 | |
|   const uint8_t* chars;
 | |
|   uint32_t len;
 | |
|   Servo_CssUrlData_GetSerialization(mCssUrl, &chars, &len);
 | |
|   return nsDependentCSubstring(reinterpret_cast<const char*>(chars), len);
 | |
| }
 | |
| 
 | |
| nsIURI* css::URLValue::GetURI() const {
 | |
|   MOZ_ASSERT(NS_IsMainThread());
 | |
| 
 | |
|   if (!mURIResolved) {
 | |
|     MOZ_ASSERT(!mURI);
 | |
|     nsCOMPtr<nsIURI> newURI;
 | |
|     NS_NewURI(getter_AddRefs(newURI), GetString(), nullptr,
 | |
|               ExtraData()->BaseURI());
 | |
|     mURI = newURI.forget();
 | |
|     mURIResolved = true;
 | |
|   }
 | |
| 
 | |
|   return mURI;
 | |
| }
 | |
| 
 | |
| bool css::URLValue::HasRef() const {
 | |
|   if (IsLocalRef()) {
 | |
|     return true;
 | |
|   }
 | |
| 
 | |
|   if (nsIURI* uri = GetURI()) {
 | |
|     nsAutoCString ref;
 | |
|     nsresult rv = uri->GetRef(ref);
 | |
|     return NS_SUCCEEDED(rv) && !ref.IsEmpty();
 | |
|   }
 | |
| 
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| already_AddRefed<nsIURI> css::URLValue::ResolveLocalRef(nsIURI* aURI) const {
 | |
|   nsCOMPtr<nsIURI> result = GetURI();
 | |
| 
 | |
|   if (result && IsLocalRef()) {
 | |
|     nsCString ref;
 | |
|     mURI->GetRef(ref);
 | |
| 
 | |
|     nsresult rv = NS_MutateURI(aURI).SetRef(ref).Finalize(result);
 | |
| 
 | |
|     if (NS_FAILED(rv)) {
 | |
|       // If setting the ref failed, just return the original URI.
 | |
|       result = aURI;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return result.forget();
 | |
| }
 | |
| 
 | |
| already_AddRefed<nsIURI> css::URLValue::ResolveLocalRef(
 | |
|     nsIContent* aContent) const {
 | |
|   nsCOMPtr<nsIURI> url = aContent->GetBaseURI();
 | |
|   return ResolveLocalRef(url);
 | |
| }
 | |
| 
 | |
| void css::URLValue::GetSourceString(nsString& aRef) const {
 | |
|   nsIURI* uri = GetURI();
 | |
|   if (!uri) {
 | |
|     aRef.Truncate();
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   nsCString cref;
 | |
|   if (IsLocalRef()) {
 | |
|     // XXXheycam It's possible we can just return mString in this case, since
 | |
|     // it should be the "#fragment" string the URLValue was created with.
 | |
|     uri->GetRef(cref);
 | |
|     cref.Insert('#', 0);
 | |
|   } else {
 | |
|     // It's not entirely clear how to best handle failure here. Ensuring the
 | |
|     // string is empty seems safest.
 | |
|     nsresult rv = uri->GetSpec(cref);
 | |
|     if (NS_FAILED(rv)) {
 | |
|       cref.Truncate();
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   aRef = NS_ConvertUTF8toUTF16(cref);
 | |
| }
 | |
| 
 | |
| size_t css::URLValue::SizeOfIncludingThis(
 | |
|     mozilla::MallocSizeOf aMallocSizeOf) const {
 | |
|   // Measurement of the following members may be added later if DMD finds it
 | |
|   // is worthwhile:
 | |
|   // - mURI
 | |
|   // - mString
 | |
| 
 | |
|   // Only measure it if it's unshared, to avoid double-counting.
 | |
|   size_t n = 0;
 | |
|   if (mRefCnt <= 1) {
 | |
|     n += aMallocSizeOf(this);
 | |
|   }
 | |
|   return n;
 | |
| }
 | |
| 
 | |
| imgRequestProxy* css::URLValue::LoadImage(Document* aDocument) {
 | |
|   MOZ_ASSERT(NS_IsMainThread());
 | |
| 
 | |
|   static uint64_t sNextLoadID = 1;
 | |
| 
 | |
|   if (mLoadID == 0) {
 | |
|     mLoadID = sNextLoadID++;
 | |
|   }
 | |
| 
 | |
|   // NB: If aDocument is not the original document, we may not be able to load
 | |
|   // images from aDocument.  Instead we do the image load from the original doc
 | |
|   // and clone it to aDocument.
 | |
|   Document* loadingDoc = aDocument->GetOriginalDocument();
 | |
|   if (!loadingDoc) {
 | |
|     loadingDoc = aDocument;
 | |
|   }
 | |
| 
 | |
|   // Kick off the load in the loading document.
 | |
|   ImageLoader::LoadImage(this, loadingDoc);
 | |
| 
 | |
|   // Register the image in the document that's using it.
 | |
|   return aDocument->StyleImageLoader()->RegisterCSSImage(this);
 | |
| }
 | |
| 
 | |
| size_t mozilla::css::GridTemplateAreasValue::SizeOfIncludingThis(
 | |
|     mozilla::MallocSizeOf aMallocSizeOf) const {
 | |
|   // Only measure it if it's unshared, to avoid double-counting.
 | |
|   size_t n = 0;
 | |
|   if (mRefCnt <= 1) {
 | |
|     n += aMallocSizeOf(this);
 | |
|     n += mNamedAreas.ShallowSizeOfExcludingThis(aMallocSizeOf);
 | |
|     n += mTemplates.ShallowSizeOfExcludingThis(aMallocSizeOf);
 | |
|   }
 | |
|   return n;
 | |
| }
 |