1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
24 * Alternatively, the contents of this file may be used under the terms of
25 * either of the GNU General Public License Version 2 or later (the "GPL"),
26 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
40 #include "nsISupports.h"
43 class nsTableCellFrame
;
48 #define MAX_ROWSPAN 8190 // the cellmap can not handle more
49 #define MAX_COLSPAN 1000 // limit as IE and opera do
52 * Data stored by nsCellMap to rationalize rowspan and colspan cells.
57 /** Initialize the mOrigCell pointer
58 * @param aOrigCell the table cell frame which will be stored in mOrigCell.
60 void Init(nsTableCellFrame
* aCellFrame
);
62 /** does a cell originate from here
63 * @return is true if a cell corresponds to this cellmap entry
65 PRBool
IsOrig() const;
67 /** is the celldata valid
68 * @return is true if no cell originates and the cell is not spanned by
69 * a row- or colspan. mBits are 0 in this case and mOrigCell is
72 PRBool
IsDead() const;
74 /** is the entry spanned by row- or a colspan
75 * @return is true if the entry is spanned by a row- or colspan
77 PRBool
IsSpan() const;
79 /** is the entry spanned by rowspan
80 * @return is true if the entry is spanned by a rowspan
82 PRBool
IsRowSpan() const;
84 /** is the entry spanned by a zero rowspan
85 * zero rowspans span all cells starting from the originating cell down to
86 * the end of the rowgroup or a cell originating in the same column
87 * @return is true if the entry is spanned by a zero rowspan
89 PRBool
IsZeroRowSpan() const;
91 /** mark the current entry as spanned by a zero rowspan
92 * @param aIsZero if true mark the entry as covered by a zero rowspan
94 void SetZeroRowSpan(PRBool aIsZero
);
96 /** get the distance from the current entry to the corresponding origin of the rowspan
97 * @return containing the distance in the column to the originating cell
99 PRUint32
GetRowSpanOffset() const;
101 /** set the distance from the current entry to the corresponding origin of the rowspan
102 * @param the distance in the column to the originating cell
104 void SetRowSpanOffset(PRUint32 aSpan
);
106 /** is the entry spanned by colspan
107 * @return is true if the entry is spanned by a colspan
109 PRBool
IsColSpan() const;
111 /** is the entry spanned by a zero colspan
112 * zero colspans span all cells starting from the originating cell towards
113 * the end of the colgroup or a cell originating in the same row
114 * or a rowspanned entry
115 * @return is true if the entry is spanned by a zero colspan
117 PRBool
IsZeroColSpan() const;
119 /** mark the current entry as spanned by a zero colspan
120 * @param aIsZero if true mark the entry as covered by a zero colspan
122 void SetZeroColSpan(PRBool aIsZero
);
124 /** get the distance from the current entry to the corresponding origin of the colspan
125 * @return containing the distance in the row to the originating cell
127 PRUint32
GetColSpanOffset() const;
129 /** set the distance from the current entry to the corresponding origin of the colspan
130 * @param the distance in the column to the originating cell
132 void SetColSpanOffset(PRUint32 aSpan
);
134 /** is the entry spanned by a row- and a colspan
135 * @return is true if the entry is spanned by a row- and a colspan
137 PRBool
IsOverlap() const;
139 /** mark the current entry as spanned by a row- and a colspan
140 * @param aOverlap if true mark the entry as covered by a row- and a colspan
142 void SetOverlap(PRBool aOverlap
);
144 /** get the table cell frame for this entry
145 * @return a pointer to the cellframe, this will be nsnull when the entry
146 * is only a spanned entry
148 nsTableCellFrame
* GetCellFrame() const;
151 friend class nsCellMap
;
152 friend class BCCellData
;
155 * @param aOrigCell the table cell frame which will be stored in mOrigCell.
157 CellData(nsTableCellFrame
* aOrigCell
); // implemented in nsCellMap.cpp
160 ~CellData(); // implemented in nsCellMap.cpp
164 // this union relies on the assumption that an object (not primitive type) does
165 // not start on an odd bit boundary. If mSpan is 0 then mOrigCell is in effect
166 // and the data does not represent a span. If mSpan is 1, then mBits is in
167 // effect and the data represents a span.
168 // mBits must be an unsigned long because it must match the size of
169 // mOrigCell on both 32- and 64-bit platforms.
171 nsTableCellFrame
* mOrigCell
;
176 // Border Collapsing Cell Data
181 eAjaColGroupOwner
= 2, // col group to the left
183 eAjaColOwner
= 4, // col to the left
185 eAjaRowGroupOwner
= 6, // row group above
187 eAjaRowOwner
= 8, // row above
189 eAjaCellOwner
= 10 // cell to the top or to the left
192 typedef PRUint16 BCPixelSize
;
194 // These are the max sizes that are stored. If they are exceeded, then the max is stored and
195 // the actual value is computed when needed.
196 #define MAX_BORDER_WIDTH nscoord(PR_BITMASK(sizeof(BCPixelSize) * 8))
198 #define BC_BORDER_TOP_HALF_COORD(p2t,px) NSToCoordRound(float((px) - (px) / 2) * (p2t) )
199 #define BC_BORDER_RIGHT_HALF_COORD(p2t,px) NSToCoordRound(float( (px) / 2) * (p2t) )
200 #define BC_BORDER_BOTTOM_HALF_COORD(p2t,px) NSToCoordRound(float( (px) / 2) * (p2t) )
201 #define BC_BORDER_LEFT_HALF_COORD(p2t,px) NSToCoordRound(float((px) - (px) / 2) * (p2t) )
203 #define BC_BORDER_TOP_HALF(px) ((px) - (px) / 2)
204 #define BC_BORDER_RIGHT_HALF(px) ((px) / 2)
205 #define BC_BORDER_BOTTOM_HALF(px) ((px) / 2)
206 #define BC_BORDER_LEFT_HALF(px) ((px) - (px) / 2)
208 // BCData stores the top and left border info and the corner connecting the two.
216 nscoord
GetLeftEdge(BCBorderOwner
& aOwner
,
217 PRBool
& aStart
) const;
219 void SetLeftEdge(BCBorderOwner aOwner
,
223 nscoord
GetTopEdge(BCBorderOwner
& aOwner
,
224 PRBool
& aStart
) const;
226 void SetTopEdge(BCBorderOwner aOwner
,
230 BCPixelSize
GetCorner(PRUint8
& aCornerOwner
,
231 PRPackedBool
& aBevel
) const;
233 void SetCorner(BCPixelSize aSubSize
,
237 PRBool
IsLeftStart() const;
239 void SetLeftStart(PRBool aValue
);
241 PRBool
IsTopStart() const;
243 void SetTopStart(PRBool aValue
);
247 BCPixelSize mLeftSize
; // size in pixels of left border
248 BCPixelSize mTopSize
; // size in pixels of top border
249 BCPixelSize mCornerSubSize
; // size of the largest border not in the
250 // dominant plane (for example, if corner is
251 // owned by the segment to its top or bottom,
252 // then the size is the max of the border
253 // sizes of the segments to its left or right.
254 unsigned mLeftOwner
: 4; // owner of left border
255 unsigned mTopOwner
: 4; // owner of top border
256 unsigned mLeftStart
: 1; // set if this is the start of a vertical border segment
257 unsigned mTopStart
: 1; // set if this is the start of a horizontal border segment
258 unsigned mCornerSide
: 2; // side of the owner of the upper left corner relative to the corner
259 unsigned mCornerBevel
: 1; // is the corner beveled (only two segments, perpendicular, not dashed or dotted).
262 // BCCellData entries replace CellData entries in the cell map if the border collapsing model is in
263 // effect. BCData for a row and col entry contains the left and top borders of cell at that row and
264 // col and the corner connecting the two. The right borders of the cells in the last col and the bottom
265 // borders of the last row are stored in separate BCData entries in the cell map.
266 class BCCellData
: public CellData
269 BCCellData(nsTableCellFrame
* aOrigCell
);
276 #define SPAN 0x00000001 // there a row or col span
277 #define ROW_SPAN 0x00000002 // there is a row span
278 #define ROW_SPAN_0 0x00000004 // the row span is 0
279 #define ROW_SPAN_OFFSET 0x0000FFF8 // the row offset to the data containing the original cell
280 #define COL_SPAN 0x00010000 // there is a col span
281 #define COL_SPAN_0 0x00020000 // the col span is 0
282 #define OVERLAP 0x00040000 // there is a row span and col span but no by same cell
283 #define COL_SPAN_OFFSET 0xFFF80000 // the col offset to the data containing the original cell
284 #define ROW_SPAN_SHIFT 3 // num bits to shift to get right justified row span
285 #define COL_SPAN_SHIFT 19 // num bits to shift to get right justified col span
287 inline nsTableCellFrame
* CellData::GetCellFrame() const
289 if (SPAN
!= (SPAN
& mBits
)) {
295 inline void CellData::Init(nsTableCellFrame
* aCellFrame
)
297 mOrigCell
= aCellFrame
;
300 inline PRBool
CellData::IsOrig() const
302 return ((nsnull
!= mOrigCell
) && (SPAN
!= (SPAN
& mBits
)));
305 inline PRBool
CellData::IsDead() const
310 inline PRBool
CellData::IsSpan() const
312 return (SPAN
== (SPAN
& mBits
));
315 inline PRBool
CellData::IsRowSpan() const
317 return (SPAN
== (SPAN
& mBits
)) &&
318 (ROW_SPAN
== (ROW_SPAN
& mBits
));
321 inline PRBool
CellData::IsZeroRowSpan() const
323 return (SPAN
== (SPAN
& mBits
)) &&
324 (ROW_SPAN
== (ROW_SPAN
& mBits
)) &&
325 (ROW_SPAN_0
== (ROW_SPAN_0
& mBits
));
328 inline void CellData::SetZeroRowSpan(PRBool aIsZeroSpan
)
330 if (SPAN
== (SPAN
& mBits
)) {
335 mBits
&= ~ROW_SPAN_0
;
340 inline PRUint32
CellData::GetRowSpanOffset() const
342 if ((SPAN
== (SPAN
& mBits
)) && ((ROW_SPAN
== (ROW_SPAN
& mBits
)))) {
343 return (PRUint32
)((mBits
& ROW_SPAN_OFFSET
) >> ROW_SPAN_SHIFT
);
348 inline void CellData::SetRowSpanOffset(PRUint32 aSpan
)
350 mBits
&= ~ROW_SPAN_OFFSET
;
351 mBits
|= (aSpan
<< ROW_SPAN_SHIFT
);
356 inline PRBool
CellData::IsColSpan() const
358 return (SPAN
== (SPAN
& mBits
)) &&
359 (COL_SPAN
== (COL_SPAN
& mBits
));
362 inline PRBool
CellData::IsZeroColSpan() const
364 return (SPAN
== (SPAN
& mBits
)) &&
365 (COL_SPAN
== (COL_SPAN
& mBits
)) &&
366 (COL_SPAN_0
== (COL_SPAN_0
& mBits
));
369 inline void CellData::SetZeroColSpan(PRBool aIsZeroSpan
)
371 if (SPAN
== (SPAN
& mBits
)) {
376 mBits
&= ~COL_SPAN_0
;
381 inline PRUint32
CellData::GetColSpanOffset() const
383 if ((SPAN
== (SPAN
& mBits
)) && ((COL_SPAN
== (COL_SPAN
& mBits
)))) {
384 return (PRUint32
)((mBits
& COL_SPAN_OFFSET
) >> COL_SPAN_SHIFT
);
389 inline void CellData::SetColSpanOffset(PRUint32 aSpan
)
391 mBits
&= ~COL_SPAN_OFFSET
;
392 mBits
|= (aSpan
<< COL_SPAN_SHIFT
);
398 inline PRBool
CellData::IsOverlap() const
400 return (SPAN
== (SPAN
& mBits
)) && (OVERLAP
== (OVERLAP
& mBits
));
403 inline void CellData::SetOverlap(PRBool aOverlap
)
405 if (SPAN
== (SPAN
& mBits
)) {
415 inline BCData::BCData()
417 mLeftOwner
= mTopOwner
= eCellOwner
;
418 mLeftStart
= mTopStart
= 1;
419 mLeftSize
= mCornerSide
= mCornerSubSize
= mTopSize
= 0;
420 mCornerBevel
= PR_FALSE
;
423 inline BCData::~BCData()
427 inline nscoord
BCData::GetLeftEdge(BCBorderOwner
& aOwner
,
428 PRBool
& aStart
) const
430 aOwner
= (BCBorderOwner
)mLeftOwner
;
431 aStart
= (PRBool
)mLeftStart
;
433 return (nscoord
)mLeftSize
;
436 inline void BCData::SetLeftEdge(BCBorderOwner aOwner
,
441 mLeftSize
= (aSize
> MAX_BORDER_WIDTH
) ? MAX_BORDER_WIDTH
: aSize
;
445 inline nscoord
BCData::GetTopEdge(BCBorderOwner
& aOwner
,
446 PRBool
& aStart
) const
448 aOwner
= (BCBorderOwner
)mTopOwner
;
449 aStart
= (PRBool
)mTopStart
;
451 return (nscoord
)mTopSize
;
454 inline void BCData::SetTopEdge(BCBorderOwner aOwner
,
459 mTopSize
= (aSize
> MAX_BORDER_WIDTH
) ? MAX_BORDER_WIDTH
: aSize
;
463 inline BCPixelSize
BCData::GetCorner(PRUint8
& aOwnerSide
,
464 PRPackedBool
& aBevel
) const
466 aOwnerSide
= mCornerSide
;
467 aBevel
= (PRBool
)mCornerBevel
;
468 return mCornerSubSize
;
471 inline void BCData::SetCorner(BCPixelSize aSubSize
,
475 mCornerSubSize
= aSubSize
;
476 mCornerSide
= aOwnerSide
;
477 mCornerBevel
= aBevel
;
480 inline PRBool
BCData::IsLeftStart() const
482 return (PRBool
)mLeftStart
;
485 inline void BCData::SetLeftStart(PRBool aValue
)
490 inline PRBool
BCData::IsTopStart() const
492 return (PRBool
)mTopStart
;
495 inline void BCData::SetTopStart(PRBool aValue
)