forked from mirrors/gecko-dev
		
	 265e672179
			
		
	
	
		265e672179
		
	
	
	
	
		
			
			# ignore-this-changeset --HG-- extra : amend_source : 4d301d3b0b8711c4692392aa76088ba7fd7d1022
		
			
				
	
	
		
			333 lines
		
	
	
	
		
			9.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			333 lines
		
	
	
	
		
			9.7 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 length values in computed style data */
 | |
| 
 | |
| #include "mozilla/HashFunctions.h"
 | |
| #include "mozilla/PodOperations.h"
 | |
| 
 | |
| // nsStyleCoord.h must not be the first header in a unified source file,
 | |
| // otherwise it may not build with MSVC due to a bug in our STL wrapper.
 | |
| // See bug 1331102.
 | |
| #include "nsStyleCoord.h"
 | |
| 
 | |
| using namespace mozilla;
 | |
| 
 | |
| nsStyleCoord::nsStyleCoord(nsStyleUnit aUnit) : mUnit(aUnit) {
 | |
|   NS_ASSERTION(aUnit < eStyleUnit_Percent, "not a valueless unit");
 | |
|   if (aUnit >= eStyleUnit_Percent) {
 | |
|     mUnit = eStyleUnit_Null;
 | |
|   }
 | |
|   mValue.mInt = 0;
 | |
| }
 | |
| 
 | |
| nsStyleCoord::nsStyleCoord(int32_t aValue, nsStyleUnit aUnit) : mUnit(aUnit) {
 | |
|   // if you want to pass in eStyleUnit_Coord, don't. instead, use the
 | |
|   // constructor just above this one... MMP
 | |
|   NS_ASSERTION(
 | |
|       (aUnit == eStyleUnit_Enumerated) || (aUnit == eStyleUnit_Integer),
 | |
|       "not an int value");
 | |
|   if ((aUnit == eStyleUnit_Enumerated) || (aUnit == eStyleUnit_Integer)) {
 | |
|     mValue.mInt = aValue;
 | |
|   } else {
 | |
|     mUnit = eStyleUnit_Null;
 | |
|     mValue.mInt = 0;
 | |
|   }
 | |
| }
 | |
| 
 | |
| nsStyleCoord::nsStyleCoord(float aValue, nsStyleUnit aUnit) : mUnit(aUnit) {
 | |
|   if (aUnit < eStyleUnit_Percent || aUnit >= eStyleUnit_Coord) {
 | |
|     MOZ_ASSERT_UNREACHABLE("not a float value");
 | |
|     mUnit = eStyleUnit_Null;
 | |
|     mValue.mInt = 0;
 | |
|   } else {
 | |
|     mValue.mFloat = aValue;
 | |
|   }
 | |
| }
 | |
| 
 | |
