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 // 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
) {
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
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
,
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
; }
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
211 unsigned mBStartStart
: 1; // set if this is the start of an inline-dir
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
225 class BCCellData
: public CellData
{
227 explicit BCCellData(nsTableCellFrame
* aOrigCell
);
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)
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
256 (1 << (COL_SPAN_SHIFT - 1)) // there is a row span and
257 // col span but not by
260 inline nsTableCellFrame
* CellData::GetCellFrame() const {
261 if (SPAN
!= (SPAN
& mBits
)) {
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
)) {
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
);
305 inline void CellData::SetRowSpanOffset(uint32_t aSpan
) {
306 mBits
&= ~ROW_SPAN_OFFSET
;
307 mBits
|= (aSpan
<< ROW_SPAN_SHIFT
);
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
);
323 inline void CellData::SetColSpanOffset(uint32_t aSpan
) {
324 mBits
&= ~COL_SPAN_OFFSET
;
325 mBits
|= (aSpan
<< COL_SPAN_SHIFT
);
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
)) {
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
,
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
,
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
;