1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/layout/tables/celldata.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,489 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 +#ifndef CellData_h__ 1.9 +#define CellData_h__ 1.10 + 1.11 +#include "nsISupports.h" 1.12 +#include "nsCoord.h" 1.13 +#include "mozilla/gfx/Types.h" 1.14 +#include <stdint.h> 1.15 + 1.16 +class nsTableCellFrame; 1.17 +class nsCellMap; 1.18 +class BCCellData; 1.19 + 1.20 + 1.21 +#define MAX_ROWSPAN 65534 // the cellmap can not handle more. 1.22 +#define MAX_COLSPAN 1000 // limit as IE and opera do. If this ever changes, 1.23 + // change COL_SPAN_OFFSET/COL_SPAN_SHIFT accordingly. 1.24 + 1.25 +/** 1.26 + * Data stored by nsCellMap to rationalize rowspan and colspan cells. 1.27 + */ 1.28 +class CellData 1.29 +{ 1.30 +public: 1.31 + /** Initialize the mOrigCell pointer 1.32 + * @param aOrigCell the table cell frame which will be stored in mOrigCell. 1.33 + */ 1.34 + void Init(nsTableCellFrame* aCellFrame); 1.35 + 1.36 + /** does a cell originate from here 1.37 + * @return is true if a cell corresponds to this cellmap entry 1.38 + */ 1.39 + bool IsOrig() const; 1.40 + 1.41 + /** is the celldata valid 1.42 + * @return is true if no cell originates and the cell is not spanned by 1.43 + * a row- or colspan. mBits are 0 in this case and mOrigCell is 1.44 + * nullptr 1.45 + */ 1.46 + bool IsDead() const; 1.47 + 1.48 + /** is the entry spanned by row- or a colspan 1.49 + * @return is true if the entry is spanned by a row- or colspan 1.50 + */ 1.51 + bool IsSpan() const; 1.52 + 1.53 + /** is the entry spanned by rowspan 1.54 + * @return is true if the entry is spanned by a rowspan 1.55 + */ 1.56 + bool IsRowSpan() const; 1.57 + 1.58 + /** is the entry spanned by a zero rowspan 1.59 + * zero rowspans span all cells starting from the originating cell down to 1.60 + * the end of the rowgroup or a cell originating in the same column 1.61 + * @return is true if the entry is spanned by a zero rowspan 1.62 + */ 1.63 + bool IsZeroRowSpan() const; 1.64 + 1.65 + /** mark the current entry as spanned by a zero rowspan 1.66 + * @param aIsZero if true mark the entry as covered by a zero rowspan 1.67 + */ 1.68 + void SetZeroRowSpan(bool aIsZero); 1.69 + 1.70 + /** get the distance from the current entry to the corresponding origin of the rowspan 1.71 + * @return containing the distance in the column to the originating cell 1.72 + */ 1.73 + uint32_t GetRowSpanOffset() const; 1.74 + 1.75 + /** set the distance from the current entry to the corresponding origin of the rowspan 1.76 + * @param the distance in the column to the originating cell 1.77 + */ 1.78 + void SetRowSpanOffset(uint32_t aSpan); 1.79 + 1.80 + /** is the entry spanned by colspan 1.81 + * @return is true if the entry is spanned by a colspan 1.82 + */ 1.83 + bool IsColSpan() const; 1.84 + 1.85 + /** is the entry spanned by a zero colspan 1.86 + * zero colspans span all cells starting from the originating cell towards 1.87 + * the end of the colgroup or a cell originating in the same row 1.88 + * or a rowspanned entry 1.89 + * @return is true if the entry is spanned by a zero colspan 1.90 + */ 1.91 + bool IsZeroColSpan() const; 1.92 + 1.93 + /** mark the current entry as spanned by a zero colspan 1.94 + * @param aIsZero if true mark the entry as covered by a zero colspan 1.95 + */ 1.96 + void SetZeroColSpan(bool aIsZero); 1.97 + 1.98 + /** get the distance from the current entry to the corresponding origin of the colspan 1.99 + * @return containing the distance in the row to the originating cell 1.100 + */ 1.101 + uint32_t GetColSpanOffset() const; 1.102 + 1.103 + /** set the distance from the current entry to the corresponding origin of the colspan 1.104 + * @param the distance in the column to the originating cell 1.105 + */ 1.106 + void SetColSpanOffset(uint32_t aSpan); 1.107 + 1.108 + /** is the entry spanned by a row- and a colspan 1.109 + * @return is true if the entry is spanned by a row- and a colspan 1.110 + */ 1.111 + bool IsOverlap() const; 1.112 + 1.113 + /** mark the current entry as spanned by a row- and a colspan 1.114 + * @param aOverlap if true mark the entry as covered by a row- and a colspan 1.115 + */ 1.116 + void SetOverlap(bool aOverlap); 1.117 + 1.118 + /** get the table cell frame for this entry 1.119 + * @return a pointer to the cellframe, this will be nullptr when the entry 1.120 + * is only a spanned entry 1.121 + */ 1.122 + nsTableCellFrame* GetCellFrame() const; 1.123 + 1.124 +private: 1.125 + friend class nsCellMap; 1.126 + friend class BCCellData; 1.127 + 1.128 + /** constructor. 1.129 + * @param aOrigCell the table cell frame which will be stored in mOrigCell. 1.130 + */ 1.131 + CellData(nsTableCellFrame* aOrigCell); // implemented in nsCellMap.cpp 1.132 + 1.133 + /** destructor */ 1.134 + ~CellData(); // implemented in nsCellMap.cpp 1.135 + 1.136 +protected: 1.137 + 1.138 + // this union relies on the assumption that an object (not primitive type) does 1.139 + // not start on an odd bit boundary. If mSpan is 0 then mOrigCell is in effect 1.140 + // and the data does not represent a span. If mSpan is 1, then mBits is in 1.141 + // effect and the data represents a span. 1.142 + // mBits must match the size of mOrigCell on both 32- and 64-bit platforms. 1.143 + union { 1.144 + nsTableCellFrame* mOrigCell; 1.145 + uintptr_t mBits; 1.146 + }; 1.147 +}; 1.148 + 1.149 +// Border Collapsing Cell Data 1.150 +enum BCBorderOwner 1.151 +{ 1.152 + eTableOwner = 0, 1.153 + eColGroupOwner = 1, 1.154 + eAjaColGroupOwner = 2, // col group to the left 1.155 + eColOwner = 3, 1.156 + eAjaColOwner = 4, // col to the left 1.157 + eRowGroupOwner = 5, 1.158 + eAjaRowGroupOwner = 6, // row group above 1.159 + eRowOwner = 7, 1.160 + eAjaRowOwner = 8, // row above 1.161 + eCellOwner = 9, 1.162 + eAjaCellOwner = 10 // cell to the top or to the left 1.163 +}; 1.164 + 1.165 +typedef uint16_t BCPixelSize; 1.166 + 1.167 +// These are the max sizes that are stored. If they are exceeded, then the max is stored and 1.168 +// the actual value is computed when needed. 1.169 +#define MAX_BORDER_WIDTH nscoord((1u << (sizeof(BCPixelSize) * 8)) - 1) 1.170 + 1.171 +static inline nscoord 1.172 +BC_BORDER_TOP_HALF_COORD(int32_t p2t, uint16_t px) { return (px - px / 2) * p2t; } 1.173 +static inline nscoord 1.174 +BC_BORDER_RIGHT_HALF_COORD(int32_t p2t, uint16_t px) { return ( px / 2) * p2t; } 1.175 +static inline nscoord 1.176 +BC_BORDER_BOTTOM_HALF_COORD(int32_t p2t, uint16_t px) { return ( px / 2) * p2t; } 1.177 +static inline nscoord 1.178 +BC_BORDER_LEFT_HALF_COORD(int32_t p2t, uint16_t px) { return (px - px / 2) * p2t; } 1.179 + 1.180 +#define BC_BORDER_TOP_HALF(px) ((px) - (px) / 2) 1.181 +#define BC_BORDER_RIGHT_HALF(px) ((px) / 2) 1.182 +#define BC_BORDER_BOTTOM_HALF(px) ((px) / 2) 1.183 +#define BC_BORDER_LEFT_HALF(px) ((px) - (px) / 2) 1.184 + 1.185 +// BCData stores the top and left border info and the corner connecting the two. 1.186 +class BCData 1.187 +{ 1.188 +public: 1.189 + BCData(); 1.190 + 1.191 + ~BCData(); 1.192 + 1.193 + nscoord GetLeftEdge(BCBorderOwner& aOwner, 1.194 + bool& aStart) const; 1.195 + 1.196 + void SetLeftEdge(BCBorderOwner aOwner, 1.197 + nscoord aSize, 1.198 + bool aStart); 1.199 + 1.200 + nscoord GetTopEdge(BCBorderOwner& aOwner, 1.201 + bool& aStart) const; 1.202 + 1.203 + void SetTopEdge(BCBorderOwner aOwner, 1.204 + nscoord aSize, 1.205 + bool aStart); 1.206 + 1.207 + BCPixelSize GetCorner(mozilla::css::Side& aCornerOwner, 1.208 + bool& aBevel) const; 1.209 + 1.210 + void SetCorner(BCPixelSize aSubSize, 1.211 + mozilla::css::Side aOwner, 1.212 + bool aBevel); 1.213 + 1.214 + bool IsLeftStart() const; 1.215 + 1.216 + void SetLeftStart(bool aValue); 1.217 + 1.218 + bool IsTopStart() const; 1.219 + 1.220 + void SetTopStart(bool aValue); 1.221 + 1.222 + 1.223 +protected: 1.224 + BCPixelSize mLeftSize; // size in pixels of left border 1.225 + BCPixelSize mTopSize; // size in pixels of top border 1.226 + BCPixelSize mCornerSubSize; // size of the largest border not in the 1.227 + // dominant plane (for example, if corner is 1.228 + // owned by the segment to its top or bottom, 1.229 + // then the size is the max of the border 1.230 + // sizes of the segments to its left or right. 1.231 + unsigned mLeftOwner: 4; // owner of left border 1.232 + unsigned mTopOwner: 4; // owner of top border 1.233 + unsigned mLeftStart: 1; // set if this is the start of a vertical border segment 1.234 + unsigned mTopStart: 1; // set if this is the start of a horizontal border segment 1.235 + unsigned mCornerSide: 2; // mozilla::css::Side of the owner of the upper left corner relative to the corner 1.236 + unsigned mCornerBevel: 1; // is the corner beveled (only two segments, perpendicular, not dashed or dotted). 1.237 +}; 1.238 + 1.239 +// BCCellData entries replace CellData entries in the cell map if the border collapsing model is in 1.240 +// effect. BCData for a row and col entry contains the left and top borders of cell at that row and 1.241 +// col and the corner connecting the two. The right borders of the cells in the last col and the bottom 1.242 +// borders of the last row are stored in separate BCData entries in the cell map. 1.243 +class BCCellData : public CellData 1.244 +{ 1.245 +public: 1.246 + BCCellData(nsTableCellFrame* aOrigCell); 1.247 + ~BCCellData(); 1.248 + 1.249 + BCData mData; 1.250 +}; 1.251 + 1.252 + 1.253 +// The layout of a celldata is as follows. The top 10 bits are the colspan 1.254 +// offset (which is enough to represent our allowed values 1-1000 for colspan). 1.255 +// Then there are three bits of flags. Then 16 bits of rowspan offset (which 1.256 +// lets us represent numbers up to 65535. Then another 3 bits of flags. 1.257 + 1.258 +// num bits to shift right to get right aligned col span 1.259 +#define COL_SPAN_SHIFT 22 1.260 +// num bits to shift right to get right aligned row span 1.261 +#define ROW_SPAN_SHIFT 3 1.262 + 1.263 +// the col offset to the data containing the original cell. 1.264 +#define COL_SPAN_OFFSET (0x3FF << COL_SPAN_SHIFT) 1.265 +// the row offset to the data containing the original cell 1.266 +#define ROW_SPAN_OFFSET (0xFFFF << ROW_SPAN_SHIFT) 1.267 + 1.268 +// And the flags 1.269 +#define SPAN 0x00000001 // there a row or col span 1.270 +#define ROW_SPAN 0x00000002 // there is a row span 1.271 +#define ROW_SPAN_0 0x00000004 // the row span is 0 1.272 +#define COL_SPAN (1 << (COL_SPAN_SHIFT - 3)) // there is a col span 1.273 +#define COL_SPAN_0 (1 << (COL_SPAN_SHIFT - 2)) // the col span is 0 1.274 +#define OVERLAP (1 << (COL_SPAN_SHIFT - 1)) // there is a row span and 1.275 + // col span but not by 1.276 + // same cell 1.277 + 1.278 +inline nsTableCellFrame* CellData::GetCellFrame() const 1.279 +{ 1.280 + if (SPAN != (SPAN & mBits)) { 1.281 + return mOrigCell; 1.282 + } 1.283 + return nullptr; 1.284 +} 1.285 + 1.286 +inline void CellData::Init(nsTableCellFrame* aCellFrame) 1.287 +{ 1.288 + mOrigCell = aCellFrame; 1.289 +} 1.290 + 1.291 +inline bool CellData::IsOrig() const 1.292 +{ 1.293 + return ((nullptr != mOrigCell) && (SPAN != (SPAN & mBits))); 1.294 +} 1.295 + 1.296 +inline bool CellData::IsDead() const 1.297 +{ 1.298 + return (0 == mBits); 1.299 +} 1.300 + 1.301 +inline bool CellData::IsSpan() const 1.302 +{ 1.303 + return (SPAN == (SPAN & mBits)); 1.304 +} 1.305 + 1.306 +inline bool CellData::IsRowSpan() const 1.307 +{ 1.308 + return (SPAN == (SPAN & mBits)) && 1.309 + (ROW_SPAN == (ROW_SPAN & mBits)); 1.310 +} 1.311 + 1.312 +inline bool CellData::IsZeroRowSpan() const 1.313 +{ 1.314 + return (SPAN == (SPAN & mBits)) && 1.315 + (ROW_SPAN == (ROW_SPAN & mBits)) && 1.316 + (ROW_SPAN_0 == (ROW_SPAN_0 & mBits)); 1.317 +} 1.318 + 1.319 +inline void CellData::SetZeroRowSpan(bool aIsZeroSpan) 1.320 +{ 1.321 + if (SPAN == (SPAN & mBits)) { 1.322 + if (aIsZeroSpan) { 1.323 + mBits |= ROW_SPAN_0; 1.324 + } 1.325 + else { 1.326 + mBits &= ~ROW_SPAN_0; 1.327 + } 1.328 + } 1.329 +} 1.330 + 1.331 +inline uint32_t CellData::GetRowSpanOffset() const 1.332 +{ 1.333 + if ((SPAN == (SPAN & mBits)) && ((ROW_SPAN == (ROW_SPAN & mBits)))) { 1.334 + return (uint32_t)((mBits & ROW_SPAN_OFFSET) >> ROW_SPAN_SHIFT); 1.335 + } 1.336 + return 0; 1.337 +} 1.338 + 1.339 +inline void CellData::SetRowSpanOffset(uint32_t aSpan) 1.340 +{ 1.341 + mBits &= ~ROW_SPAN_OFFSET; 1.342 + mBits |= (aSpan << ROW_SPAN_SHIFT); 1.343 + mBits |= SPAN; 1.344 + mBits |= ROW_SPAN; 1.345 +} 1.346 + 1.347 +inline bool CellData::IsColSpan() const 1.348 +{ 1.349 + return (SPAN == (SPAN & mBits)) && 1.350 + (COL_SPAN == (COL_SPAN & mBits)); 1.351 +} 1.352 + 1.353 +inline bool CellData::IsZeroColSpan() const 1.354 +{ 1.355 + return (SPAN == (SPAN & mBits)) && 1.356 + (COL_SPAN == (COL_SPAN & mBits)) && 1.357 + (COL_SPAN_0 == (COL_SPAN_0 & mBits)); 1.358 +} 1.359 + 1.360 +inline void CellData::SetZeroColSpan(bool aIsZeroSpan) 1.361 +{ 1.362 + if (SPAN == (SPAN & mBits)) { 1.363 + if (aIsZeroSpan) { 1.364 + mBits |= COL_SPAN_0; 1.365 + } 1.366 + else { 1.367 + mBits &= ~COL_SPAN_0; 1.368 + } 1.369 + } 1.370 +} 1.371 + 1.372 +inline uint32_t CellData::GetColSpanOffset() const 1.373 +{ 1.374 + if ((SPAN == (SPAN & mBits)) && ((COL_SPAN == (COL_SPAN & mBits)))) { 1.375 + return (uint32_t)((mBits & COL_SPAN_OFFSET) >> COL_SPAN_SHIFT); 1.376 + } 1.377 + return 0; 1.378 +} 1.379 + 1.380 +inline void CellData::SetColSpanOffset(uint32_t aSpan) 1.381 +{ 1.382 + mBits &= ~COL_SPAN_OFFSET; 1.383 + mBits |= (aSpan << COL_SPAN_SHIFT); 1.384 + 1.385 + mBits |= SPAN; 1.386 + mBits |= COL_SPAN; 1.387 +} 1.388 + 1.389 +inline bool CellData::IsOverlap() const 1.390 +{ 1.391 + return (SPAN == (SPAN & mBits)) && (OVERLAP == (OVERLAP & mBits)); 1.392 +} 1.393 + 1.394 +inline void CellData::SetOverlap(bool aOverlap) 1.395 +{ 1.396 + if (SPAN == (SPAN & mBits)) { 1.397 + if (aOverlap) { 1.398 + mBits |= OVERLAP; 1.399 + } 1.400 + else { 1.401 + mBits &= ~OVERLAP; 1.402 + } 1.403 + } 1.404 +} 1.405 + 1.406 +inline BCData::BCData() 1.407 +{ 1.408 + mLeftOwner = mTopOwner = eCellOwner; 1.409 + mLeftStart = mTopStart = 1; 1.410 + mLeftSize = mCornerSubSize = mTopSize = 0; 1.411 + mCornerSide = NS_SIDE_TOP; 1.412 + mCornerBevel = false; 1.413 +} 1.414 + 1.415 +inline BCData::~BCData() 1.416 +{ 1.417 +} 1.418 + 1.419 +inline nscoord BCData::GetLeftEdge(BCBorderOwner& aOwner, 1.420 + bool& aStart) const 1.421 +{ 1.422 + aOwner = (BCBorderOwner)mLeftOwner; 1.423 + aStart = (bool)mLeftStart; 1.424 + 1.425 + return (nscoord)mLeftSize; 1.426 +} 1.427 + 1.428 +inline void BCData::SetLeftEdge(BCBorderOwner aOwner, 1.429 + nscoord aSize, 1.430 + bool aStart) 1.431 +{ 1.432 + mLeftOwner = aOwner; 1.433 + mLeftSize = (aSize > MAX_BORDER_WIDTH) ? MAX_BORDER_WIDTH : aSize; 1.434 + mLeftStart = aStart; 1.435 +} 1.436 + 1.437 +inline nscoord BCData::GetTopEdge(BCBorderOwner& aOwner, 1.438 + bool& aStart) const 1.439 +{ 1.440 + aOwner = (BCBorderOwner)mTopOwner; 1.441 + aStart = (bool)mTopStart; 1.442 + 1.443 + return (nscoord)mTopSize; 1.444 +} 1.445 + 1.446 +inline void BCData::SetTopEdge(BCBorderOwner aOwner, 1.447 + nscoord aSize, 1.448 + bool aStart) 1.449 +{ 1.450 + mTopOwner = aOwner; 1.451 + mTopSize = (aSize > MAX_BORDER_WIDTH) ? MAX_BORDER_WIDTH : aSize; 1.452 + mTopStart = aStart; 1.453 +} 1.454 + 1.455 +inline BCPixelSize BCData::GetCorner(mozilla::css::Side& aOwnerSide, 1.456 + bool& aBevel) const 1.457 +{ 1.458 + aOwnerSide = mozilla::css::Side(mCornerSide); 1.459 + aBevel = (bool)mCornerBevel; 1.460 + return mCornerSubSize; 1.461 +} 1.462 + 1.463 +inline void BCData::SetCorner(BCPixelSize aSubSize, 1.464 + mozilla::css::Side aOwnerSide, 1.465 + bool aBevel) 1.466 +{ 1.467 + mCornerSubSize = aSubSize; 1.468 + mCornerSide = aOwnerSide; 1.469 + mCornerBevel = aBevel; 1.470 +} 1.471 + 1.472 +inline bool BCData::IsLeftStart() const 1.473 +{ 1.474 + return (bool)mLeftStart; 1.475 +} 1.476 + 1.477 +inline void BCData::SetLeftStart(bool aValue) 1.478 +{ 1.479 + mLeftStart = aValue; 1.480 +} 1.481 + 1.482 +inline bool BCData::IsTopStart() const 1.483 +{ 1.484 + return (bool)mTopStart; 1.485 +} 1.486 + 1.487 +inline void BCData::SetTopStart(bool aValue) 1.488 +{ 1.489 + mTopStart = aValue; 1.490 +} 1.491 + 1.492 +#endif