| bool nsStyleCoord::operator==(const nsStyleCoord& aOther) const {
 | |
|   if (mUnit != aOther.mUnit) {
 | |
|     return false;
 | |
|   }
 | |
|   switch (mUnit) {
 | |
|     case eStyleUnit_Null:
 | |
|     case eStyleUnit_Normal:
 | |
|     case eStyleUnit_Auto:
 | |
|     case eStyleUnit_None:
 | |
|       return true;
 | |
|     case eStyleUnit_Percent:
 | |
|     case eStyleUnit_Factor:
 | |
|     case eStyleUnit_Degree:
 | |
|     case eStyleUnit_FlexFraction:
 | |
|       return mValue.mFloat == aOther.mValue.mFloat;
 | |
|     case eStyleUnit_Coord:
 | |
|     case eStyleUnit_Integer:
 | |
|     case eStyleUnit_Enumerated:
 | |
|       return mValue.mInt == aOther.mValue.mInt;
 | |
|     case eStyleUnit_Calc:
 | |
|       return *this->GetCalcValue() == *aOther.GetCalcValue();
 | |
|   }
 | |
|   MOZ_ASSERT(false, "unexpected unit");
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| void nsStyleCoord::Reset() { Reset(mUnit, mValue); }
 | |
| 
 | |
| void nsStyleCoord::SetCoordValue(nscoord aValue) {
 | |
|   Reset();
 | |
|   mUnit = eStyleUnit_Coord;
 | |
|   mValue.mInt = aValue;
 | |
| }
 | |
| 
 | |
| void nsStyleCoord::SetIntValue(int32_t aValue, nsStyleUnit aUnit) {
 | |
|   NS_ASSERTION(
 | |
|       (aUnit == eStyleUnit_Enumerated) || (aUnit == eStyleUnit_Integer),
 | |
|       "not an int value");
 | |
|   Reset();
 | |
|   if ((aUnit == eStyleUnit_Enumerated) || (aUnit == eStyleUnit_Integer)) {
 | |
|     mUnit = aUnit;
 | |
|     mValue.mInt = aValue;
 | |
|   }
 | |
| }
 | |
| 
 | |
| void nsStyleCoord::SetPercentValue(float aValue) {
 | |
|   Reset();
 | |
|   mUnit = eStyleUnit_Percent;
 | |
|   mValue.mFloat = aValue;
 | |
| }
 | |
| 
 | |
| void nsStyleCoord::SetFactorValue(float aValue) {
 | |
|   Reset();
 | |
|   mUnit = eStyleUnit_Factor;
 | |
|   mValue.mFloat = aValue;
 | |
| }
 | |
| 
 | |
| void nsStyleCoord::SetFlexFractionValue(float aValue) {
 | |
|   Reset();
 | |
|   mUnit = eStyleUnit_FlexFraction;
 | |
|   mValue.mFloat = aValue;
 | |
| }
 | |
| 
 | |
| void nsStyleCoord::SetCalcValue(Calc* aValue) {
 | |
|   Reset();
 | |
|   mUnit = eStyleUnit_Calc;
 | |
|   mValue.mPointer = aValue;
 | |
|   aValue->AddRef();
 | |
| }
 | |
| 
 | |
| void nsStyleCoord::SetNormalValue() {
 | |
|   Reset();
 | |
|   mUnit = eStyleUnit_Normal;
 | |
|   mValue.mInt = 0;
 | |
| }
 | |
| 
 | |
| void nsStyleCoord::SetAutoValue() {
 | |
|   Reset();
 | |
|   mUnit = eStyleUnit_Auto;
 | |
|   mValue.mInt = 0;
 | |
| }
 | |
| 
 | |
| void nsStyleCoord::SetNoneValue() {
 | |
|   Reset();
 | |
|   mUnit = eStyleUnit_None;
 | |
|   mValue.mInt = 0;
 | |
| }
 | |
| 
 | |
| // accessors that are not inlined
 | |
| 
 | |
| double nsStyleCoord::GetAngleValueInDegrees() const {
 | |
|   // Note that this extends the value from float to double.
 | |
|   return GetAngleValue();
 | |
| }
 | |
| 
 | |
| double nsStyleCoord::GetAngleValueInRadians() const {
 | |
|   return GetAngleValueInDegrees() * M_PI / 180.0;
 | |
| }
 | |
| 
 | |
| nscoord nsStyleCoord::ComputeComputedCalc(nscoord aPercentageBasis) const {
 | |
|   Calc* calc = GetCalcValue();
 | |
|   return calc->mLength +
 | |
|          NSToCoordFloorClamped(aPercentageBasis * calc->mPercent);
 | |
| }
 | |
| 
 | |
| nscoord nsStyleCoord::ComputeCoordPercentCalc(nscoord aPercentageBasis) const {
 | |
|   switch (GetUnit()) {
 | |
|     case eStyleUnit_Coord:
 | |
|       return GetCoordValue();
 | |
|     case eStyleUnit_Percent:
 | |
|       return NSToCoordFloorClamped(aPercentageBasis * GetPercentValue());
 | |
|     case eStyleUnit_Calc:
 | |
|       return ComputeComputedCalc(aPercentageBasis);
 | |
|     default:
 | |
|       MOZ_ASSERT_UNREACHABLE("Unexpected unit!");
 | |
|       return 0;
 | |
|   }
 | |
| }
 | |
| 
 | |
| nsStyleSides::nsStyleSides() {
 | |
|   NS_FOR_CSS_SIDES(i) { mUnits[i] = eStyleUnit_Null; }
 | |
|   mozilla::PodArrayZero(mValues);
 | |
| }
 | |
| 
 | |
| nsStyleSides::nsStyleSides(const nsStyleSides& aOther) {
 | |
|   NS_FOR_CSS_SIDES(i) { mUnits[i] = eStyleUnit_Null; }
 | |
|   *this = aOther;
 | |
| }
 | |
| 
 | |
| nsStyleSides::~nsStyleSides() { Reset(); }
 | |
| 
 | |
| nsStyleSides& nsStyleSides::operator=(const nsStyleSides& aCopy) {
 | |
|   if (this != &aCopy) {
 | |
|     NS_FOR_CSS_SIDES(i) {
 | |
|       nsStyleCoord::SetValue(mUnits[i], mValues[i], aCopy.mUnits[i],
 | |
|                              aCopy.mValues[i]);
 | |
|     }
 | |
|   }
 | |
|   return *this;
 | |
| }
 | |
| 
 | |
| bool nsStyleSides::operator==(const nsStyleSides& aOther) const {
 | |
|   NS_FOR_CSS_SIDES(i) {
 | |
|     if (nsStyleCoord(mValues[i], (nsStyleUnit)mUnits[i]) !=
 | |
|         nsStyleCoord(aOther.mValues[i], (nsStyleUnit)aOther.mUnits[i])) {
 | |
|       return false;
 | |
|     }
 | |
|   }
 | |
|   return true;
 | |
| }
 | |
| 
 | |
| void nsStyleSides::Reset() {
 | |
|   NS_FOR_CSS_SIDES(i) { nsStyleCoord::Reset(mUnits[i], mValues[i]); }
 | |
| }
 | |
| 
 | |
| nsStyleCorners::nsStyleCorners() {
 | |
|   NS_FOR_CSS_HALF_CORNERS(i) { mUnits[i] = eStyleUnit_Null; }
 | |
|   mozilla::PodArrayZero(mValues);
 | |
| }
 | |
| 
 | |
| nsStyleCorners::nsStyleCorners(const nsStyleCorners& aOther) {
 | |
|   NS_FOR_CSS_HALF_CORNERS(i) { mUnits[i] = eStyleUnit_Null; }
 | |
|   *this = aOther;
 | |
| }
 | |
| 
 | |
| nsStyleCorners::~nsStyleCorners() { Reset(); }
 | |
| 
 | |
| nsStyleCorners& nsStyleCorners::operator=(const nsStyleCorners& aCopy) {
 | |
|   if (this != &aCopy) {
 | |
|     NS_FOR_CSS_HALF_CORNERS(i) {
 | |
|       nsStyleCoord::SetValue(mUnits[i], mValues[i], aCopy.mUnits[i],
 | |
|                              aCopy.mValues[i]);
 | |
|     }
 | |
|   }
 | |
|   return *this;
 | |
| }
 | |
| 
 | |
| bool nsStyleCorners::operator==(const nsStyleCorners& aOther) const {
 | |
|   NS_FOR_CSS_HALF_CORNERS(i) {
 | |
|     if (nsStyleCoord(mValues[i], (nsStyleUnit)mUnits[i]) !=
 | |
|         nsStyleCoord(aOther.mValues[i], (nsStyleUnit)aOther.mUnits[i])) {
 | |
|       return false;
 | |
|     }
 | |
|   }
 | |
|   return true;
 | |
| }
 | |
| 
 | |
| void nsStyleCorners::Reset() {
 | |
|   NS_FOR_CSS_HALF_CORNERS(i) { nsStyleCoord::Reset(mUnits[i], mValues[i]); }
 | |
| }
 | |
| 
 | |
| // Validation of SideIsVertical.
 | |
| #define CASE(side, result) \
 | |
|   static_assert(SideIsVertical(side) == result, "SideIsVertical is wrong")
 | |
| CASE(eSideTop, false);
 | |
| CASE(eSideRight, true);
 | |
| CASE(eSideBottom, false);
 | |
| CASE(eSideLeft, true);
 | |
| #undef CASE
 | |
| 
 | |
| // Validation of HalfCornerIsX.
 | |
| #define CASE(corner, result) \
 | |
|   static_assert(HalfCornerIsX(corner) == result, "HalfCornerIsX is wrong")
 | |
| CASE(eCornerTopLeftX, true);
 | |
| CASE(eCornerTopLeftY, false);
 | |
| CASE(eCornerTopRightX, true);
 | |
| CASE(eCornerTopRightY, false);
 | |
| CASE(eCornerBottomRightX, true);
 | |
| CASE(eCornerBottomRightY, false);
 | |
| CASE(eCornerBottomLeftX, true);
 | |
| CASE(eCornerBottomLeftY, false);
 | |
| #undef CASE
 | |
| 
 | |
| // Validation of HalfToFullCorner.
 | |
| #define CASE(corner, result)                        \
 | |
|   static_assert(HalfToFullCorner(corner) == result, \
 | |
|                 "HalfToFullCorner is "              \
 | |
|                 "wrong")
 | |
| CASE(eCornerTopLeftX, eCornerTopLeft);
 | |
| CASE(eCornerTopLeftY, eCornerTopLeft);
 | |
| CASE(eCornerTopRightX, eCornerTopRight);
 | |
| CASE(eCornerTopRightY, eCornerTopRight);
 | |
| CASE(eCornerBottomRightX, eCornerBottomRight);
 | |
| CASE(eCornerBottomRightY, eCornerBottomRight);
 | |
| CASE(eCornerBottomLeftX, eCornerBottomLeft);
 | |
| CASE(eCornerBottomLeftY, eCornerBottomLeft);
 | |
| #undef CASE
 | |
| 
 | |
| // Validation of FullToHalfCorner.
 | |
| #define CASE(corner, vert, result)                        \
 | |
|   static_assert(FullToHalfCorner(corner, vert) == result, \
 | |
|                 "FullToHalfCorner is wrong")
 | |
| CASE(eCornerTopLeft, false, eCornerTopLeftX);
 | |
| CASE(eCornerTopLeft, true, eCornerTopLeftY);
 | |
| CASE(eCornerTopRight, false, eCornerTopRightX);
 | |
| CASE(eCornerTopRight, true, eCornerTopRightY);
 | |
| CASE(eCornerBottomRight, false, eCornerBottomRightX);
 | |
| CASE(eCornerBottomRight, true, eCornerBottomRightY);
 | |
| CASE(eCornerBottomLeft, false, eCornerBottomLeftX);
 | |
| CASE(eCornerBottomLeft, true, eCornerBottomLeftY);
 | |
| #undef CASE
 | |
| 
 | |
| // Validation of SideToFullCorner.
 | |
| #define CASE(side, second, result)                        \
 | |
|   static_assert(SideToFullCorner(side, second) == result, \
 | |
|                 "SideToFullCorner is wrong")
 | |
| CASE(eSideTop, false, eCornerTopLeft);
 | |
| CASE(eSideTop, true, eCornerTopRight);
 | |
| 
 | |
| CASE(eSideRight, false, eCornerTopRight);
 | |
| CASE(eSideRight, true, eCornerBottomRight);
 | |
| 
 | |
| CASE(eSideBottom, false, eCornerBottomRight);
 | |
| CASE(eSideBottom, true, eCornerBottomLeft);
 | |
| 
 | |
| CASE(eSideLeft, false, eCornerBottomLeft);
 | |
| CASE(eSideLeft, true, eCornerTopLeft);
 | |
| #undef CASE
 | |
| 
 | |
| // Validation of SideToHalfCorner.
 | |
| #define CASE(side, second, parallel, result)                        \
 | |
|   static_assert(SideToHalfCorner(side, second, parallel) == result, \
 | |
|                 "SideToHalfCorner is wrong")
 | |
| CASE(eSideTop, false, true, eCornerTopLeftX);
 | |
| CASE(eSideTop, false, false, eCornerTopLeftY);
 | |
| CASE(eSideTop, true, true, eCornerTopRightX);
 | |
| CASE(eSideTop, true, false, eCornerTopRightY);
 | |
| 
 | |
| CASE(eSideRight, false, false, eCornerTopRightX);
 | |
| CASE(eSideRight, false, true, eCornerTopRightY);
 | |
| CASE(eSideRight, true, false, eCornerBottomRightX);
 | |
| CASE(eSideRight, true, true, eCornerBottomRightY);
 | |
| 
 | |
| CASE(eSideBottom, false, true, eCornerBottomRightX);
 | |
| CASE(eSideBottom, false, false, eCornerBottomRightY);
 | |
| CASE(eSideBottom, true, true, eCornerBottomLeftX);
 | |
| CASE(eSideBottom, true, false, eCornerBottomLeftY);
 | |
| 
 | |
| CASE(eSideLeft, false, false, eCornerBottomLeftX);
 | |
| CASE(eSideLeft, false, true, eCornerBottomLeftY);
 | |
| CASE(eSideLeft, true, false, eCornerTopLeftX);
 | |
| CASE(eSideLeft, true, true, eCornerTopLeftY);
 | |
| #undef CASE
 |