celldata.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
  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. #ifndef CellData_h__
  6. #define CellData_h__
  7. #include "nsISupports.h"
  8. #include "nsITableCellLayout.h" // for MAX_COLSPAN / MAX_ROWSPAN
  9. #include "nsCoord.h"
  10. #include "mozilla/gfx/Types.h"
  11. #include "mozilla/WritingModes.h"
  12. #include <stdint.h>
  13. class nsTableCellFrame;
  14. class nsCellMap;
  15. class BCCellData;
  16. /**
  17. * Data stored by nsCellMap to rationalize rowspan and colspan cells.
  18. */
  19. class CellData
  20. {
  21. public:
  22. /** Initialize the mOrigCell pointer
  23. * @param aOrigCell the table cell frame which will be stored in mOrigCell.
  24. */
  25. void Init(nsTableCellFrame* aCellFrame);
  26. /** does a cell originate from here
  27. * @return is true if a cell corresponds to this cellmap entry
  28. */
  29. bool IsOrig() const;
  30. /** is the celldata valid
  31. * @return is true if no cell originates and the cell is not spanned by
  32. * a row- or colspan. mBits are 0 in this case and mOrigCell is
  33. * nullptr
  34. */
  35. bool IsDead() const;
  36. /** is the entry spanned by row- or a colspan
  37. * @return is true if the entry is spanned by a row- or colspan
  38. */
  39. bool IsSpan() const;
  40. /** is the entry spanned by rowspan
  41. * @return is true if the entry is spanned by a rowspan
  42. */
  43. bool IsRowSpan() const;
  44. /** is the entry spanned by a zero rowspan
  45. * zero rowspans span all cells starting from the originating cell down to
  46. * the end of the rowgroup or a cell originating in the same column
  47. * @return is true if the entry is spanned by a zero rowspan
  48. */
  49. bool IsZeroRowSpan() const;
  50. /** mark the current entry as spanned by a zero rowspan
  51. * @param aIsZero if true mark the entry as covered by a zero rowspan
  52. */
  53. void SetZeroRowSpan(bool aIsZero);
  54. /** get the distance from the current entry to the corresponding origin of the rowspan
  55. * @return containing the distance in the column to the originating cell
  56. */
  57. uint32_t GetRowSpanOffset() const;
  58. /** set the distance from the current entry to the corresponding origin of the rowspan
  59. * @param the distance in the column to the originating cell
  60. */
  61. void SetRowSpanOffset(uint32_t aSpan);
  62. /** is the entry spanned by colspan
  63. * @return is true if the entry is spanned by a colspan
  64. */
  65. bool IsColSpan() const;
  66. /** get the distance from the current entry to the corresponding origin of the colspan
  67. * @return containing the distance in the row to the originating cell
  68. */
  69. uint32_t GetColSpanOffset() const;
  70. /** set the distance from the current entry to the corresponding origin of the colspan
  71. * @param the distance in the column to the originating cell
  72. */
  73. void SetColSpanOffset(uint32_t aSpan);
  74. /** is the entry spanned by a row- and a colspan
  75. * @return is true if the entry is spanned by a row- and a colspan
  76. */
  77. bool IsOverlap() const;
  78. /** mark the current entry as spanned by a row- and a colspan
  79. * @param aOverlap if true mark the entry as covered by a row- and a colspan
  80. */
  81. void SetOverlap(bool aOverlap);
  82. /** get the table cell frame for this entry
  83. * @return a pointer to the cellframe, this will be nullptr when the entry
  84. * is only a spanned entry
  85. */
  86. nsTableCellFrame* GetCellFrame() const;
  87. private:
  88. friend class nsCellMap;
  89. friend class BCCellData;
  90. /** constructor.
  91. * @param aOrigCell the table cell frame which will be stored in mOrigCell.
  92. */
  93. explicit CellData(nsTableCellFrame* aOrigCell); // implemented in nsCellMap.cpp
  94. /** destructor */
  95. ~CellData(); // implemented in nsCellMap.cpp
  96. protected:
  97. // this union relies on the assumption that an object (not primitive type) does
  98. // not start on an odd bit boundary. If mSpan is 0 then mOrigCell is in effect
  99. // and the data does not represent a span. If mSpan is 1, then mBits is in
  100. // effect and the data represents a span.
  101. // mBits must match the size of mOrigCell on both 32- and 64-bit platforms.
  102. union {
  103. nsTableCellFrame* mOrigCell;
  104. uintptr_t mBits;
  105. };
  106. };
  107. // Border Collapsing Cell Data
  108. enum BCBorderOwner
  109. {
  110. eTableOwner = 0,
  111. eColGroupOwner = 1,
  112. eAjaColGroupOwner = 2, // col group to the left
  113. eColOwner = 3,
  114. eAjaColOwner = 4, // col to the left
  115. eRowGroupOwner = 5,
  116. eAjaRowGroupOwner = 6, // row group above
  117. eRowOwner = 7,
  118. eAjaRowOwner = 8, // row above
  119. eCellOwner = 9,
  120. eAjaCellOwner = 10 // cell to the top or to the left
  121. };
  122. typedef uint16_t BCPixelSize;
  123. // These are the max sizes that are stored. If they are exceeded, then the max is stored and
  124. // the actual value is computed when needed.
  125. #define MAX_BORDER_WIDTH nscoord((1u << (sizeof(BCPixelSize) * 8)) - 1)
  126. // The half of border on inline/block-axis start side
  127. static inline BCPixelSize
  128. BC_BORDER_START_HALF(BCPixelSize px) { return px - px / 2; }
  129. // The half of border on inline/block-axis end side
  130. static inline BCPixelSize
  131. BC_BORDER_END_HALF(BCPixelSize px) { return px / 2; }
  132. static inline nscoord
  133. BC_BORDER_START_HALF_COORD(int32_t p2t, BCPixelSize px)
  134. { return BC_BORDER_START_HALF(px) * p2t; }
  135. static inline nscoord
  136. BC_BORDER_END_HALF_COORD(int32_t p2t, BCPixelSize px)
  137. { return BC_BORDER_END_HALF(px) * p2t; }
  138. // BCData stores the bstart and istart border info and the corner connecting the two.
  139. class BCData
  140. {
  141. public:
  142. BCData();
  143. ~BCData();
  144. nscoord GetIStartEdge(BCBorderOwner& aOwner,
  145. bool& aStart) const;
  146. void SetIStartEdge(BCBorderOwner aOwner,
  147. nscoord aSize,
  148. bool aStart);
  149. nscoord GetBStartEdge(BCBorderOwner& aOwner,
  150. bool& aStart) const;
  151. void SetBStartEdge(BCBorderOwner aOwner,
  152. nscoord aSize,
  153. bool aStart);
  154. BCPixelSize GetCorner(mozilla::LogicalSide& aCornerOwner,
  155. bool& aBevel) const;
  156. void SetCorner(BCPixelSize aSubSize,
  157. mozilla::LogicalSide aOwner,
  158. bool aBevel);
  159. bool IsIStartStart() const;
  160. void SetIStartStart(bool aValue);
  161. bool IsBStartStart() const;
  162. void SetBStartStart(bool aValue);
  163. protected:
  164. BCPixelSize mIStartSize; // size in pixels of iStart border
  165. BCPixelSize mBStartSize; // size in pixels of bStart border
  166. BCPixelSize mCornerSubSize; // size of the largest border not in the
  167. // dominant plane (for example, if corner is
  168. // owned by the segment to its bStart or bEnd,
  169. // then the size is the max of the border
  170. // sizes of the segments to its iStart or iEnd.
  171. unsigned mIStartOwner: 4; // owner of iStart border
  172. unsigned mBStartOwner: 4; // owner of bStart border
  173. unsigned mIStartStart: 1; // set if this is the start of a block-dir border segment
  174. unsigned mBStartStart: 1; // set if this is the start of an inline-dir border segment
  175. unsigned mCornerSide: 2; // LogicalSide of the owner of the bStart-iStart corner relative to the corner
  176. unsigned mCornerBevel: 1; // is the corner beveled (only two segments, perpendicular, not dashed or dotted).
  177. };
  178. // BCCellData entries replace CellData entries in the cell map if the border collapsing model is in
  179. // effect. BCData for a row and col entry contains the left and top borders of cell at that row and
  180. // col and the corner connecting the two. The right borders of the cells in the last col and the bottom
  181. // borders of the last row are stored in separate BCData entries in the cell map.
  182. class BCCellData : public CellData
  183. {
  184. public:
  185. explicit BCCellData(nsTableCellFrame* aOrigCell);
  186. ~BCCellData();
  187. BCData mData;
  188. };
  189. // The layout of a celldata is as follows. The top 10 bits are the colspan
  190. // offset (which is enough to represent our allowed values 1-1000 for colspan).
  191. // Then there are two bits of flags.
  192. // XXXmats Then one unused bit that we should decide how to use in bug 862624.
  193. // Then 16 bits of rowspan offset (which
  194. // lets us represent numbers up to 65535. Then another 3 bits of flags.
  195. // num bits to shift right to get right aligned col span
  196. #define COL_SPAN_SHIFT 22
  197. // num bits to shift right to get right aligned row span
  198. #define ROW_SPAN_SHIFT 3
  199. // the col offset to the data containing the original cell.
  200. #define COL_SPAN_OFFSET (0x3FF << COL_SPAN_SHIFT)
  201. // the row offset to the data containing the original cell
  202. #define ROW_SPAN_OFFSET (0xFFFF << ROW_SPAN_SHIFT)
  203. // And the flags
  204. #define SPAN 0x00000001 // there a row or col span
  205. #define ROW_SPAN 0x00000002 // there is a row span
  206. #define ROW_SPAN_0 0x00000004 // the row span is 0
  207. #define COL_SPAN (1 << (COL_SPAN_SHIFT - 2)) // there is a col span
  208. #define OVERLAP (1 << (COL_SPAN_SHIFT - 1)) // there is a row span and
  209. // col span but not by
  210. // same cell
  211. inline nsTableCellFrame* CellData::GetCellFrame() const
  212. {
  213. if (SPAN != (SPAN & mBits)) {
  214. return mOrigCell;
  215. }
  216. return nullptr;
  217. }
  218. inline void CellData::Init(nsTableCellFrame* aCellFrame)
  219. {
  220. mOrigCell = aCellFrame;
  221. }
  222. inline bool CellData::IsOrig() const
  223. {
  224. return ((nullptr != mOrigCell) && (SPAN != (SPAN & mBits)));
  225. }
  226. inline bool CellData::IsDead() const
  227. {
  228. return (0 == mBits);
  229. }
  230. inline bool CellData::IsSpan() const
  231. {
  232. return (SPAN == (SPAN & mBits));
  233. }
  234. inline bool CellData::IsRowSpan() const
  235. {
  236. return (SPAN == (SPAN & mBits)) &&
  237. (ROW_SPAN == (ROW_SPAN & mBits));
  238. }
  239. inline bool CellData::IsZeroRowSpan() const
  240. {
  241. return (SPAN == (SPAN & mBits)) &&
  242. (ROW_SPAN == (ROW_SPAN & mBits)) &&
  243. (ROW_SPAN_0 == (ROW_SPAN_0 & mBits));
  244. }
  245. inline void CellData::SetZeroRowSpan(bool aIsZeroSpan)
  246. {
  247. if (SPAN == (SPAN & mBits)) {
  248. if (aIsZeroSpan) {
  249. mBits |= ROW_SPAN_0;
  250. }
  251. else {
  252. mBits &= ~ROW_SPAN_0;
  253. }
  254. }
  255. }
  256. inline uint32_t CellData::GetRowSpanOffset() const
  257. {
  258. if ((SPAN == (SPAN & mBits)) && ((ROW_SPAN == (ROW_SPAN & mBits)))) {
  259. return (uint32_t)((mBits & ROW_SPAN_OFFSET) >> ROW_SPAN_SHIFT);
  260. }
  261. return 0;
  262. }
  263. inline void CellData::SetRowSpanOffset(uint32_t aSpan)
  264. {
  265. mBits &= ~ROW_SPAN_OFFSET;
  266. mBits |= (aSpan << ROW_SPAN_SHIFT);
  267. mBits |= SPAN;
  268. mBits |= ROW_SPAN;
  269. }
  270. inline bool CellData::IsColSpan() const
  271. {
  272. return (SPAN == (SPAN & mBits)) &&
  273. (COL_SPAN == (COL_SPAN & mBits));
  274. }
  275. inline uint32_t CellData::GetColSpanOffset() const
  276. {
  277. if ((SPAN == (SPAN & mBits)) && ((COL_SPAN == (COL_SPAN & mBits)))) {
  278. return (uint32_t)((mBits & COL_SPAN_OFFSET) >> COL_SPAN_SHIFT);
  279. }
  280. return 0;
  281. }
  282. inline void CellData::SetColSpanOffset(uint32_t aSpan)
  283. {
  284. mBits &= ~COL_SPAN_OFFSET;
  285. mBits |= (aSpan << COL_SPAN_SHIFT);
  286. mBits |= SPAN;
  287. mBits |= COL_SPAN;
  288. }
  289. inline bool CellData::IsOverlap() const
  290. {
  291. return (SPAN == (SPAN & mBits)) && (OVERLAP == (OVERLAP & mBits));
  292. }
  293. inline void CellData::SetOverlap(bool aOverlap)
  294. {
  295. if (SPAN == (SPAN & mBits)) {
  296. if (aOverlap) {
  297. mBits |= OVERLAP;
  298. }
  299. else {
  300. mBits &= ~OVERLAP;
  301. }
  302. }
  303. }
  304. inline BCData::BCData()
  305. {
  306. mIStartOwner = mBStartOwner = eCellOwner;
  307. mIStartStart = mBStartStart = 1;
  308. mIStartSize = mCornerSubSize = mBStartSize = 0;
  309. mCornerSide = mozilla::eLogicalSideBStart;
  310. mCornerBevel = false;
  311. }
  312. inline BCData::~BCData()
  313. {
  314. }
  315. inline nscoord BCData::GetIStartEdge(BCBorderOwner& aOwner,
  316. bool& aStart) const
  317. {
  318. aOwner = (BCBorderOwner)mIStartOwner;
  319. aStart = (bool)mIStartStart;
  320. return (nscoord)mIStartSize;
  321. }
  322. inline void BCData::SetIStartEdge(BCBorderOwner aOwner,
  323. nscoord aSize,
  324. bool aStart)
  325. {
  326. mIStartOwner = aOwner;
  327. mIStartSize = (aSize > MAX_BORDER_WIDTH) ? MAX_BORDER_WIDTH : aSize;
  328. mIStartStart = aStart;
  329. }
  330. inline nscoord BCData::GetBStartEdge(BCBorderOwner& aOwner,
  331. bool& aStart) const
  332. {
  333. aOwner = (BCBorderOwner)mBStartOwner;
  334. aStart = (bool)mBStartStart;
  335. return (nscoord)mBStartSize;
  336. }
  337. inline void BCData::SetBStartEdge(BCBorderOwner aOwner,
  338. nscoord aSize,
  339. bool aStart)
  340. {
  341. mBStartOwner = aOwner;
  342. mBStartSize = (aSize > MAX_BORDER_WIDTH) ? MAX_BORDER_WIDTH : aSize;
  343. mBStartStart = aStart;
  344. }
  345. inline BCPixelSize BCData::GetCorner(mozilla::LogicalSide& aOwnerSide,
  346. bool& aBevel) const
  347. {
  348. aOwnerSide = mozilla::LogicalSide(mCornerSide);
  349. aBevel = (bool)mCornerBevel;
  350. return mCornerSubSize;
  351. }
  352. inline void BCData::SetCorner(BCPixelSize aSubSize,
  353. mozilla::LogicalSide aOwnerSide,
  354. bool aBevel)
  355. {
  356. mCornerSubSize = aSubSize;
  357. mCornerSide = aOwnerSide;
  358. mCornerBevel = aBevel;
  359. }
  360. inline bool BCData::IsIStartStart() const
  361. {
  362. return (bool)mIStartStart;
  363. }
  364. inline void BCData::SetIStartStart(bool aValue)
  365. {
  366. mIStartStart = aValue;
  367. }
  368. inline bool BCData::IsBStartStart() const
  369. {
  370. return (bool)mBStartStart;
  371. }
  372. inline void BCData::SetBStartStart(bool aValue)
  373. {
  374. mBStartStart = aValue;
  375. }
  376. #endif