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
4 : *
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/
9 : *
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
13 : * License.
14 : *
15 : * The Original Code is mozilla.org code.
16 : *
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.
21 : *
22 : * Contributor(s):
23 : *
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.
35 : *
36 : * ***** END LICENSE BLOCK ***** */
37 : #ifndef CellData_h__
38 : #define CellData_h__
39 :
40 : #include "nsISupports.h"
41 : #include "nsCoord.h"
42 : #include "mozilla/gfx/Types.h"
43 :
44 : class nsTableCellFrame;
45 : class nsCellMap;
46 : class BCCellData;
47 :
48 :
49 : #define MAX_ROWSPAN 65534 // the cellmap can not handle more.
50 : #define MAX_COLSPAN 1000 // limit as IE and opera do. If this ever changes,
51 : // change COL_SPAN_OFFSET/COL_SPAN_SHIFT accordingly.
52 :
53 : /**
54 : * Data stored by nsCellMap to rationalize rowspan and colspan cells.
55 : */
56 : class CellData
57 : {
58 : public:
59 : /** Initialize the mOrigCell pointer
60 : * @param aOrigCell the table cell frame which will be stored in mOrigCell.
61 : */
62 : void Init(nsTableCellFrame* aCellFrame);
63 :
64 : /** does a cell originate from here
65 : * @return is true if a cell corresponds to this cellmap entry
66 : */
67 : bool IsOrig() const;
68 :
69 : /** is the celldata valid
70 : * @return is true if no cell originates and the cell is not spanned by
71 : * a row- or colspan. mBits are 0 in this case and mOrigCell is
72 : * nsnull
73 : */
74 : bool IsDead() const;
75 :
76 : /** is the entry spanned by row- or a colspan
77 : * @return is true if the entry is spanned by a row- or colspan
78 : */
79 : bool IsSpan() const;
80 :
81 : /** is the entry spanned by rowspan
82 : * @return is true if the entry is spanned by a rowspan
83 : */
84 : bool IsRowSpan() const;
85 :
86 : /** is the entry spanned by a zero rowspan
87 : * zero rowspans span all cells starting from the originating cell down to
88 : * the end of the rowgroup or a cell originating in the same column
89 : * @return is true if the entry is spanned by a zero rowspan
90 : */
91 : bool IsZeroRowSpan() const;
92 :
93 : /** mark the current entry as spanned by a zero rowspan
94 : * @param aIsZero if true mark the entry as covered by a zero rowspan
95 : */
96 : void SetZeroRowSpan(bool aIsZero);
97 :
98 : /** get the distance from the current entry to the corresponding origin of the rowspan
99 : * @return containing the distance in the column to the originating cell
100 : */
101 : PRUint32 GetRowSpanOffset() const;
102 :
103 : /** set the distance from the current entry to the corresponding origin of the rowspan
104 : * @param the distance in the column to the originating cell
105 : */
106 : void SetRowSpanOffset(PRUint32 aSpan);
107 :
108 : /** is the entry spanned by colspan
109 : * @return is true if the entry is spanned by a colspan
110 : */
111 : bool IsColSpan() const;
112 :
113 : /** is the entry spanned by a zero colspan
114 : * zero colspans span all cells starting from the originating cell towards
115 : * the end of the colgroup or a cell originating in the same row
116 : * or a rowspanned entry
117 : * @return is true if the entry is spanned by a zero colspan
118 : */
119 : bool IsZeroColSpan() const;
120 :
121 : /** mark the current entry as spanned by a zero colspan
122 : * @param aIsZero if true mark the entry as covered by a zero colspan
123 : */
124 : void SetZeroColSpan(bool aIsZero);
125 :
126 : /** get the distance from the current entry to the corresponding origin of the colspan
127 : * @return containing the distance in the row to the originating cell
128 : */
129 : PRUint32 GetColSpanOffset() const;
130 :
131 : /** set the distance from the current entry to the corresponding origin of the colspan
132 : * @param the distance in the column to the originating cell
133 : */
134 : void SetColSpanOffset(PRUint32 aSpan);
135 :
136 : /** is the entry spanned by a row- and a colspan
137 : * @return is true if the entry is spanned by a row- and a colspan
138 : */
139 : bool IsOverlap() const;
140 :
141 : /** mark the current entry as spanned by a row- and a colspan
142 : * @param aOverlap if true mark the entry as covered by a row- and a colspan
143 : */
144 : void SetOverlap(bool aOverlap);
145 :
146 : /** get the table cell frame for this entry
147 : * @return a pointer to the cellframe, this will be nsnull when the entry
148 : * is only a spanned entry
149 : */
150 : nsTableCellFrame* GetCellFrame() const;
151 :
152 : private:
153 : friend class nsCellMap;
154 : friend class BCCellData;
155 :
156 : /** constructor.
157 : * @param aOrigCell the table cell frame which will be stored in mOrigCell.
158 : */
159 : CellData(nsTableCellFrame* aOrigCell); // implemented in nsCellMap.cpp
160 :
161 : /** destructor */
162 : ~CellData(); // implemented in nsCellMap.cpp
163 :
164 : protected:
165 :
166 : // this union relies on the assumption that an object (not primitive type) does
167 : // not start on an odd bit boundary. If mSpan is 0 then mOrigCell is in effect
168 : // and the data does not represent a span. If mSpan is 1, then mBits is in
169 : // effect and the data represents a span.
170 : // mBits must be an unsigned long because it must match the size of
171 : // mOrigCell on both 32- and 64-bit platforms.
172 : union {
173 : nsTableCellFrame* mOrigCell;
174 : unsigned long mBits;
175 : };
176 : };
177 :
178 : // Border Collapsing Cell Data
179 : enum BCBorderOwner
180 : {
181 : eTableOwner = 0,
182 : eColGroupOwner = 1,
183 : eAjaColGroupOwner = 2, // col group to the left
184 : eColOwner = 3,
185 : eAjaColOwner = 4, // col to the left
186 : eRowGroupOwner = 5,
187 : eAjaRowGroupOwner = 6, // row group above
188 : eRowOwner = 7,
189 : eAjaRowOwner = 8, // row above
190 : eCellOwner = 9,
191 : eAjaCellOwner = 10 // cell to the top or to the left
192 : };
193 :
194 : typedef PRUint16 BCPixelSize;
195 :
196 : // These are the max sizes that are stored. If they are exceeded, then the max is stored and
197 : // the actual value is computed when needed.
198 : #define MAX_BORDER_WIDTH nscoord(PR_BITMASK(sizeof(BCPixelSize) * 8))
199 :
200 : static inline nscoord
201 0 : BC_BORDER_TOP_HALF_COORD(PRInt32 p2t, PRUint16 px) { return (px - px / 2) * p2t; }
202 : static inline nscoord
203 0 : BC_BORDER_RIGHT_HALF_COORD(PRInt32 p2t, PRUint16 px) { return ( px / 2) * p2t; }
204 : static inline nscoord
205 0 : BC_BORDER_BOTTOM_HALF_COORD(PRInt32 p2t, PRUint16 px) { return ( px / 2) * p2t; }
206 : static inline nscoord
207 0 : BC_BORDER_LEFT_HALF_COORD(PRInt32 p2t, PRUint16 px) { return (px - px / 2) * p2t; }
208 :
209 : #define BC_BORDER_TOP_HALF(px) ((px) - (px) / 2)
210 : #define BC_BORDER_RIGHT_HALF(px) ((px) / 2)
211 : #define BC_BORDER_BOTTOM_HALF(px) ((px) / 2)
212 : #define BC_BORDER_LEFT_HALF(px) ((px) - (px) / 2)
213 :
214 : // BCData stores the top and left border info and the corner connecting the two.
215 : class BCData
216 : {
217 : public:
218 : BCData();
219 :
220 : ~BCData();
221 :
222 : nscoord GetLeftEdge(BCBorderOwner& aOwner,
223 : bool& aStart) const;
224 :
225 : void SetLeftEdge(BCBorderOwner aOwner,
226 : nscoord aSize,
227 : bool aStart);
228 :
229 : nscoord GetTopEdge(BCBorderOwner& aOwner,
230 : bool& aStart) const;
231 :
232 : void SetTopEdge(BCBorderOwner aOwner,
233 : nscoord aSize,
234 : bool aStart);
235 :
236 : BCPixelSize GetCorner(mozilla::css::Side& aCornerOwner,
237 : bool& aBevel) const;
238 :
239 : void SetCorner(BCPixelSize aSubSize,
240 : mozilla::css::Side aOwner,
241 : bool aBevel);
242 :
243 : bool IsLeftStart() const;
244 :
245 : void SetLeftStart(bool aValue);
246 :
247 : bool IsTopStart() const;
248 :
249 : void SetTopStart(bool aValue);
250 :
251 :
252 : protected:
253 : BCPixelSize mLeftSize; // size in pixels of left border
254 : BCPixelSize mTopSize; // size in pixels of top border
255 : BCPixelSize mCornerSubSize; // size of the largest border not in the
256 : // dominant plane (for example, if corner is
257 : // owned by the segment to its top or bottom,
258 : // then the size is the max of the border
259 : // sizes of the segments to its left or right.
260 : unsigned mLeftOwner: 4; // owner of left border
261 : unsigned mTopOwner: 4; // owner of top border
262 : unsigned mLeftStart: 1; // set if this is the start of a vertical border segment
263 : unsigned mTopStart: 1; // set if this is the start of a horizontal border segment
264 : unsigned mCornerSide: 2; // mozilla::css::Side of the owner of the upper left corner relative to the corner
265 : unsigned mCornerBevel: 1; // is the corner beveled (only two segments, perpendicular, not dashed or dotted).
266 : };
267 :
268 : // BCCellData entries replace CellData entries in the cell map if the border collapsing model is in
269 : // effect. BCData for a row and col entry contains the left and top borders of cell at that row and
270 : // col and the corner connecting the two. The right borders of the cells in the last col and the bottom
271 : // borders of the last row are stored in separate BCData entries in the cell map.
272 : class BCCellData : public CellData
273 : {
274 : public:
275 : BCCellData(nsTableCellFrame* aOrigCell);
276 : ~BCCellData();
277 :
278 : BCData mData;
279 : };
280 :
281 :
282 : // The layout of a celldata is as follows. The top 10 bits are the colspan
283 : // offset (which is enough to represent our allowed values 1-1000 for colspan).
284 : // Then there are three bits of flags. Then 16 bits of rowspan offset (which
285 : // lets us represent numbers up to 65535. Then another 3 bits of flags.
286 :
287 : // num bits to shift right to get right aligned col span
288 : #define COL_SPAN_SHIFT 22
289 : // num bits to shift right to get right aligned row span
290 : #define ROW_SPAN_SHIFT 3
291 :
292 : // the col offset to the data containing the original cell.
293 : #define COL_SPAN_OFFSET (0x3FF << COL_SPAN_SHIFT)
294 : // the row offset to the data containing the original cell
295 : #define ROW_SPAN_OFFSET (0xFFFF << ROW_SPAN_SHIFT)
296 :
297 : // And the flags
298 : #define SPAN 0x00000001 // there a row or col span
299 : #define ROW_SPAN 0x00000002 // there is a row span
300 : #define ROW_SPAN_0 0x00000004 // the row span is 0
301 : #define COL_SPAN (1 << (COL_SPAN_SHIFT - 3)) // there is a col span
302 : #define COL_SPAN_0 (1 << (COL_SPAN_SHIFT - 2)) // the col span is 0
303 : #define OVERLAP (1 << (COL_SPAN_SHIFT - 1)) // there is a row span and
304 : // col span but not by
305 : // same cell
306 :
307 0 : inline nsTableCellFrame* CellData::GetCellFrame() const
308 : {
309 0 : if (SPAN != (SPAN & mBits)) {
310 0 : return mOrigCell;
311 : }
312 0 : return nsnull;
313 : }
314 :
315 0 : inline void CellData::Init(nsTableCellFrame* aCellFrame)
316 : {
317 0 : mOrigCell = aCellFrame;
318 0 : }
319 :
320 0 : inline bool CellData::IsOrig() const
321 : {
322 0 : return ((nsnull != mOrigCell) && (SPAN != (SPAN & mBits)));
323 : }
324 :
325 0 : inline bool CellData::IsDead() const
326 : {
327 0 : return (0 == mBits);
328 : }
329 :
330 0 : inline bool CellData::IsSpan() const
331 : {
332 0 : return (SPAN == (SPAN & mBits));
333 : }
334 :
335 0 : inline bool CellData::IsRowSpan() const
336 : {
337 : return (SPAN == (SPAN & mBits)) &&
338 0 : (ROW_SPAN == (ROW_SPAN & mBits));
339 : }
340 :
341 0 : inline bool CellData::IsZeroRowSpan() const
342 : {
343 : return (SPAN == (SPAN & mBits)) &&
344 : (ROW_SPAN == (ROW_SPAN & mBits)) &&
345 0 : (ROW_SPAN_0 == (ROW_SPAN_0 & mBits));
346 : }
347 :
348 0 : inline void CellData::SetZeroRowSpan(bool aIsZeroSpan)
349 : {
350 0 : if (SPAN == (SPAN & mBits)) {
351 0 : if (aIsZeroSpan) {
352 0 : mBits |= ROW_SPAN_0;
353 : }
354 : else {
355 0 : mBits &= ~ROW_SPAN_0;
356 : }
357 : }
358 0 : }
359 :
360 0 : inline PRUint32 CellData::GetRowSpanOffset() const
361 : {
362 0 : if ((SPAN == (SPAN & mBits)) && ((ROW_SPAN == (ROW_SPAN & mBits)))) {
363 0 : return (PRUint32)((mBits & ROW_SPAN_OFFSET) >> ROW_SPAN_SHIFT);
364 : }
365 0 : return 0;
366 : }
367 :
368 0 : inline void CellData::SetRowSpanOffset(PRUint32 aSpan)
369 : {
370 0 : mBits &= ~ROW_SPAN_OFFSET;
371 0 : mBits |= (aSpan << ROW_SPAN_SHIFT);
372 0 : mBits |= SPAN;
373 0 : mBits |= ROW_SPAN;
374 0 : }
375 :
376 0 : inline bool CellData::IsColSpan() const
377 : {
378 : return (SPAN == (SPAN & mBits)) &&
379 0 : (COL_SPAN == (COL_SPAN & mBits));
380 : }
381 :
382 0 : inline bool CellData::IsZeroColSpan() const
383 : {
384 : return (SPAN == (SPAN & mBits)) &&
385 : (COL_SPAN == (COL_SPAN & mBits)) &&
386 0 : (COL_SPAN_0 == (COL_SPAN_0 & mBits));
387 : }
388 :
389 0 : inline void CellData::SetZeroColSpan(bool aIsZeroSpan)
390 : {
391 0 : if (SPAN == (SPAN & mBits)) {
392 0 : if (aIsZeroSpan) {
393 0 : mBits |= COL_SPAN_0;
394 : }
395 : else {
396 0 : mBits &= ~COL_SPAN_0;
397 : }
398 : }
399 0 : }
400 :
401 0 : inline PRUint32 CellData::GetColSpanOffset() const
402 : {
403 0 : if ((SPAN == (SPAN & mBits)) && ((COL_SPAN == (COL_SPAN & mBits)))) {
404 0 : return (PRUint32)((mBits & COL_SPAN_OFFSET) >> COL_SPAN_SHIFT);
405 : }
406 0 : return 0;
407 : }
408 :
409 0 : inline void CellData::SetColSpanOffset(PRUint32 aSpan)
410 : {
411 0 : mBits &= ~COL_SPAN_OFFSET;
412 0 : mBits |= (aSpan << COL_SPAN_SHIFT);
413 :
414 0 : mBits |= SPAN;
415 0 : mBits |= COL_SPAN;
416 0 : }
417 :
418 0 : inline bool CellData::IsOverlap() const
419 : {
420 0 : return (SPAN == (SPAN & mBits)) && (OVERLAP == (OVERLAP & mBits));
421 : }
422 :
423 0 : inline void CellData::SetOverlap(bool aOverlap)
424 : {
425 0 : if (SPAN == (SPAN & mBits)) {
426 0 : if (aOverlap) {
427 0 : mBits |= OVERLAP;
428 : }
429 : else {
430 0 : mBits &= ~OVERLAP;
431 : }
432 : }
433 0 : }
434 :
435 0 : inline BCData::BCData()
436 : {
437 0 : mLeftOwner = mTopOwner = eCellOwner;
438 0 : mLeftStart = mTopStart = 1;
439 0 : mLeftSize = mCornerSubSize = mTopSize = 0;
440 0 : mCornerSide = NS_SIDE_TOP;
441 0 : mCornerBevel = false;
442 0 : }
443 :
444 0 : inline BCData::~BCData()
445 : {
446 0 : }
447 :
448 0 : inline nscoord BCData::GetLeftEdge(BCBorderOwner& aOwner,
449 : bool& aStart) const
450 : {
451 0 : aOwner = (BCBorderOwner)mLeftOwner;
452 0 : aStart = (bool)mLeftStart;
453 :
454 0 : return (nscoord)mLeftSize;
455 : }
456 :
457 0 : inline void BCData::SetLeftEdge(BCBorderOwner aOwner,
458 : nscoord aSize,
459 : bool aStart)
460 : {
461 0 : mLeftOwner = aOwner;
462 0 : mLeftSize = (aSize > MAX_BORDER_WIDTH) ? MAX_BORDER_WIDTH : aSize;
463 0 : mLeftStart = aStart;
464 0 : }
465 :
466 0 : inline nscoord BCData::GetTopEdge(BCBorderOwner& aOwner,
467 : bool& aStart) const
468 : {
469 0 : aOwner = (BCBorderOwner)mTopOwner;
470 0 : aStart = (bool)mTopStart;
471 :
472 0 : return (nscoord)mTopSize;
473 : }
474 :
475 0 : inline void BCData::SetTopEdge(BCBorderOwner aOwner,
476 : nscoord aSize,
477 : bool aStart)
478 : {
479 0 : mTopOwner = aOwner;
480 0 : mTopSize = (aSize > MAX_BORDER_WIDTH) ? MAX_BORDER_WIDTH : aSize;
481 0 : mTopStart = aStart;
482 0 : }
483 :
484 0 : inline BCPixelSize BCData::GetCorner(mozilla::css::Side& aOwnerSide,
485 : bool& aBevel) const
486 : {
487 0 : aOwnerSide = mozilla::css::Side(mCornerSide);
488 0 : aBevel = (bool)mCornerBevel;
489 0 : return mCornerSubSize;
490 : }
491 :
492 0 : inline void BCData::SetCorner(BCPixelSize aSubSize,
493 : mozilla::css::Side aOwnerSide,
494 : bool aBevel)
495 : {
496 0 : mCornerSubSize = aSubSize;
497 0 : mCornerSide = aOwnerSide;
498 0 : mCornerBevel = aBevel;
499 0 : }
500 :
501 : inline bool BCData::IsLeftStart() const
502 : {
503 : return (bool)mLeftStart;
504 : }
505 :
506 : inline void BCData::SetLeftStart(bool aValue)
507 : {
508 : mLeftStart = aValue;
509 : }
510 :
511 0 : inline bool BCData::IsTopStart() const
512 : {
513 0 : return (bool)mTopStart;
514 : }
515 :
516 0 : inline void BCData::SetTopStart(bool aValue)
517 : {
518 0 : mTopStart = aValue;
519 0 : }
520 :
521 : #endif
|