Bug 1869043 allow a device to be specified with MediaTrackGraph::NotifyWhenDeviceStar...
[gecko.git] / layout / tables / celldata.h
blob681f0e9f280cf6ae020a798542ff93748b0d3b65
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__
8 #include "nsISupports.h"
9 #include "nsITableCellLayout.h" // for MAX_COLSPAN / MAX_ROWSPAN
10 #include "nsCoord.h"
11 #include "mozilla/gfx/Types.h"
12 #include "mozilla/WritingModes.h"
13 #include <stdint.h>
15 class nsTableCellFrame;
16 class nsCellMap;
17 class BCCellData;
19 /**
20 * Data stored by nsCellMap to rationalize rowspan and colspan cells.
22 class CellData {
23 public:
24 /** Initialize the mOrigCell pointer
25 * @param aOrigCell the table cell frame which will be stored in mOrigCell.
27 void Init(nsTableCellFrame* aCellFrame);
29 /** does a cell originate from here
30 * @return is true if a cell corresponds to this cellmap entry
32 bool IsOrig() const;
34 /** is the celldata valid
35 * @return is true if no cell originates and the cell is not spanned by
36 * a row- or colspan. mBits are 0 in this case and mOrigCell is
37 * nullptr
39 bool IsDead() const;
41 /** is the entry spanned by row- or a colspan
42 * @return is true if the entry is spanned by a row- or colspan
44 bool IsSpan() const;
46 /** is the entry spanned by rowspan
47 * @return is true if the entry is spanned by a rowspan
49 bool IsRowSpan() const;
51 /** is the entry spanned by a zero rowspan
52 * zero rowspans span all cells starting from the originating cell down to
53 * the end of the rowgroup or a cell originating in the same column
54 * @return is true if the entry is spanned by a zero rowspan
56 bool IsZeroRowSpan() const;
58 /** mark the current entry as spanned by a zero rowspan
59 * @param aIsZero if true mark the entry as covered by a zero rowspan
61 void SetZeroRowSpan(bool aIsZero);
63 /** get the distance from the current entry to the corresponding origin of the
64 * rowspan
65 * @return containing the distance in the column to the originating cell
67 uint32_t GetRowSpanOffset() const;
69 /** set the distance from the current entry to the corresponding origin of
70 * the rowspan
71 * @param the distance in the column to the originating cell
73 void SetRowSpanOffset(uint32_t aSpan);
75 /** is the entry spanned by colspan
76 * @return is true if the entry is spanned by a colspan
78 bool IsColSpan() const;
80 /** get the distance from the current entry to the corresponding origin of
81 * the colspan
82 * @return containing the distance in the row to the originating cell
84 uint32_t GetColSpanOffset() const;
86 /** set the distance from the current entry to the corresponding origin of the
87 * colspan
88 * @param the distance in the column to the originating cell
90 void SetColSpanOffset(uint32_t aSpan);
92 /** is the entry spanned by a row- and a colspan
93 * @return is true if the entry is spanned by a row- and a colspan
95 bool IsOverlap() const;
97 /** mark the current entry as spanned by a row- and a colspan
98 * @param aOverlap if true mark the entry as covered by a row- and
99 * a colspan
101 void SetOverlap(bool aOverlap);
103 /** get the table cell frame for this entry
104 * @return a pointer to the cellframe, this will be nullptr when the entry
105 * is only a spanned entry
107 nsTableCellFrame* GetCellFrame() const;
109 private:
110 friend class nsCellMap;
111 friend class BCCellData;
114 * Implemented in nsCellMap.cpp
116 * @param aOrigCell the table cell frame which will be stored in mOrigCell.
118 explicit CellData(nsTableCellFrame* aOrigCell);
120 ~CellData(); // implemented in nsCellMap.cpp
122 protected:
123 // this union relies on the assumption that an object (not primitive type)
124 // does not start on an odd bit boundary. If mSpan is 0 then mOrigCell is in
125 // effect and the data does not represent a span. If mSpan is 1, then mBits is
126 // in effect and the data represents a span. mBits must match the size of
127 // mOrigCell on both 32- and 64-bit platforms.
128 union {
129 nsTableCellFrame* mOrigCell;
130 uintptr_t mBits;
134 // Border Collapsing Cell Data
135 enum BCBorderOwner {
136 eTableOwner = 0,
137 eColGroupOwner = 1,
138 eAjaColGroupOwner = 2, // col group to the left
139 eColOwner = 3,
140 eAjaColOwner = 4, // col to the left
141 eRowGroupOwner = 5,
142 eAjaRowGroupOwner = 6, // row group above
143 eRowOwner = 7,
144 eAjaRowOwner = 8, // row above
145 eCellOwner = 9,
146 eAjaCellOwner = 10 // cell to the top or to the left
149 // BCPixelSize is in device pixels.
150 typedef uint16_t BCPixelSize;
152 // These are the max sizes that are stored. If they are exceeded, then the max
153 // is stored and the actual value is computed when needed.
154 #define MAX_BORDER_WIDTH nscoord((1u << (sizeof(BCPixelSize) * 8)) - 1)
156 // The half of border on inline/block-axis start side
157 static inline BCPixelSize BC_BORDER_START_HALF(BCPixelSize px) {
158 return px - px / 2;
160 // The half of border on inline/block-axis end side
161 static inline BCPixelSize BC_BORDER_END_HALF(BCPixelSize px) { return px / 2; }
163 static inline nscoord BC_BORDER_START_HALF_COORD(int32_t d2a, BCPixelSize px) {
164 return BC_BORDER_START_HALF(px) * d2a;
166 static inline nscoord BC_BORDER_END_HALF_COORD(int32_t d2a, BCPixelSize px) {
167 return BC_BORDER_END_HALF(px) * d2a;
170 // BCData stores the bstart and istart border info and the corner connecting the
171 // two.
172 class BCData {
173 public:
174 BCData();
176 ~BCData();
178 nscoord GetIStartEdge(BCBorderOwner& aOwner, bool& aStart) const;
180 void SetIStartEdge(BCBorderOwner aOwner, nscoord aSize, bool aStart);
182 nscoord GetBStartEdge(BCBorderOwner& aOwner, bool& aStart) const;
184 void SetBStartEdge(BCBorderOwner aOwner, nscoord aSize, bool aStart);
186 BCPixelSize GetCorner(mozilla::LogicalSide& aCornerOwner, bool& aBevel) const;
188 void SetCorner(BCPixelSize aSubSize, mozilla::LogicalSide aOwner,
189 bool aBevel);
191 inline bool IsIStartStart() const { return (bool)mIStartStart; }
193 inline void SetIStartStart(bool aValue) { mIStartStart = aValue; }
195 inline bool IsBStartStart() const { return (bool)mBStartStart; }
197 inline void SetBStartStart(bool aValue) { mBStartStart = aValue; }
199 protected:
200 BCPixelSize mIStartSize; // size in pixels of iStart border
201 BCPixelSize mBStartSize; // size in pixels of bStart border
202 BCPixelSize mCornerSubSize; // size of the largest border not in the
203 // dominant plane (for example, if corner is
204 // owned by the segment to its bStart or bEnd,
205 // then the size is the max of the border
206 // sizes of the segments to its iStart or iEnd.
207 unsigned mIStartOwner : 4; // owner of iStart border
208 unsigned mBStartOwner : 4; // owner of bStart border
209 unsigned mIStartStart : 1; // set if this is the start of a block-dir border
210 // segment
211 unsigned mBStartStart : 1; // set if this is the start of an inline-dir
212 // border segment
213 unsigned mCornerSide : 2; // LogicalSide of the owner of the bStart-iStart
214 // corner relative to the corner
215 unsigned mCornerBevel : 1; // is the corner beveled (only two segments,
216 // perpendicular, not dashed or dotted).
219 // BCCellData entries replace CellData entries in the cell map if the border
220 // collapsing model is in effect. BCData for a row and col entry contains the
221 // left and top borders of cell at that row and col and the corner connecting
222 // the two. The right borders of the cells in the last col and the bottom
223 // borders of the last row are stored in separate BCData entries in the cell
224 // map.
225 class BCCellData : public CellData {
226 public:
227 explicit BCCellData(nsTableCellFrame* aOrigCell);
228 ~BCCellData();
230 BCData mData;
233 // The layout of a celldata is as follows. The top 10 bits are the colspan
234 // offset (which is enough to represent our allowed values 1-1000 for colspan).
235 // Then there are two bits of flags.
236 // XXXmats Then one unused bit that we should decide how to use in bug 862624.
237 // Then 16 bits of rowspan offset (which
238 // lets us represent numbers up to 65535. Then another 3 bits of flags.
240 // num bits to shift right to get right aligned col span
241 #define COL_SPAN_SHIFT 22
242 // num bits to shift right to get right aligned row span
243 #define ROW_SPAN_SHIFT 3
245 // the col offset to the data containing the original cell.
246 #define COL_SPAN_OFFSET (0x3FF << COL_SPAN_SHIFT)
247 // the row offset to the data containing the original cell
248 #define ROW_SPAN_OFFSET (0xFFFF << ROW_SPAN_SHIFT)
250 // And the flags
251 #define SPAN 0x00000001 // there a row or col span
252 #define ROW_SPAN 0x00000002 // there is a row span
253 #define ROW_SPAN_0 0x00000004 // the row span is 0
254 #define COL_SPAN (1 << (COL_SPAN_SHIFT - 2)) // there is a col span
255 #define OVERLAP \
256 (1 << (COL_SPAN_SHIFT - 1)) // there is a row span and
257 // col span but not by
258 // same cell
260 inline nsTableCellFrame* CellData::GetCellFrame() const {
261 if (SPAN != (SPAN & mBits)) {
262 return mOrigCell;
264 return nullptr;
267 inline void CellData::Init(nsTableCellFrame* aCellFrame) {
268 mOrigCell = aCellFrame;
271 inline bool CellData::IsOrig() const {
272 return ((nullptr != mOrigCell) && (SPAN != (SPAN & mBits)));
275 inline bool CellData::IsDead() const { return (0 == mBits); }
277 inline bool CellData::IsSpan() const { return (SPAN == (SPAN & mBits)); }
279 inline bool CellData::IsRowSpan() const {
280 return (SPAN == (SPAN & mBits)) && (ROW_SPAN == (ROW_SPAN & mBits));
283 inline bool CellData::IsZeroRowSpan() const {
284 return (SPAN == (SPAN & mBits)) && (ROW_SPAN == (ROW_SPAN & mBits)) &&
285 (ROW_SPAN_0 == (ROW_SPAN_0 & mBits));
288 inline void CellData::SetZeroRowSpan(bool aIsZeroSpan) {
289 if (SPAN == (SPAN & mBits)) {
290 if (aIsZeroSpan) {
291 mBits |= ROW_SPAN_0;
292 } else {
293 mBits &= ~ROW_SPAN_0;
298 inline uint32_t CellData::GetRowSpanOffset() const {
299 if ((SPAN == (SPAN & mBits)) && ((ROW_SPAN == (ROW_SPAN & mBits)))) {
300 return (uint32_t)((mBits & ROW_SPAN_OFFSET) >> ROW_SPAN_SHIFT);
302 return 0;
305 inline void CellData::SetRowSpanOffset(uint32_t aSpan) {
306 mBits &= ~ROW_SPAN_OFFSET;
307 mBits |= (aSpan << ROW_SPAN_SHIFT);
308 mBits |= SPAN;
309 mBits |= ROW_SPAN;
312 inline bool CellData::IsColSpan() const {
313 return (SPAN == (SPAN & mBits)) && (COL_SPAN == (COL_SPAN & mBits));
316 inline uint32_t CellData::GetColSpanOffset() const {
317 if ((SPAN == (SPAN & mBits)) && ((COL_SPAN == (COL_SPAN & mBits)))) {
318 return (uint32_t)((mBits & COL_SPAN_OFFSET) >> COL_SPAN_SHIFT);
320 return 0;
323 inline void CellData::SetColSpanOffset(uint32_t aSpan) {
324 mBits &= ~COL_SPAN_OFFSET;
325 mBits |= (aSpan << COL_SPAN_SHIFT);
327 mBits |= SPAN;
328 mBits |= COL_SPAN;
331 inline bool CellData::IsOverlap() const {
332 return (SPAN == (SPAN & mBits)) && (OVERLAP == (OVERLAP & mBits));
335 inline void CellData::SetOverlap(bool aOverlap) {
336 if (SPAN == (SPAN & mBits)) {
337 if (aOverlap) {
338 mBits |= OVERLAP;
339 } else {
340 mBits &= ~OVERLAP;
345 inline BCData::BCData() {
346 mIStartOwner = mBStartOwner = eCellOwner;
347 SetBStartStart(true);
348 SetIStartStart(true);
349 mIStartSize = mCornerSubSize = mBStartSize = 0;
350 mCornerSide = mozilla::eLogicalSideBStart;
351 mCornerBevel = false;
354 inline BCData::~BCData() = default;
356 inline nscoord BCData::GetIStartEdge(BCBorderOwner& aOwner,
357 bool& aStart) const {
358 aOwner = (BCBorderOwner)mIStartOwner;
359 aStart = IsIStartStart();
361 return (nscoord)mIStartSize;
364 inline void BCData::SetIStartEdge(BCBorderOwner aOwner, nscoord aSize,
365 bool aStart) {
366 mIStartOwner = aOwner;
367 mIStartSize = (aSize > MAX_BORDER_WIDTH) ? MAX_BORDER_WIDTH : aSize;
368 SetIStartStart(aStart);
371 inline nscoord BCData::GetBStartEdge(BCBorderOwner& aOwner,
372 bool& aStart) const {
373 aOwner = (BCBorderOwner)mBStartOwner;
374 aStart = IsBStartStart();
376 return (nscoord)mBStartSize;
379 inline void BCData::SetBStartEdge(BCBorderOwner aOwner, nscoord aSize,
380 bool aStart) {
381 mBStartOwner = aOwner;
382 mBStartSize = (aSize > MAX_BORDER_WIDTH) ? MAX_BORDER_WIDTH : aSize;
383 SetBStartStart(aStart);
386 inline BCPixelSize BCData::GetCorner(mozilla::LogicalSide& aOwnerSide,
387 bool& aBevel) const {
388 aOwnerSide = mozilla::LogicalSide(mCornerSide);
389 aBevel = (bool)mCornerBevel;
390 return mCornerSubSize;
393 inline void BCData::SetCorner(BCPixelSize aSubSize,
394 mozilla::LogicalSide aOwnerSide, bool aBevel) {
395 mCornerSubSize = aSubSize;
396 mCornerSide = aOwnerSide;
397 mCornerBevel = aBevel;
400 #endif