nsStyleCoord.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422
  1. /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. /* representation of length values in computed style data */
  6. #include "nsStyleCoord.h"
  7. #include "mozilla/HashFunctions.h"
  8. #include "mozilla/PodOperations.h"
  9. nsStyleCoord::nsStyleCoord(nsStyleUnit aUnit)
  10. : mUnit(aUnit)
  11. {
  12. NS_ASSERTION(aUnit < eStyleUnit_Percent, "not a valueless unit");
  13. if (aUnit >= eStyleUnit_Percent) {
  14. mUnit = eStyleUnit_Null;
  15. }
  16. mValue.mInt = 0;
  17. }
  18. nsStyleCoord::nsStyleCoord(int32_t aValue, nsStyleUnit aUnit)
  19. : mUnit(aUnit)
  20. {
  21. //if you want to pass in eStyleUnit_Coord, don't. instead, use the
  22. //constructor just above this one... MMP
  23. NS_ASSERTION((aUnit == eStyleUnit_Enumerated) ||
  24. (aUnit == eStyleUnit_Integer), "not an int value");
  25. if ((aUnit == eStyleUnit_Enumerated) ||
  26. (aUnit == eStyleUnit_Integer)) {
  27. mValue.mInt = aValue;
  28. }
  29. else {
  30. mUnit = eStyleUnit_Null;
  31. mValue.mInt = 0;
  32. }
  33. }
  34. nsStyleCoord::nsStyleCoord(float aValue, nsStyleUnit aUnit)
  35. : mUnit(aUnit)
  36. {
  37. if (aUnit < eStyleUnit_Percent || aUnit >= eStyleUnit_Coord) {
  38. NS_NOTREACHED("not a float value");
  39. mUnit = eStyleUnit_Null;
  40. mValue.mInt = 0;
  41. } else {
  42. mValue.mFloat = aValue;
  43. }
  44. }
  45. bool nsStyleCoord::operator==(const nsStyleCoord& aOther) const
  46. {
  47. if (mUnit != aOther.mUnit) {
  48. return false;
  49. }
  50. switch (mUnit) {
  51. case eStyleUnit_Null:
  52. case eStyleUnit_Normal:
  53. case eStyleUnit_Auto:
  54. case eStyleUnit_None:
  55. return true;
  56. case eStyleUnit_Percent:
  57. case eStyleUnit_Factor:
  58. case eStyleUnit_Degree:
  59. case eStyleUnit_Grad:
  60. case eStyleUnit_Radian:
  61. case eStyleUnit_Turn:
  62. case eStyleUnit_FlexFraction:
  63. return mValue.mFloat == aOther.mValue.mFloat;
  64. case eStyleUnit_Coord:
  65. case eStyleUnit_Integer:
  66. case eStyleUnit_Enumerated:
  67. return mValue.mInt == aOther.mValue.mInt;
  68. case eStyleUnit_Calc:
  69. return *this->GetCalcValue() == *aOther.GetCalcValue();
  70. }
  71. MOZ_ASSERT(false, "unexpected unit");
  72. return false;
  73. }
  74. uint32_t nsStyleCoord::HashValue(uint32_t aHash = 0) const
  75. {
  76. aHash = mozilla::AddToHash(aHash, mUnit);
  77. switch (mUnit) {
  78. case eStyleUnit_Null:
  79. case eStyleUnit_Normal:
  80. case eStyleUnit_Auto:
  81. case eStyleUnit_None:
  82. return mozilla::AddToHash(aHash, true);
  83. case eStyleUnit_Percent:
  84. case eStyleUnit_Factor:
  85. case eStyleUnit_Degree:
  86. case eStyleUnit_Grad:
  87. case eStyleUnit_Radian:
  88. case eStyleUnit_Turn:
  89. case eStyleUnit_FlexFraction:
  90. return mozilla::AddToHash(aHash, mValue.mFloat);
  91. case eStyleUnit_Coord:
  92. case eStyleUnit_Integer:
  93. case eStyleUnit_Enumerated:
  94. return mozilla::AddToHash(aHash, mValue.mInt);
  95. case eStyleUnit_Calc:
  96. Calc* calcValue = GetCalcValue();
  97. aHash = mozilla::AddToHash(aHash, calcValue->mLength);
  98. if (HasPercent()) {
  99. return mozilla::AddToHash(aHash, calcValue->mPercent);
  100. }
  101. return aHash;
  102. }
  103. MOZ_ASSERT(false, "unexpected unit");
  104. return aHash;
  105. }
  106. void nsStyleCoord::Reset()
  107. {
  108. Reset(mUnit, mValue);
  109. }
  110. void nsStyleCoord::SetCoordValue(nscoord aValue)
  111. {
  112. Reset();
  113. mUnit = eStyleUnit_Coord;
  114. mValue.mInt = aValue;
  115. }
  116. void nsStyleCoord::SetIntValue(int32_t aValue, nsStyleUnit aUnit)
  117. {
  118. NS_ASSERTION((aUnit == eStyleUnit_Enumerated) ||
  119. (aUnit == eStyleUnit_Integer), "not an int value");
  120. Reset();
  121. if ((aUnit == eStyleUnit_Enumerated) ||
  122. (aUnit == eStyleUnit_Integer)) {
  123. mUnit = aUnit;
  124. mValue.mInt = aValue;
  125. }
  126. }
  127. void nsStyleCoord::SetPercentValue(float aValue)
  128. {
  129. Reset();
  130. mUnit = eStyleUnit_Percent;
  131. mValue.mFloat = aValue;
  132. }
  133. void nsStyleCoord::SetFactorValue(float aValue)
  134. {
  135. Reset();
  136. mUnit = eStyleUnit_Factor;
  137. mValue.mFloat = aValue;
  138. }
  139. void nsStyleCoord::SetAngleValue(float aValue, nsStyleUnit aUnit)
  140. {
  141. Reset();
  142. if (aUnit == eStyleUnit_Degree ||
  143. aUnit == eStyleUnit_Grad ||
  144. aUnit == eStyleUnit_Radian ||
  145. aUnit == eStyleUnit_Turn) {
  146. mUnit = aUnit;
  147. mValue.mFloat = aValue;
  148. } else {
  149. NS_NOTREACHED("not an angle value");
  150. }
  151. }
  152. void nsStyleCoord::SetFlexFractionValue(float aValue)
  153. {
  154. Reset();
  155. mUnit = eStyleUnit_FlexFraction;
  156. mValue.mFloat = aValue;
  157. }
  158. void nsStyleCoord::SetCalcValue(Calc* aValue)
  159. {
  160. Reset();
  161. mUnit = eStyleUnit_Calc;
  162. mValue.mPointer = aValue;
  163. aValue->AddRef();
  164. }
  165. void nsStyleCoord::SetNormalValue()
  166. {
  167. Reset();
  168. mUnit = eStyleUnit_Normal;
  169. mValue.mInt = 0;
  170. }
  171. void nsStyleCoord::SetAutoValue()
  172. {
  173. Reset();
  174. mUnit = eStyleUnit_Auto;
  175. mValue.mInt = 0;
  176. }
  177. void nsStyleCoord::SetNoneValue()
  178. {
  179. Reset();
  180. mUnit = eStyleUnit_None;
  181. mValue.mInt = 0;
  182. }
  183. // accessors that are not inlined
  184. double
  185. nsStyleCoord::GetAngleValueInDegrees() const
  186. {
  187. return GetAngleValueInRadians() * (180.0 / M_PI);
  188. }
  189. double
  190. nsStyleCoord::GetAngleValueInRadians() const
  191. {
  192. double angle = mValue.mFloat;
  193. switch (GetUnit()) {
  194. case eStyleUnit_Radian: return angle;
  195. case eStyleUnit_Turn: return angle * 2 * M_PI;
  196. case eStyleUnit_Degree: return angle * M_PI / 180.0;
  197. case eStyleUnit_Grad: return angle * M_PI / 200.0;
  198. default:
  199. NS_NOTREACHED("unrecognized angular unit");
  200. return 0.0;
  201. }
  202. }
  203. nsStyleSides::nsStyleSides()
  204. {
  205. NS_FOR_CSS_SIDES(i) {
  206. mUnits[i] = eStyleUnit_Null;
  207. }
  208. mozilla::PodArrayZero(mValues);
  209. }
  210. nsStyleSides::nsStyleSides(const nsStyleSides& aOther)
  211. {
  212. NS_FOR_CSS_SIDES(i) {
  213. mUnits[i] = eStyleUnit_Null;
  214. }
  215. *this = aOther;
  216. }
  217. nsStyleSides::~nsStyleSides()
  218. {
  219. Reset();
  220. }
  221. nsStyleSides&
  222. nsStyleSides::operator=(const nsStyleSides& aCopy)
  223. {
  224. if (this != &aCopy) {
  225. NS_FOR_CSS_SIDES(i) {
  226. nsStyleCoord::SetValue(mUnits[i], mValues[i],
  227. aCopy.mUnits[i], aCopy.mValues[i]);
  228. }
  229. }
  230. return *this;
  231. }
  232. bool nsStyleSides::operator==(const nsStyleSides& aOther) const
  233. {
  234. NS_FOR_CSS_SIDES(i) {
  235. if (nsStyleCoord(mValues[i], (nsStyleUnit)mUnits[i]) !=
  236. nsStyleCoord(aOther.mValues[i], (nsStyleUnit)aOther.mUnits[i])) {
  237. return false;
  238. }
  239. }
  240. return true;
  241. }
  242. void nsStyleSides::Reset()
  243. {
  244. NS_FOR_CSS_SIDES(i) {
  245. nsStyleCoord::Reset(mUnits[i], mValues[i]);
  246. }
  247. }
  248. nsStyleCorners::nsStyleCorners()
  249. {
  250. NS_FOR_CSS_HALF_CORNERS(i) {
  251. mUnits[i] = eStyleUnit_Null;
  252. }
  253. mozilla::PodArrayZero(mValues);
  254. }
  255. nsStyleCorners::nsStyleCorners(const nsStyleCorners& aOther)
  256. {
  257. NS_FOR_CSS_HALF_CORNERS(i) {
  258. mUnits[i] = eStyleUnit_Null;
  259. }
  260. *this = aOther;
  261. }
  262. nsStyleCorners::~nsStyleCorners()
  263. {
  264. Reset();
  265. }
  266. nsStyleCorners&
  267. nsStyleCorners::operator=(const nsStyleCorners& aCopy)
  268. {
  269. if (this != &aCopy) {
  270. NS_FOR_CSS_HALF_CORNERS(i) {
  271. nsStyleCoord::SetValue(mUnits[i], mValues[i],
  272. aCopy.mUnits[i], aCopy.mValues[i]);
  273. }
  274. }
  275. return *this;
  276. }
  277. bool
  278. nsStyleCorners::operator==(const nsStyleCorners& aOther) const
  279. {
  280. NS_FOR_CSS_HALF_CORNERS(i) {
  281. if (nsStyleCoord(mValues[i], (nsStyleUnit)mUnits[i]) !=
  282. nsStyleCoord(aOther.mValues[i], (nsStyleUnit)aOther.mUnits[i])) {
  283. return false;
  284. }
  285. }
  286. return true;
  287. }
  288. void nsStyleCorners::Reset()
  289. {
  290. NS_FOR_CSS_HALF_CORNERS(i) {
  291. nsStyleCoord::Reset(mUnits[i], mValues[i]);
  292. }
  293. }
  294. // Validation of NS_SIDE_IS_VERTICAL and NS_HALF_CORNER_IS_X.
  295. #define CASE(side, result) \
  296. static_assert(NS_SIDE_IS_VERTICAL(side) == result, \
  297. "NS_SIDE_IS_VERTICAL is wrong")
  298. CASE(NS_SIDE_TOP, false);
  299. CASE(NS_SIDE_RIGHT, true);
  300. CASE(NS_SIDE_BOTTOM, false);
  301. CASE(NS_SIDE_LEFT, true);
  302. #undef CASE
  303. #define CASE(corner, result) \
  304. static_assert(NS_HALF_CORNER_IS_X(corner) == result, \
  305. "NS_HALF_CORNER_IS_X is wrong")
  306. CASE(NS_CORNER_TOP_LEFT_X, true);
  307. CASE(NS_CORNER_TOP_LEFT_Y, false);
  308. CASE(NS_CORNER_TOP_RIGHT_X, true);
  309. CASE(NS_CORNER_TOP_RIGHT_Y, false);
  310. CASE(NS_CORNER_BOTTOM_RIGHT_X, true);
  311. CASE(NS_CORNER_BOTTOM_RIGHT_Y, false);
  312. CASE(NS_CORNER_BOTTOM_LEFT_X, true);
  313. CASE(NS_CORNER_BOTTOM_LEFT_Y, false);
  314. #undef CASE
  315. // Validation of NS_HALF_TO_FULL_CORNER.
  316. #define CASE(corner, result) \
  317. static_assert(NS_HALF_TO_FULL_CORNER(corner) == result, \
  318. "NS_HALF_TO_FULL_CORNER is wrong")
  319. CASE(NS_CORNER_TOP_LEFT_X, NS_CORNER_TOP_LEFT);
  320. CASE(NS_CORNER_TOP_LEFT_Y, NS_CORNER_TOP_LEFT);
  321. CASE(NS_CORNER_TOP_RIGHT_X, NS_CORNER_TOP_RIGHT);
  322. CASE(NS_CORNER_TOP_RIGHT_Y, NS_CORNER_TOP_RIGHT);
  323. CASE(NS_CORNER_BOTTOM_RIGHT_X, NS_CORNER_BOTTOM_RIGHT);
  324. CASE(NS_CORNER_BOTTOM_RIGHT_Y, NS_CORNER_BOTTOM_RIGHT);
  325. CASE(NS_CORNER_BOTTOM_LEFT_X, NS_CORNER_BOTTOM_LEFT);
  326. CASE(NS_CORNER_BOTTOM_LEFT_Y, NS_CORNER_BOTTOM_LEFT);
  327. #undef CASE
  328. // Validation of NS_FULL_TO_HALF_CORNER.
  329. #define CASE(corner, vert, result) \
  330. static_assert(NS_FULL_TO_HALF_CORNER(corner, vert) == result, \
  331. "NS_FULL_TO_HALF_CORNER is wrong")
  332. CASE(NS_CORNER_TOP_LEFT, false, NS_CORNER_TOP_LEFT_X);
  333. CASE(NS_CORNER_TOP_LEFT, true, NS_CORNER_TOP_LEFT_Y);
  334. CASE(NS_CORNER_TOP_RIGHT, false, NS_CORNER_TOP_RIGHT_X);
  335. CASE(NS_CORNER_TOP_RIGHT, true, NS_CORNER_TOP_RIGHT_Y);
  336. CASE(NS_CORNER_BOTTOM_RIGHT, false, NS_CORNER_BOTTOM_RIGHT_X);
  337. CASE(NS_CORNER_BOTTOM_RIGHT, true, NS_CORNER_BOTTOM_RIGHT_Y);
  338. CASE(NS_CORNER_BOTTOM_LEFT, false, NS_CORNER_BOTTOM_LEFT_X);
  339. CASE(NS_CORNER_BOTTOM_LEFT, true, NS_CORNER_BOTTOM_LEFT_Y);
  340. #undef CASE
  341. // Validation of NS_SIDE_TO_{FULL,HALF}_CORNER.
  342. #define CASE(side, second, result) \
  343. static_assert(NS_SIDE_TO_FULL_CORNER(side, second) == result, \
  344. "NS_SIDE_TO_FULL_CORNER is wrong")
  345. CASE(NS_SIDE_TOP, false, NS_CORNER_TOP_LEFT);
  346. CASE(NS_SIDE_TOP, true, NS_CORNER_TOP_RIGHT);
  347. CASE(NS_SIDE_RIGHT, false, NS_CORNER_TOP_RIGHT);
  348. CASE(NS_SIDE_RIGHT, true, NS_CORNER_BOTTOM_RIGHT);
  349. CASE(NS_SIDE_BOTTOM, false, NS_CORNER_BOTTOM_RIGHT);
  350. CASE(NS_SIDE_BOTTOM, true, NS_CORNER_BOTTOM_LEFT);
  351. CASE(NS_SIDE_LEFT, false, NS_CORNER_BOTTOM_LEFT);
  352. CASE(NS_SIDE_LEFT, true, NS_CORNER_TOP_LEFT);
  353. #undef CASE
  354. #define CASE(side, second, parallel, result) \
  355. static_assert(NS_SIDE_TO_HALF_CORNER(side, second, parallel) == result, \
  356. "NS_SIDE_TO_HALF_CORNER is wrong")
  357. CASE(NS_SIDE_TOP, false, true, NS_CORNER_TOP_LEFT_X);
  358. CASE(NS_SIDE_TOP, false, false, NS_CORNER_TOP_LEFT_Y);
  359. CASE(NS_SIDE_TOP, true, true, NS_CORNER_TOP_RIGHT_X);
  360. CASE(NS_SIDE_TOP, true, false, NS_CORNER_TOP_RIGHT_Y);
  361. CASE(NS_SIDE_RIGHT, false, false, NS_CORNER_TOP_RIGHT_X);
  362. CASE(NS_SIDE_RIGHT, false, true, NS_CORNER_TOP_RIGHT_Y);
  363. CASE(NS_SIDE_RIGHT, true, false, NS_CORNER_BOTTOM_RIGHT_X);
  364. CASE(NS_SIDE_RIGHT, true, true, NS_CORNER_BOTTOM_RIGHT_Y);
  365. CASE(NS_SIDE_BOTTOM, false, true, NS_CORNER_BOTTOM_RIGHT_X);
  366. CASE(NS_SIDE_BOTTOM, false, false, NS_CORNER_BOTTOM_RIGHT_Y);
  367. CASE(NS_SIDE_BOTTOM, true, true, NS_CORNER_BOTTOM_LEFT_X);
  368. CASE(NS_SIDE_BOTTOM, true, false, NS_CORNER_BOTTOM_LEFT_Y);
  369. CASE(NS_SIDE_LEFT, false, false, NS_CORNER_BOTTOM_LEFT_X);
  370. CASE(NS_SIDE_LEFT, false, true, NS_CORNER_BOTTOM_LEFT_Y);
  371. CASE(NS_SIDE_LEFT, true, false, NS_CORNER_TOP_LEFT_X);
  372. CASE(NS_SIDE_LEFT, true, true, NS_CORNER_TOP_LEFT_Y);
  373. #undef CASE