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