michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef nsAttrValueInlines_h__ michael@0: #define nsAttrValueInlines_h__ michael@0: michael@0: #include michael@0: michael@0: #include "nsAttrValue.h" michael@0: michael@0: struct MiscContainer michael@0: { michael@0: typedef nsAttrValue::ValueType ValueType; michael@0: michael@0: ValueType mType; michael@0: // mStringBits points to either nsIAtom* or nsStringBuffer* and is used when michael@0: // mType isn't mCSSStyleRule. michael@0: // Note eStringBase and eAtomBase is used also to handle the type of michael@0: // mStringBits. michael@0: uintptr_t mStringBits; michael@0: union { michael@0: struct { michael@0: union { michael@0: int32_t mInteger; michael@0: nscolor mColor; michael@0: uint32_t mEnumValue; michael@0: int32_t mPercent; michael@0: mozilla::css::StyleRule* mCSSStyleRule; michael@0: mozilla::css::URLValue* mURL; michael@0: mozilla::css::ImageValue* mImage; michael@0: nsAttrValue::AtomArray* mAtomArray; michael@0: nsIntMargin* mIntMargin; michael@0: const nsSVGAngle* mSVGAngle; michael@0: const nsSVGIntegerPair* mSVGIntegerPair; michael@0: const nsSVGLength2* mSVGLength; michael@0: const mozilla::SVGLengthList* mSVGLengthList; michael@0: const mozilla::SVGNumberList* mSVGNumberList; michael@0: const nsSVGNumberPair* mSVGNumberPair; michael@0: const mozilla::SVGPathData* mSVGPathData; michael@0: const mozilla::SVGPointList* mSVGPointList; michael@0: const mozilla::SVGAnimatedPreserveAspectRatio* mSVGPreserveAspectRatio; michael@0: const mozilla::SVGStringList* mSVGStringList; michael@0: const mozilla::SVGTransformList* mSVGTransformList; michael@0: const nsSVGViewBox* mSVGViewBox; michael@0: }; michael@0: uint32_t mRefCount : 31; michael@0: uint32_t mCached : 1; michael@0: } mValue; michael@0: double mDoubleValue; michael@0: }; michael@0: michael@0: MiscContainer() michael@0: : mType(nsAttrValue::eColor), michael@0: mStringBits(0) michael@0: { michael@0: MOZ_COUNT_CTOR(MiscContainer); michael@0: mValue.mColor = 0; michael@0: mValue.mRefCount = 0; michael@0: mValue.mCached = 0; michael@0: } michael@0: michael@0: ~MiscContainer() michael@0: { michael@0: if (IsRefCounted()) { michael@0: MOZ_ASSERT(mValue.mRefCount == 0); michael@0: MOZ_ASSERT(!mValue.mCached); michael@0: } michael@0: MOZ_COUNT_DTOR(MiscContainer); michael@0: } michael@0: michael@0: bool GetString(nsAString& aString) const; michael@0: michael@0: inline bool IsRefCounted() const michael@0: { michael@0: // Nothing stops us from refcounting (and sharing) other types of michael@0: // MiscContainer (except eDoubleValue types) but there's no compelling michael@0: // reason to michael@0: return mType == nsAttrValue::eCSSStyleRule; michael@0: } michael@0: michael@0: inline int32_t AddRef() { michael@0: MOZ_ASSERT(IsRefCounted()); michael@0: return ++mValue.mRefCount; michael@0: } michael@0: michael@0: inline int32_t Release() { michael@0: MOZ_ASSERT(IsRefCounted()); michael@0: return --mValue.mRefCount; michael@0: } michael@0: michael@0: void Cache(); michael@0: void Evict(); michael@0: }; michael@0: michael@0: michael@0: /** michael@0: * Implementation of inline methods michael@0: */ michael@0: michael@0: inline int32_t michael@0: nsAttrValue::GetIntegerValue() const michael@0: { michael@0: NS_PRECONDITION(Type() == eInteger, "wrong type"); michael@0: return (BaseType() == eIntegerBase) michael@0: ? GetIntInternal() michael@0: : GetMiscContainer()->mValue.mInteger; michael@0: } michael@0: michael@0: inline int16_t michael@0: nsAttrValue::GetEnumValue() const michael@0: { michael@0: NS_PRECONDITION(Type() == eEnum, "wrong type"); michael@0: // We don't need to worry about sign extension here since we're michael@0: // returning an int16_t which will cut away the top bits. michael@0: return static_cast(( michael@0: (BaseType() == eIntegerBase) michael@0: ? static_cast(GetIntInternal()) michael@0: : GetMiscContainer()->mValue.mEnumValue) michael@0: >> NS_ATTRVALUE_ENUMTABLEINDEX_BITS); michael@0: } michael@0: michael@0: inline float michael@0: nsAttrValue::GetPercentValue() const michael@0: { michael@0: NS_PRECONDITION(Type() == ePercent, "wrong type"); michael@0: return ((BaseType() == eIntegerBase) michael@0: ? GetIntInternal() michael@0: : GetMiscContainer()->mValue.mPercent) michael@0: / 100.0f; michael@0: } michael@0: michael@0: inline nsAttrValue::AtomArray* michael@0: nsAttrValue::GetAtomArrayValue() const michael@0: { michael@0: NS_PRECONDITION(Type() == eAtomArray, "wrong type"); michael@0: return GetMiscContainer()->mValue.mAtomArray; michael@0: } michael@0: michael@0: inline mozilla::css::StyleRule* michael@0: nsAttrValue::GetCSSStyleRuleValue() const michael@0: { michael@0: NS_PRECONDITION(Type() == eCSSStyleRule, "wrong type"); michael@0: return GetMiscContainer()->mValue.mCSSStyleRule; michael@0: } michael@0: michael@0: inline mozilla::css::URLValue* michael@0: nsAttrValue::GetURLValue() const michael@0: { michael@0: NS_PRECONDITION(Type() == eURL, "wrong type"); michael@0: return GetMiscContainer()->mValue.mURL; michael@0: } michael@0: michael@0: inline mozilla::css::ImageValue* michael@0: nsAttrValue::GetImageValue() const michael@0: { michael@0: NS_PRECONDITION(Type() == eImage, "wrong type"); michael@0: return GetMiscContainer()->mValue.mImage; michael@0: } michael@0: michael@0: inline double michael@0: nsAttrValue::GetDoubleValue() const michael@0: { michael@0: NS_PRECONDITION(Type() == eDoubleValue, "wrong type"); michael@0: return GetMiscContainer()->mDoubleValue; michael@0: } michael@0: michael@0: inline bool michael@0: nsAttrValue::GetIntMarginValue(nsIntMargin& aMargin) const michael@0: { michael@0: NS_PRECONDITION(Type() == eIntMarginValue, "wrong type"); michael@0: nsIntMargin* m = GetMiscContainer()->mValue.mIntMargin; michael@0: if (!m) michael@0: return false; michael@0: aMargin = *m; michael@0: return true; michael@0: } michael@0: michael@0: inline bool michael@0: nsAttrValue::IsSVGType(ValueType aType) const michael@0: { michael@0: return aType >= eSVGTypesBegin && aType <= eSVGTypesEnd; michael@0: } michael@0: michael@0: inline void michael@0: nsAttrValue::SetPtrValueAndType(void* aValue, ValueBaseType aType) michael@0: { michael@0: NS_ASSERTION(!(NS_PTR_TO_INT32(aValue) & ~NS_ATTRVALUE_POINTERVALUE_MASK), michael@0: "pointer not properly aligned, this will crash"); michael@0: mBits = reinterpret_cast(aValue) | aType; michael@0: } michael@0: michael@0: inline void michael@0: nsAttrValue::ResetIfSet() michael@0: { michael@0: if (mBits) { michael@0: Reset(); michael@0: } michael@0: } michael@0: michael@0: inline MiscContainer* michael@0: nsAttrValue::GetMiscContainer() const michael@0: { michael@0: NS_ASSERTION(BaseType() == eOtherBase, "wrong type"); michael@0: return static_cast(GetPtr()); michael@0: } michael@0: michael@0: inline int32_t michael@0: nsAttrValue::GetIntInternal() const michael@0: { michael@0: NS_ASSERTION(BaseType() == eIntegerBase, michael@0: "getting integer from non-integer"); michael@0: // Make sure we get a signed value. michael@0: // Lets hope the optimizer optimizes this into a shift. Unfortunatly signed michael@0: // bitshift right is implementaion dependant. michael@0: return static_cast(mBits & ~NS_ATTRVALUE_INTEGERTYPE_MASK) / michael@0: NS_ATTRVALUE_INTEGERTYPE_MULTIPLIER; michael@0: } michael@0: michael@0: #endif