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: #include "nsStyleCoord.h" michael@0: #include "mozilla/HashFunctions.h" michael@0: michael@0: nsStyleCoord::nsStyleCoord(nsStyleUnit aUnit) michael@0: : mUnit(aUnit) michael@0: { michael@0: NS_ASSERTION(aUnit < eStyleUnit_Percent, "not a valueless unit"); michael@0: if (aUnit >= eStyleUnit_Percent) { michael@0: mUnit = eStyleUnit_Null; michael@0: } michael@0: mValue.mInt = 0; michael@0: } michael@0: michael@0: nsStyleCoord::nsStyleCoord(int32_t aValue, nsStyleUnit aUnit) michael@0: : mUnit(aUnit) michael@0: { michael@0: //if you want to pass in eStyleUnit_Coord, don't. instead, use the michael@0: //constructor just above this one... MMP michael@0: NS_ASSERTION((aUnit == eStyleUnit_Enumerated) || michael@0: (aUnit == eStyleUnit_Integer), "not an int value"); michael@0: if ((aUnit == eStyleUnit_Enumerated) || michael@0: (aUnit == eStyleUnit_Integer)) { michael@0: mValue.mInt = aValue; michael@0: } michael@0: else { michael@0: mUnit = eStyleUnit_Null; michael@0: mValue.mInt = 0; michael@0: } michael@0: } michael@0: michael@0: nsStyleCoord::nsStyleCoord(float aValue, nsStyleUnit aUnit) michael@0: : mUnit(aUnit) michael@0: { michael@0: if (aUnit < eStyleUnit_Percent || aUnit >= eStyleUnit_Coord) { michael@0: NS_NOTREACHED("not a float value"); michael@0: Reset(); michael@0: } else { michael@0: mValue.mFloat = aValue; michael@0: } michael@0: } michael@0: michael@0: bool nsStyleCoord::operator==(const nsStyleCoord& aOther) const michael@0: { michael@0: if (mUnit != aOther.mUnit) { michael@0: return false; michael@0: } michael@0: switch (mUnit) { michael@0: case eStyleUnit_Null: michael@0: case eStyleUnit_Normal: michael@0: case eStyleUnit_Auto: michael@0: case eStyleUnit_None: michael@0: return true; michael@0: case eStyleUnit_Percent: michael@0: case eStyleUnit_Factor: michael@0: case eStyleUnit_Degree: michael@0: case eStyleUnit_Grad: michael@0: case eStyleUnit_Radian: michael@0: case eStyleUnit_Turn: michael@0: case eStyleUnit_FlexFraction: michael@0: return mValue.mFloat == aOther.mValue.mFloat; michael@0: case eStyleUnit_Coord: michael@0: case eStyleUnit_Integer: michael@0: case eStyleUnit_Enumerated: michael@0: return mValue.mInt == aOther.mValue.mInt; michael@0: case eStyleUnit_Calc: michael@0: return *this->GetCalcValue() == *aOther.GetCalcValue(); michael@0: } michael@0: NS_ABORT_IF_FALSE(false, "unexpected unit"); michael@0: return false; michael@0: } michael@0: michael@0: uint32_t nsStyleCoord::HashValue(uint32_t aHash = 0) const michael@0: { michael@0: aHash = mozilla::AddToHash(aHash, mUnit); michael@0: michael@0: switch (mUnit) { michael@0: case eStyleUnit_Null: michael@0: case eStyleUnit_Normal: michael@0: case eStyleUnit_Auto: michael@0: case eStyleUnit_None: michael@0: return mozilla::AddToHash(aHash, true); michael@0: case eStyleUnit_Percent: michael@0: case eStyleUnit_Factor: michael@0: case eStyleUnit_Degree: michael@0: case eStyleUnit_Grad: michael@0: case eStyleUnit_Radian: michael@0: case eStyleUnit_Turn: michael@0: case eStyleUnit_FlexFraction: michael@0: return mozilla::AddToHash(aHash, mValue.mFloat); michael@0: case eStyleUnit_Coord: michael@0: case eStyleUnit_Integer: michael@0: case eStyleUnit_Enumerated: michael@0: return mozilla::AddToHash(aHash, mValue.mInt); michael@0: case eStyleUnit_Calc: michael@0: Calc* calcValue = GetCalcValue(); michael@0: aHash = mozilla::AddToHash(aHash, calcValue->mLength); michael@0: if (HasPercent()) { michael@0: return mozilla::AddToHash(aHash, calcValue->mPercent); michael@0: } michael@0: return aHash; michael@0: } michael@0: NS_ABORT_IF_FALSE(false, "unexpected unit"); michael@0: return aHash; michael@0: } michael@0: michael@0: void nsStyleCoord::Reset() michael@0: { michael@0: mUnit = eStyleUnit_Null; michael@0: mValue.mInt = 0; michael@0: } michael@0: michael@0: void nsStyleCoord::SetCoordValue(nscoord aValue) michael@0: { michael@0: mUnit = eStyleUnit_Coord; michael@0: mValue.mInt = aValue; michael@0: } michael@0: michael@0: void nsStyleCoord::SetIntValue(int32_t aValue, nsStyleUnit aUnit) michael@0: { michael@0: NS_ASSERTION((aUnit == eStyleUnit_Enumerated) || michael@0: (aUnit == eStyleUnit_Integer), "not an int value"); michael@0: if ((aUnit == eStyleUnit_Enumerated) || michael@0: (aUnit == eStyleUnit_Integer)) { michael@0: mUnit = aUnit; michael@0: mValue.mInt = aValue; michael@0: } michael@0: else { michael@0: Reset(); michael@0: } michael@0: } michael@0: michael@0: void nsStyleCoord::SetPercentValue(float aValue) michael@0: { michael@0: mUnit = eStyleUnit_Percent; michael@0: mValue.mFloat = aValue; michael@0: } michael@0: michael@0: void nsStyleCoord::SetFactorValue(float aValue) michael@0: { michael@0: mUnit = eStyleUnit_Factor; michael@0: mValue.mFloat = aValue; michael@0: } michael@0: michael@0: void nsStyleCoord::SetAngleValue(float aValue, nsStyleUnit aUnit) michael@0: { michael@0: if (aUnit == eStyleUnit_Degree || michael@0: aUnit == eStyleUnit_Grad || michael@0: aUnit == eStyleUnit_Radian || michael@0: aUnit == eStyleUnit_Turn) { michael@0: mUnit = aUnit; michael@0: mValue.mFloat = aValue; michael@0: } else { michael@0: NS_NOTREACHED("not an angle value"); michael@0: Reset(); michael@0: } michael@0: } michael@0: michael@0: void nsStyleCoord::SetFlexFractionValue(float aValue) michael@0: { michael@0: mUnit = eStyleUnit_FlexFraction; michael@0: mValue.mFloat = aValue; michael@0: } michael@0: michael@0: void nsStyleCoord::SetCalcValue(Calc* aValue) michael@0: { michael@0: mUnit = eStyleUnit_Calc; michael@0: mValue.mPointer = aValue; michael@0: } michael@0: michael@0: void nsStyleCoord::SetNormalValue() michael@0: { michael@0: mUnit = eStyleUnit_Normal; michael@0: mValue.mInt = 0; michael@0: } michael@0: michael@0: void nsStyleCoord::SetAutoValue() michael@0: { michael@0: mUnit = eStyleUnit_Auto; michael@0: mValue.mInt = 0; michael@0: } michael@0: michael@0: void nsStyleCoord::SetNoneValue() michael@0: { michael@0: mUnit = eStyleUnit_None; michael@0: mValue.mInt = 0; michael@0: } michael@0: michael@0: // accessors that are not inlined michael@0: michael@0: double michael@0: nsStyleCoord::GetAngleValueInRadians() const michael@0: { michael@0: double angle = mValue.mFloat; michael@0: michael@0: switch (GetUnit()) { michael@0: case eStyleUnit_Radian: return angle; michael@0: case eStyleUnit_Turn: return angle * 2 * M_PI; michael@0: case eStyleUnit_Degree: return angle * M_PI / 180.0; michael@0: case eStyleUnit_Grad: return angle * M_PI / 200.0; michael@0: michael@0: default: michael@0: NS_NOTREACHED("unrecognized angular unit"); michael@0: return 0.0; michael@0: } michael@0: } michael@0: michael@0: nsStyleSides::nsStyleSides() michael@0: { michael@0: memset(this, 0x00, sizeof(nsStyleSides)); michael@0: } michael@0: michael@0: bool nsStyleSides::operator==(const nsStyleSides& aOther) const michael@0: { michael@0: NS_FOR_CSS_SIDES(i) { michael@0: if (nsStyleCoord(mValues[i], (nsStyleUnit)mUnits[i]) != michael@0: nsStyleCoord(aOther.mValues[i], (nsStyleUnit)aOther.mUnits[i])) { michael@0: return false; michael@0: } michael@0: } michael@0: return true; michael@0: } michael@0: michael@0: void nsStyleSides::Reset() michael@0: { michael@0: memset(this, 0x00, sizeof(nsStyleSides)); michael@0: } michael@0: michael@0: nsStyleCorners::nsStyleCorners() michael@0: { michael@0: memset(this, 0x00, sizeof(nsStyleCorners)); michael@0: } michael@0: michael@0: bool michael@0: nsStyleCorners::operator==(const nsStyleCorners& aOther) const michael@0: { michael@0: NS_FOR_CSS_HALF_CORNERS(i) { michael@0: if (nsStyleCoord(mValues[i], (nsStyleUnit)mUnits[i]) != michael@0: nsStyleCoord(aOther.mValues[i], (nsStyleUnit)aOther.mUnits[i])) { michael@0: return false; michael@0: } michael@0: } michael@0: return true; michael@0: } michael@0: michael@0: void nsStyleCorners::Reset() michael@0: { michael@0: memset(this, 0x00, sizeof(nsStyleCorners)); michael@0: } michael@0: michael@0: // Validation of NS_SIDE_IS_VERTICAL and NS_HALF_CORNER_IS_X. michael@0: #define CASE(side, result) \ michael@0: static_assert(NS_SIDE_IS_VERTICAL(side) == result, \ michael@0: "NS_SIDE_IS_VERTICAL is wrong") michael@0: CASE(NS_SIDE_TOP, false); michael@0: CASE(NS_SIDE_RIGHT, true); michael@0: CASE(NS_SIDE_BOTTOM, false); michael@0: CASE(NS_SIDE_LEFT, true); michael@0: #undef CASE michael@0: michael@0: #define CASE(corner, result) \ michael@0: static_assert(NS_HALF_CORNER_IS_X(corner) == result, \ michael@0: "NS_HALF_CORNER_IS_X is wrong") michael@0: CASE(NS_CORNER_TOP_LEFT_X, true); michael@0: CASE(NS_CORNER_TOP_LEFT_Y, false); michael@0: CASE(NS_CORNER_TOP_RIGHT_X, true); michael@0: CASE(NS_CORNER_TOP_RIGHT_Y, false); michael@0: CASE(NS_CORNER_BOTTOM_RIGHT_X, true); michael@0: CASE(NS_CORNER_BOTTOM_RIGHT_Y, false); michael@0: CASE(NS_CORNER_BOTTOM_LEFT_X, true); michael@0: CASE(NS_CORNER_BOTTOM_LEFT_Y, false); michael@0: #undef CASE michael@0: michael@0: // Validation of NS_HALF_TO_FULL_CORNER. michael@0: #define CASE(corner, result) \ michael@0: static_assert(NS_HALF_TO_FULL_CORNER(corner) == result, \ michael@0: "NS_HALF_TO_FULL_CORNER is wrong") michael@0: CASE(NS_CORNER_TOP_LEFT_X, NS_CORNER_TOP_LEFT); michael@0: CASE(NS_CORNER_TOP_LEFT_Y, NS_CORNER_TOP_LEFT); michael@0: CASE(NS_CORNER_TOP_RIGHT_X, NS_CORNER_TOP_RIGHT); michael@0: CASE(NS_CORNER_TOP_RIGHT_Y, NS_CORNER_TOP_RIGHT); michael@0: CASE(NS_CORNER_BOTTOM_RIGHT_X, NS_CORNER_BOTTOM_RIGHT); michael@0: CASE(NS_CORNER_BOTTOM_RIGHT_Y, NS_CORNER_BOTTOM_RIGHT); michael@0: CASE(NS_CORNER_BOTTOM_LEFT_X, NS_CORNER_BOTTOM_LEFT); michael@0: CASE(NS_CORNER_BOTTOM_LEFT_Y, NS_CORNER_BOTTOM_LEFT); michael@0: #undef CASE michael@0: michael@0: // Validation of NS_FULL_TO_HALF_CORNER. michael@0: #define CASE(corner, vert, result) \ michael@0: static_assert(NS_FULL_TO_HALF_CORNER(corner, vert) == result, \ michael@0: "NS_FULL_TO_HALF_CORNER is wrong") michael@0: CASE(NS_CORNER_TOP_LEFT, false, NS_CORNER_TOP_LEFT_X); michael@0: CASE(NS_CORNER_TOP_LEFT, true, NS_CORNER_TOP_LEFT_Y); michael@0: CASE(NS_CORNER_TOP_RIGHT, false, NS_CORNER_TOP_RIGHT_X); michael@0: CASE(NS_CORNER_TOP_RIGHT, true, NS_CORNER_TOP_RIGHT_Y); michael@0: CASE(NS_CORNER_BOTTOM_RIGHT, false, NS_CORNER_BOTTOM_RIGHT_X); michael@0: CASE(NS_CORNER_BOTTOM_RIGHT, true, NS_CORNER_BOTTOM_RIGHT_Y); michael@0: CASE(NS_CORNER_BOTTOM_LEFT, false, NS_CORNER_BOTTOM_LEFT_X); michael@0: CASE(NS_CORNER_BOTTOM_LEFT, true, NS_CORNER_BOTTOM_LEFT_Y); michael@0: #undef CASE michael@0: michael@0: // Validation of NS_SIDE_TO_{FULL,HALF}_CORNER. michael@0: #define CASE(side, second, result) \ michael@0: static_assert(NS_SIDE_TO_FULL_CORNER(side, second) == result, \ michael@0: "NS_SIDE_TO_FULL_CORNER is wrong") michael@0: CASE(NS_SIDE_TOP, false, NS_CORNER_TOP_LEFT); michael@0: CASE(NS_SIDE_TOP, true, NS_CORNER_TOP_RIGHT); michael@0: michael@0: CASE(NS_SIDE_RIGHT, false, NS_CORNER_TOP_RIGHT); michael@0: CASE(NS_SIDE_RIGHT, true, NS_CORNER_BOTTOM_RIGHT); michael@0: michael@0: CASE(NS_SIDE_BOTTOM, false, NS_CORNER_BOTTOM_RIGHT); michael@0: CASE(NS_SIDE_BOTTOM, true, NS_CORNER_BOTTOM_LEFT); michael@0: michael@0: CASE(NS_SIDE_LEFT, false, NS_CORNER_BOTTOM_LEFT); michael@0: CASE(NS_SIDE_LEFT, true, NS_CORNER_TOP_LEFT); michael@0: #undef CASE michael@0: michael@0: #define CASE(side, second, parallel, result) \ michael@0: static_assert(NS_SIDE_TO_HALF_CORNER(side, second, parallel) == result, \ michael@0: "NS_SIDE_TO_HALF_CORNER is wrong") michael@0: CASE(NS_SIDE_TOP, false, true, NS_CORNER_TOP_LEFT_X); michael@0: CASE(NS_SIDE_TOP, false, false, NS_CORNER_TOP_LEFT_Y); michael@0: CASE(NS_SIDE_TOP, true, true, NS_CORNER_TOP_RIGHT_X); michael@0: CASE(NS_SIDE_TOP, true, false, NS_CORNER_TOP_RIGHT_Y); michael@0: michael@0: CASE(NS_SIDE_RIGHT, false, false, NS_CORNER_TOP_RIGHT_X); michael@0: CASE(NS_SIDE_RIGHT, false, true, NS_CORNER_TOP_RIGHT_Y); michael@0: CASE(NS_SIDE_RIGHT, true, false, NS_CORNER_BOTTOM_RIGHT_X); michael@0: CASE(NS_SIDE_RIGHT, true, true, NS_CORNER_BOTTOM_RIGHT_Y); michael@0: michael@0: CASE(NS_SIDE_BOTTOM, false, true, NS_CORNER_BOTTOM_RIGHT_X); michael@0: CASE(NS_SIDE_BOTTOM, false, false, NS_CORNER_BOTTOM_RIGHT_Y); michael@0: CASE(NS_SIDE_BOTTOM, true, true, NS_CORNER_BOTTOM_LEFT_X); michael@0: CASE(NS_SIDE_BOTTOM, true, false, NS_CORNER_BOTTOM_LEFT_Y); michael@0: michael@0: CASE(NS_SIDE_LEFT, false, false, NS_CORNER_BOTTOM_LEFT_X); michael@0: CASE(NS_SIDE_LEFT, false, true, NS_CORNER_BOTTOM_LEFT_Y); michael@0: CASE(NS_SIDE_LEFT, true, false, NS_CORNER_TOP_LEFT_X); michael@0: CASE(NS_SIDE_LEFT, true, true, NS_CORNER_TOP_LEFT_Y); michael@0: #undef CASE