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/. */
8 #include "nsISupports.h"
9 #include "nsITableCellLayout.h" // for MAX_COLSPAN / MAX_ROWSPAN
11 #include "mozilla/gfx/Types.h"
12 #include "mozilla/WritingModes.h"
15 class nsTableCellFrame
;
20 * Data stored by nsCellMap to rationalize rowspan and colspan cells.
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
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
41 /** is the entry spanned by row- or a colspan
42 * @return is true if the entry is spanned by a row- or colspan
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
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
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
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
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
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;
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
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.
129 nsTableCellFrame
* mOrigCell
;
134 // Border Collapsing Cell Data
138 eAjaColGroupOwner
= 2, // col group to the left
140 eAjaColOwner
= 4, // col to the left
142 eAjaRowGroupOwner
= 6, // row group above
144 eAjaRowOwner
= 8, // row above
146 eAjaCellOwner
= 10 // cell to the top or to the left
149 // These are the max sizes that are stored. If they are exceeded, then the max
150 // is stored and the actual value is computed when needed.
151 #define MAX_BORDER_WIDTH nscoord((1u << (sizeof(uint16_t) * 8)) - 1)
153 // The half of border on inline/block-axis start side
154 static inline nscoord
BC_BORDER_START_HALF(nscoord aCoord
) {
155 return aCoord
- aCoord
/ 2;
157 // The half of border on inline/block-axis end side
158 static inline nscoord
BC_BORDER_END_HALF(nscoord aCoord
) { return aCoord
/ 2; }
160 // BCData stores the bstart and istart border info and the corner connecting the
168 nscoord
GetIStartEdge(BCBorderOwner
& aOwner
, bool& aStart
) const;
170 void SetIStartEdge(BCBorderOwner aOwner
, nscoord aSize
, bool aStart
);
172 nscoord
GetBStartEdge(BCBorderOwner
& aOwner
, bool& aStart
) const;
174 void SetBStartEdge(BCBorderOwner aOwner
, nscoord aSize
, bool aStart
);
176 nscoord
GetCorner(mozilla::LogicalSide
& aOwnerSide
, bool& aBevel
) const;
178 void SetCorner(nscoord aSubSize
, mozilla::LogicalSide aOwner
, bool aBevel
);
180 inline bool IsIStartStart() const { return (bool)mIStartStart
; }
182 inline void SetIStartStart(bool aValue
) { mIStartStart
= aValue
; }
184 inline bool IsBStartStart() const { return (bool)mBStartStart
; }
186 inline void SetBStartStart(bool aValue
) { mBStartStart
= aValue
; }
189 nscoord mIStartSize
; // size of iStart border
190 nscoord mBStartSize
; // size of bStart border
191 nscoord mCornerSubSize
; // size of the largest border not in the
192 // dominant plane (for example, if corner is
193 // owned by the segment to its bStart or bEnd,
194 // then the size is the max of the border
195 // sizes of the segments to its iStart or iEnd.
196 unsigned mIStartOwner
: 4; // owner of iStart border
197 unsigned mBStartOwner
: 4; // owner of bStart border
198 unsigned mIStartStart
: 1; // set if this is the start of a block-dir border
200 unsigned mBStartStart
: 1; // set if this is the start of an inline-dir
202 unsigned mCornerSide
: 2; // LogicalSide of the owner of the bStart-iStart
203 // corner relative to the corner
204 unsigned mCornerBevel
: 1; // is the corner beveled (only two segments,
205 // perpendicular, not dashed or dotted).
208 // BCCellData entries replace CellData entries in the cell map if the border
209 // collapsing model is in effect. BCData for a row and col entry contains the
210 // left and top borders of cell at that row and col and the corner connecting
211 // the two. The right borders of the cells in the last col and the bottom
212 // borders of the last row are stored in separate BCData entries in the cell
214 class BCCellData
: public CellData
{
216 explicit BCCellData(nsTableCellFrame
* aOrigCell
);
222 // The layout of a celldata is as follows. The top 10 bits are the colspan
223 // offset (which is enough to represent our allowed values 1-1000 for colspan).
224 // Then there are two bits of flags.
225 // XXXmats Then one unused bit that we should decide how to use in bug 862624.
226 // Then 16 bits of rowspan offset (which
227 // lets us represent numbers up to 65535. Then another 3 bits of flags.
229 // num bits to shift right to get right aligned col span
230 #define COL_SPAN_SHIFT 22
231 // num bits to shift right to get right aligned row span
232 #define ROW_SPAN_SHIFT 3
234 // the col offset to the data containing the original cell.
235 #define COL_SPAN_OFFSET (0x3FF << COL_SPAN_SHIFT)
236 // the row offset to the data containing the original cell
237 #define ROW_SPAN_OFFSET (0xFFFF << ROW_SPAN_SHIFT)
240 #define SPAN 0x00000001 // there a row or col span
241 #define ROW_SPAN 0x00000002 // there is a row span
242 #define ROW_SPAN_0 0x00000004 // the row span is 0
243 #define COL_SPAN (1 << (COL_SPAN_SHIFT - 2)) // there is a col span
245 (1 << (COL_SPAN_SHIFT - 1)) // there is a row span and
246 // col span but not by
249 inline nsTableCellFrame
* CellData::GetCellFrame() const {
250 if (SPAN
!= (SPAN
& mBits
)) {
256 inline void CellData::Init(nsTableCellFrame
* aCellFrame
) {
257 mOrigCell
= aCellFrame
;
260 inline bool CellData::IsOrig() const {
261 return ((nullptr != mOrigCell
) && (SPAN
!= (SPAN
& mBits
)));
264 inline bool CellData::IsDead() const { return (0 == mBits
); }
266 inline bool CellData::IsSpan() const { return (SPAN
== (SPAN
& mBits
)); }
268 inline bool CellData::IsRowSpan() const {
269 return (SPAN
== (SPAN
& mBits
)) && (ROW_SPAN
== (ROW_SPAN
& mBits
));
272 inline bool CellData::IsZeroRowSpan() const {
273 return (SPAN
== (SPAN
& mBits
)) && (ROW_SPAN
== (ROW_SPAN
& mBits
)) &&
274 (ROW_SPAN_0
== (ROW_SPAN_0
& mBits
));
277 inline void CellData::SetZeroRowSpan(bool aIsZeroSpan
) {
278 if (SPAN
== (SPAN
& mBits
)) {
282 mBits
&= ~ROW_SPAN_0
;
287 inline uint32_t CellData::GetRowSpanOffset() const {
288 if ((SPAN
== (SPAN
& mBits
)) && ((ROW_SPAN
== (ROW_SPAN
& mBits
)))) {
289 return (uint32_t)((mBits
& ROW_SPAN_OFFSET
) >> ROW_SPAN_SHIFT
);
294 inline void CellData::SetRowSpanOffset(uint32_t aSpan
) {
295 mBits
&= ~ROW_SPAN_OFFSET
;
296 mBits
|= (aSpan
<< ROW_SPAN_SHIFT
);
301 inline bool CellData::IsColSpan() const {
302 return (SPAN
== (SPAN
& mBits
)) && (COL_SPAN
== (COL_SPAN
& mBits
));
305 inline uint32_t CellData::GetColSpanOffset() const {
306 if ((SPAN
== (SPAN
& mBits
)) && ((COL_SPAN
== (COL_SPAN
& mBits
)))) {
307 return (uint32_t)((mBits
& COL_SPAN_OFFSET
) >> COL_SPAN_SHIFT
);
312 inline void CellData::SetColSpanOffset(uint32_t aSpan
) {
313 mBits
&= ~COL_SPAN_OFFSET
;
314 mBits
|= (aSpan
<< COL_SPAN_SHIFT
);
320 inline bool CellData::IsOverlap() const {
321 return (SPAN
== (SPAN
& mBits
)) && (OVERLAP
== (OVERLAP
& mBits
));
324 inline void CellData::SetOverlap(bool aOverlap
) {
325 if (SPAN
== (SPAN
& mBits
)) {
334 inline BCData::BCData() {
335 mIStartOwner
= mBStartOwner
= eCellOwner
;
336 SetBStartStart(true);
337 SetIStartStart(true);
338 mIStartSize
= mCornerSubSize
= mBStartSize
= 0;
339 mCornerSide
= static_cast<uint8_t>(mozilla::LogicalSide::BStart
);
340 mCornerBevel
= false;
343 inline BCData::~BCData() = default;
345 inline nscoord
BCData::GetIStartEdge(BCBorderOwner
& aOwner
,
346 bool& aStart
) const {
347 aOwner
= (BCBorderOwner
)mIStartOwner
;
348 aStart
= IsIStartStart();
350 return (nscoord
)mIStartSize
;
353 inline void BCData::SetIStartEdge(BCBorderOwner aOwner
, nscoord aSize
,
355 mIStartOwner
= aOwner
;
356 mIStartSize
= (aSize
> MAX_BORDER_WIDTH
) ? MAX_BORDER_WIDTH
: aSize
;
357 SetIStartStart(aStart
);
360 inline nscoord
BCData::GetBStartEdge(BCBorderOwner
& aOwner
,
361 bool& aStart
) const {
362 aOwner
= (BCBorderOwner
)mBStartOwner
;
363 aStart
= IsBStartStart();
365 return (nscoord
)mBStartSize
;
368 inline void BCData::SetBStartEdge(BCBorderOwner aOwner
, nscoord aSize
,
370 mBStartOwner
= aOwner
;
371 mBStartSize
= (aSize
> MAX_BORDER_WIDTH
) ? MAX_BORDER_WIDTH
: aSize
;
372 SetBStartStart(aStart
);
375 inline nscoord
BCData::GetCorner(mozilla::LogicalSide
& aOwnerSide
,
376 bool& aBevel
) const {
377 aOwnerSide
= mozilla::LogicalSide(mCornerSide
);
378 aBevel
= (bool)mCornerBevel
;
379 return mCornerSubSize
;
382 inline void BCData::SetCorner(nscoord aSubSize
, mozilla::LogicalSide aOwnerSide
,
384 mCornerSubSize
= aSubSize
;
385 mCornerSide
= static_cast<uint8_t>(aOwnerSide
);
386 mCornerBevel
= aBevel
;