michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 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: /* representation of length values in computed style data */ michael@0: michael@0: #ifndef nsStyleCoord_h___ michael@0: #define nsStyleCoord_h___ michael@0: michael@0: #include "nsCoord.h" michael@0: #include "nsStyleConsts.h" michael@0: michael@0: enum nsStyleUnit { michael@0: eStyleUnit_Null = 0, // (no value) value is not specified michael@0: eStyleUnit_Normal = 1, // (no value) michael@0: eStyleUnit_Auto = 2, // (no value) michael@0: eStyleUnit_None = 3, // (no value) michael@0: eStyleUnit_Percent = 10, // (float) 1.0 == 100% michael@0: eStyleUnit_Factor = 11, // (float) a multiplier michael@0: eStyleUnit_Degree = 12, // (float) angle in degrees michael@0: eStyleUnit_Grad = 13, // (float) angle in grads michael@0: eStyleUnit_Radian = 14, // (float) angle in radians michael@0: eStyleUnit_Turn = 15, // (float) angle in turns michael@0: eStyleUnit_FlexFraction = 16, // (float) in fr units michael@0: eStyleUnit_Coord = 20, // (nscoord) value is twips michael@0: eStyleUnit_Integer = 30, // (int) value is simple integer michael@0: eStyleUnit_Enumerated = 32, // (int) value has enumerated meaning michael@0: michael@0: // The following are allocated types. They are weak pointers to michael@0: // values allocated by nsStyleContext::Alloc. michael@0: eStyleUnit_Calc = 40 // (Calc*) calc() toplevel; always present michael@0: // to distinguish 50% from calc(50%), etc. michael@0: }; michael@0: michael@0: typedef union { michael@0: int32_t mInt; // nscoord is a int32_t for now michael@0: float mFloat; michael@0: // An mPointer is a weak pointer to a value that is guaranteed to michael@0: // outlive the nsStyleCoord. In the case of nsStyleCoord::Calc*, it michael@0: // is a pointer owned by the style context, allocated through michael@0: // nsStyleContext::Alloc (and, therefore, is never stored in the rule michael@0: // tree). michael@0: void* mPointer; michael@0: } nsStyleUnion; michael@0: michael@0: /** michael@0: * Class that hold a single size specification used by the style michael@0: * system. The size specification consists of two parts -- a number michael@0: * and a unit. The number is an integer, a floating point value, an michael@0: * nscoord, or undefined, and the unit is an nsStyleUnit. Checking michael@0: * the unit is a must before asking for the value in any particular michael@0: * form. michael@0: */ michael@0: class nsStyleCoord { michael@0: public: michael@0: struct Calc { michael@0: // Every calc() expression evaluates to a length plus a percentage. michael@0: nscoord mLength; michael@0: float mPercent; michael@0: bool mHasPercent; // whether there was any % syntax, even if 0 michael@0: michael@0: bool operator==(const Calc& aOther) const { michael@0: return mLength == aOther.mLength && michael@0: mPercent == aOther.mPercent && michael@0: mHasPercent == aOther.mHasPercent; michael@0: } michael@0: bool operator!=(const Calc& aOther) const { return !(*this == aOther); } michael@0: }; michael@0: michael@0: nsStyleCoord(nsStyleUnit aUnit = eStyleUnit_Null); michael@0: enum CoordConstructorType { CoordConstructor }; michael@0: inline nsStyleCoord(nscoord aValue, CoordConstructorType); michael@0: nsStyleCoord(int32_t aValue, nsStyleUnit aUnit); michael@0: nsStyleCoord(float aValue, nsStyleUnit aUnit); michael@0: inline nsStyleCoord(const nsStyleCoord& aCopy); michael@0: inline nsStyleCoord(const nsStyleUnion& aValue, nsStyleUnit aUnit); michael@0: michael@0: nsStyleCoord& operator=(const nsStyleCoord& aOther) michael@0: { michael@0: mUnit = aOther.mUnit; michael@0: mValue = aOther.mValue; michael@0: return *this; michael@0: } michael@0: bool operator==(const nsStyleCoord& aOther) const; michael@0: bool operator!=(const nsStyleCoord& aOther) const; michael@0: michael@0: nsStyleUnit GetUnit() const { michael@0: NS_ASSERTION(mUnit != eStyleUnit_Null, "reading uninitialized value"); michael@0: return mUnit; michael@0: } michael@0: michael@0: bool IsAngleValue() const { michael@0: return eStyleUnit_Degree <= mUnit && mUnit <= eStyleUnit_Turn; michael@0: } michael@0: michael@0: bool IsCalcUnit() const { michael@0: return eStyleUnit_Calc == mUnit; michael@0: } michael@0: michael@0: bool IsPointerValue() const { michael@0: return IsCalcUnit(); michael@0: } michael@0: michael@0: bool IsCoordPercentCalcUnit() const { michael@0: return mUnit == eStyleUnit_Coord || michael@0: mUnit == eStyleUnit_Percent || michael@0: IsCalcUnit(); michael@0: } michael@0: michael@0: // Does this calc() expression have any percentages inside it? Can be michael@0: // called only when IsCalcUnit() is true. michael@0: bool CalcHasPercent() const { michael@0: return GetCalcValue()->mHasPercent; michael@0: } michael@0: michael@0: bool HasPercent() const { michael@0: return mUnit == eStyleUnit_Percent || michael@0: (IsCalcUnit() && CalcHasPercent()); michael@0: } michael@0: michael@0: bool ConvertsToLength() const { michael@0: return mUnit == eStyleUnit_Coord || michael@0: (IsCalcUnit() && !CalcHasPercent()); michael@0: } michael@0: michael@0: nscoord GetCoordValue() const; michael@0: int32_t GetIntValue() const; michael@0: float GetPercentValue() const; michael@0: float GetFactorValue() const; michael@0: float GetAngleValue() const; michael@0: double GetAngleValueInRadians() const; michael@0: float GetFlexFractionValue() const; michael@0: Calc* GetCalcValue() const; michael@0: void GetUnionValue(nsStyleUnion& aValue) const; michael@0: uint32_t HashValue(uint32_t aHash) const; michael@0: michael@0: void Reset(); // sets to null michael@0: void SetCoordValue(nscoord aValue); michael@0: void SetIntValue(int32_t aValue, nsStyleUnit aUnit); michael@0: void SetPercentValue(float aValue); michael@0: void SetFactorValue(float aValue); michael@0: void SetAngleValue(float aValue, nsStyleUnit aUnit); michael@0: void SetFlexFractionValue(float aValue); michael@0: void SetNormalValue(); michael@0: void SetAutoValue(); michael@0: void SetNoneValue(); michael@0: void SetCalcValue(Calc* aValue); michael@0: michael@0: private: michael@0: nsStyleUnit mUnit; michael@0: nsStyleUnion mValue; michael@0: }; michael@0: michael@0: /** michael@0: * Class that represents a set of top/right/bottom/left nsStyleCoords. michael@0: * This is commonly used to hold the widths of the borders, margins, michael@0: * or paddings of a box. michael@0: */ michael@0: class nsStyleSides { michael@0: public: michael@0: nsStyleSides(); michael@0: michael@0: // nsStyleSides& operator=(const nsStyleSides& aCopy); // use compiler's version michael@0: bool operator==(const nsStyleSides& aOther) const; michael@0: bool operator!=(const nsStyleSides& aOther) const; michael@0: michael@0: inline nsStyleUnit GetUnit(mozilla::css::Side aSide) const; michael@0: inline nsStyleUnit GetLeftUnit() const; michael@0: inline nsStyleUnit GetTopUnit() const; michael@0: inline nsStyleUnit GetRightUnit() const; michael@0: inline nsStyleUnit GetBottomUnit() const; michael@0: michael@0: inline nsStyleCoord Get(mozilla::css::Side aSide) const; michael@0: inline nsStyleCoord GetLeft() const; michael@0: inline nsStyleCoord GetTop() const; michael@0: inline nsStyleCoord GetRight() const; michael@0: inline nsStyleCoord GetBottom() const; michael@0: michael@0: void Reset(); michael@0: michael@0: inline void Set(mozilla::css::Side aSide, const nsStyleCoord& aCoord); michael@0: inline void SetLeft(const nsStyleCoord& aCoord); michael@0: inline void SetTop(const nsStyleCoord& aCoord); michael@0: inline void SetRight(const nsStyleCoord& aCoord); michael@0: inline void SetBottom(const nsStyleCoord& aCoord); michael@0: michael@0: protected: michael@0: uint8_t mUnits[4]; michael@0: nsStyleUnion mValues[4]; michael@0: }; michael@0: michael@0: /** michael@0: * Class that represents a set of top-left/top-right/bottom-left/bottom-right michael@0: * nsStyleCoord pairs. This is used to hold the dimensions of the michael@0: * corners of a box (for, e.g., border-radius and outline-radius). michael@0: */ michael@0: class nsStyleCorners { michael@0: public: michael@0: nsStyleCorners(); michael@0: michael@0: // use compiler's version michael@0: //nsStyleCorners& operator=(const nsStyleCorners& aCopy); michael@0: bool operator==(const nsStyleCorners& aOther) const; michael@0: bool operator!=(const nsStyleCorners& aOther) const; michael@0: michael@0: // aCorner is always one of NS_CORNER_* defined in nsStyleConsts.h michael@0: inline nsStyleUnit GetUnit(uint8_t aHalfCorner) const; michael@0: michael@0: inline nsStyleCoord Get(uint8_t aHalfCorner) const; michael@0: michael@0: void Reset(); michael@0: michael@0: inline void Set(uint8_t aHalfCorner, const nsStyleCoord& aCoord); michael@0: michael@0: protected: michael@0: uint8_t mUnits[8]; michael@0: nsStyleUnion mValues[8]; michael@0: }; michael@0: michael@0: michael@0: // ------------------------- michael@0: // nsStyleCoord inlines michael@0: // michael@0: inline nsStyleCoord::nsStyleCoord(nscoord aValue, CoordConstructorType) michael@0: : mUnit(eStyleUnit_Coord) michael@0: { michael@0: mValue.mInt = aValue; michael@0: } michael@0: michael@0: // FIXME: In C++0x we can rely on the default copy constructor since michael@0: // default copy construction is defined properly for unions. But when michael@0: // can we actually use that? (It seems to work in gcc 4.4.) michael@0: inline nsStyleCoord::nsStyleCoord(const nsStyleCoord& aCopy) michael@0: : mUnit(aCopy.mUnit) michael@0: { michael@0: if ((eStyleUnit_Percent <= mUnit) && (mUnit < eStyleUnit_Coord)) { michael@0: mValue.mFloat = aCopy.mValue.mFloat; michael@0: } michael@0: else if (IsPointerValue()) { michael@0: mValue.mPointer = aCopy.mValue.mPointer; michael@0: } michael@0: else { michael@0: mValue.mInt = aCopy.mValue.mInt; michael@0: } michael@0: } michael@0: michael@0: inline nsStyleCoord::nsStyleCoord(const nsStyleUnion& aValue, nsStyleUnit aUnit) michael@0: : mUnit(aUnit), mValue(aValue) michael@0: { michael@0: } michael@0: michael@0: inline bool nsStyleCoord::operator!=(const nsStyleCoord& aOther) const michael@0: { michael@0: return !((*this) == aOther); michael@0: } michael@0: michael@0: inline nscoord nsStyleCoord::GetCoordValue() const michael@0: { michael@0: NS_ASSERTION((mUnit == eStyleUnit_Coord), "not a coord value"); michael@0: if (mUnit == eStyleUnit_Coord) { michael@0: return mValue.mInt; michael@0: } michael@0: return 0; michael@0: } michael@0: michael@0: inline int32_t nsStyleCoord::GetIntValue() const michael@0: { michael@0: NS_ASSERTION((mUnit == eStyleUnit_Enumerated) || michael@0: (mUnit == eStyleUnit_Integer), "not an int value"); michael@0: if ((mUnit == eStyleUnit_Enumerated) || michael@0: (mUnit == eStyleUnit_Integer)) { michael@0: return mValue.mInt; michael@0: } michael@0: return 0; michael@0: } michael@0: michael@0: inline float nsStyleCoord::GetPercentValue() const michael@0: { michael@0: NS_ASSERTION(mUnit == eStyleUnit_Percent, "not a percent value"); michael@0: if (mUnit == eStyleUnit_Percent) { michael@0: return mValue.mFloat; michael@0: } michael@0: return 0.0f; michael@0: } michael@0: michael@0: inline float nsStyleCoord::GetFactorValue() const michael@0: { michael@0: NS_ASSERTION(mUnit == eStyleUnit_Factor, "not a factor value"); michael@0: if (mUnit == eStyleUnit_Factor) { michael@0: return mValue.mFloat; michael@0: } michael@0: return 0.0f; michael@0: } michael@0: michael@0: inline float nsStyleCoord::GetAngleValue() const michael@0: { michael@0: NS_ASSERTION(mUnit >= eStyleUnit_Degree && michael@0: mUnit <= eStyleUnit_Turn, "not an angle value"); michael@0: if (mUnit >= eStyleUnit_Degree && mUnit <= eStyleUnit_Turn) { michael@0: return mValue.mFloat; michael@0: } michael@0: return 0.0f; michael@0: } michael@0: michael@0: inline float nsStyleCoord::GetFlexFractionValue() const michael@0: { michael@0: NS_ASSERTION(mUnit == eStyleUnit_FlexFraction, "not a fr value"); michael@0: if (mUnit == eStyleUnit_FlexFraction) { michael@0: return mValue.mFloat; michael@0: } michael@0: return 0.0f; michael@0: } michael@0: michael@0: inline nsStyleCoord::Calc* nsStyleCoord::GetCalcValue() const michael@0: { michael@0: NS_ASSERTION(IsCalcUnit(), "not a pointer value"); michael@0: if (IsCalcUnit()) { michael@0: return static_cast(mValue.mPointer); michael@0: } michael@0: return nullptr; michael@0: } michael@0: michael@0: michael@0: inline void nsStyleCoord::GetUnionValue(nsStyleUnion& aValue) const michael@0: { michael@0: aValue = mValue; michael@0: } michael@0: michael@0: // ------------------------- michael@0: // nsStyleSides inlines michael@0: // michael@0: inline bool nsStyleSides::operator!=(const nsStyleSides& aOther) const michael@0: { michael@0: return !((*this) == aOther); michael@0: } michael@0: michael@0: inline nsStyleUnit nsStyleSides::GetUnit(mozilla::css::Side aSide) const michael@0: { michael@0: return (nsStyleUnit)mUnits[aSide]; michael@0: } michael@0: michael@0: inline nsStyleUnit nsStyleSides::GetLeftUnit() const michael@0: { michael@0: return GetUnit(NS_SIDE_LEFT); michael@0: } michael@0: michael@0: inline nsStyleUnit nsStyleSides::GetTopUnit() const michael@0: { michael@0: return GetUnit(NS_SIDE_TOP); michael@0: } michael@0: michael@0: inline nsStyleUnit nsStyleSides::GetRightUnit() const michael@0: { michael@0: return GetUnit(NS_SIDE_RIGHT); michael@0: } michael@0: michael@0: inline nsStyleUnit nsStyleSides::GetBottomUnit() const michael@0: { michael@0: return GetUnit(NS_SIDE_BOTTOM); michael@0: } michael@0: michael@0: inline nsStyleCoord nsStyleSides::Get(mozilla::css::Side aSide) const michael@0: { michael@0: return nsStyleCoord(mValues[aSide], nsStyleUnit(mUnits[aSide])); michael@0: } michael@0: michael@0: inline nsStyleCoord nsStyleSides::GetLeft() const michael@0: { michael@0: return Get(NS_SIDE_LEFT); michael@0: } michael@0: michael@0: inline nsStyleCoord nsStyleSides::GetTop() const michael@0: { michael@0: return Get(NS_SIDE_TOP); michael@0: } michael@0: michael@0: inline nsStyleCoord nsStyleSides::GetRight() const michael@0: { michael@0: return Get(NS_SIDE_RIGHT); michael@0: } michael@0: michael@0: inline nsStyleCoord nsStyleSides::GetBottom() const michael@0: { michael@0: return Get(NS_SIDE_BOTTOM); michael@0: } michael@0: michael@0: inline void nsStyleSides::Set(mozilla::css::Side aSide, const nsStyleCoord& aCoord) michael@0: { michael@0: mUnits[aSide] = aCoord.GetUnit(); michael@0: aCoord.GetUnionValue(mValues[aSide]); michael@0: } michael@0: michael@0: inline void nsStyleSides::SetLeft(const nsStyleCoord& aCoord) michael@0: { michael@0: Set(NS_SIDE_LEFT, aCoord); michael@0: } michael@0: michael@0: inline void nsStyleSides::SetTop(const nsStyleCoord& aCoord) michael@0: { michael@0: Set(NS_SIDE_TOP, aCoord); michael@0: } michael@0: michael@0: inline void nsStyleSides::SetRight(const nsStyleCoord& aCoord) michael@0: { michael@0: Set(NS_SIDE_RIGHT, aCoord); michael@0: } michael@0: michael@0: inline void nsStyleSides::SetBottom(const nsStyleCoord& aCoord) michael@0: { michael@0: Set(NS_SIDE_BOTTOM, aCoord); michael@0: } michael@0: michael@0: // ------------------------- michael@0: // nsStyleCorners inlines michael@0: // michael@0: inline bool nsStyleCorners::operator!=(const nsStyleCorners& aOther) const michael@0: { michael@0: return !((*this) == aOther); michael@0: } michael@0: michael@0: inline nsStyleUnit nsStyleCorners::GetUnit(uint8_t aCorner) const michael@0: { michael@0: return (nsStyleUnit)mUnits[aCorner]; michael@0: } michael@0: michael@0: inline nsStyleCoord nsStyleCorners::Get(uint8_t aCorner) const michael@0: { michael@0: return nsStyleCoord(mValues[aCorner], nsStyleUnit(mUnits[aCorner])); michael@0: } michael@0: michael@0: inline void nsStyleCorners::Set(uint8_t aCorner, const nsStyleCoord& aCoord) michael@0: { michael@0: mUnits[aCorner] = aCoord.GetUnit(); michael@0: aCoord.GetUnionValue(mValues[aCorner]); michael@0: } michael@0: michael@0: #endif /* nsStyleCoord_h___ */