layout/tables/celldata.h

Fri, 16 Jan 2015 04:50:19 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 04:50:19 +0100
branch
TOR_BUG_9701
changeset 13
44a2da4a2ab2
permissions
-rw-r--r--

Replace accessor implementation with direct member state manipulation, by
request https://trac.torproject.org/projects/tor/ticket/9701#comment:32

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

mercurial