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