summaryrefslogtreecommitdiffstats
path: root/layout/tables/celldata.h
diff options
context:
space:
mode:
Diffstat (limited to 'layout/tables/celldata.h')
-rw-r--r--layout/tables/celldata.h459
1 files changed, 459 insertions, 0 deletions
diff --git a/layout/tables/celldata.h b/layout/tables/celldata.h
new file mode 100644
index 000000000..b744b5175
--- /dev/null
+++ b/layout/tables/celldata.h
@@ -0,0 +1,459 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifndef CellData_h__
+#define CellData_h__
+
+#include "nsISupports.h"
+#include "nsCoord.h"
+#include "mozilla/gfx/Types.h"
+#include "mozilla/WritingModes.h"
+#include <stdint.h>
+
+class nsTableCellFrame;
+class nsCellMap;
+class BCCellData;
+
+
+#define MAX_ROWSPAN 65534 // the cellmap can not handle more.
+#define MAX_COLSPAN 1000 // limit as IE and opera do. If this ever changes,
+ // change COL_SPAN_OFFSET/COL_SPAN_SHIFT accordingly.
+
+/**
+ * Data stored by nsCellMap to rationalize rowspan and colspan cells.
+ */
+class CellData
+{
+public:
+ /** Initialize the mOrigCell pointer
+ * @param aOrigCell the table cell frame which will be stored in mOrigCell.
+ */
+ void Init(nsTableCellFrame* aCellFrame);
+
+ /** does a cell originate from here
+ * @return is true if a cell corresponds to this cellmap entry
+ */
+ bool IsOrig() const;
+
+ /** is the celldata valid
+ * @return is true if no cell originates and the cell is not spanned by
+ * a row- or colspan. mBits are 0 in this case and mOrigCell is
+ * nullptr
+ */
+ bool IsDead() const;
+
+ /** is the entry spanned by row- or a colspan
+ * @return is true if the entry is spanned by a row- or colspan
+ */
+ bool IsSpan() const;
+
+ /** is the entry spanned by rowspan
+ * @return is true if the entry is spanned by a rowspan
+ */
+ bool IsRowSpan() const;
+
+ /** is the entry spanned by a zero rowspan
+ * zero rowspans span all cells starting from the originating cell down to
+ * the end of the rowgroup or a cell originating in the same column
+ * @return is true if the entry is spanned by a zero rowspan
+ */
+ bool IsZeroRowSpan() const;
+
+ /** mark the current entry as spanned by a zero rowspan
+ * @param aIsZero if true mark the entry as covered by a zero rowspan
+ */
+ void SetZeroRowSpan(bool aIsZero);
+
+ /** get the distance from the current entry to the corresponding origin of the rowspan
+ * @return containing the distance in the column to the originating cell
+ */
+ uint32_t GetRowSpanOffset() const;
+
+ /** set the distance from the current entry to the corresponding origin of the rowspan
+ * @param the distance in the column to the originating cell
+ */
+ void SetRowSpanOffset(uint32_t aSpan);
+
+ /** is the entry spanned by colspan
+ * @return is true if the entry is spanned by a colspan
+ */
+ bool IsColSpan() const;
+
+ /** get the distance from the current entry to the corresponding origin of the colspan
+ * @return containing the distance in the row to the originating cell
+ */
+ uint32_t GetColSpanOffset() const;
+
+ /** set the distance from the current entry to the corresponding origin of the colspan
+ * @param the distance in the column to the originating cell
+ */
+ void SetColSpanOffset(uint32_t aSpan);
+
+ /** is the entry spanned by a row- and a colspan
+ * @return is true if the entry is spanned by a row- and a colspan
+ */
+ bool IsOverlap() const;
+
+ /** mark the current entry as spanned by a row- and a colspan
+ * @param aOverlap if true mark the entry as covered by a row- and a colspan
+ */
+ void SetOverlap(bool aOverlap);
+
+ /** get the table cell frame for this entry
+ * @return a pointer to the cellframe, this will be nullptr when the entry
+ * is only a spanned entry
+ */
+ nsTableCellFrame* GetCellFrame() const;
+
+private:
+ friend class nsCellMap;
+ friend class BCCellData;
+
+ /** constructor.
+ * @param aOrigCell the table cell frame which will be stored in mOrigCell.
+ */
+ explicit CellData(nsTableCellFrame* aOrigCell); // implemented in nsCellMap.cpp
+
+ /** destructor */
+ ~CellData(); // implemented in nsCellMap.cpp
+
+protected:
+
+ // this union relies on the assumption that an object (not primitive type) does
+ // not start on an odd bit boundary. If mSpan is 0 then mOrigCell is in effect
+ // and the data does not represent a span. If mSpan is 1, then mBits is in
+ // effect and the data represents a span.
+ // mBits must match the size of mOrigCell on both 32- and 64-bit platforms.
+ union {
+ nsTableCellFrame* mOrigCell;
+ uintptr_t mBits;
+ };
+};
+
+// Border Collapsing Cell Data
+enum BCBorderOwner
+{
+ eTableOwner = 0,
+ eColGroupOwner = 1,
+ eAjaColGroupOwner = 2, // col group to the left
+ eColOwner = 3,
+ eAjaColOwner = 4, // col to the left
+ eRowGroupOwner = 5,
+ eAjaRowGroupOwner = 6, // row group above
+ eRowOwner = 7,
+ eAjaRowOwner = 8, // row above
+ eCellOwner = 9,
+ eAjaCellOwner = 10 // cell to the top or to the left
+};
+
+typedef uint16_t BCPixelSize;
+
+// These are the max sizes that are stored. If they are exceeded, then the max is stored and
+// the actual value is computed when needed.
+#define MAX_BORDER_WIDTH nscoord((1u << (sizeof(BCPixelSize) * 8)) - 1)
+
+// The half of border on inline/block-axis start side
+static inline BCPixelSize
+BC_BORDER_START_HALF(BCPixelSize px) { return px - px / 2; }
+// The half of border on inline/block-axis end side
+static inline BCPixelSize
+BC_BORDER_END_HALF(BCPixelSize px) { return px / 2; }
+
+static inline nscoord
+BC_BORDER_START_HALF_COORD(int32_t p2t, BCPixelSize px)
+ { return BC_BORDER_START_HALF(px) * p2t; }
+static inline nscoord
+BC_BORDER_END_HALF_COORD(int32_t p2t, BCPixelSize px)
+ { return BC_BORDER_END_HALF(px) * p2t; }
+
+// BCData stores the bstart and istart border info and the corner connecting the two.
+class BCData
+{
+public:
+ BCData();
+
+ ~BCData();
+
+ nscoord GetIStartEdge(BCBorderOwner& aOwner,
+ bool& aStart) const;
+
+ void SetIStartEdge(BCBorderOwner aOwner,
+ nscoord aSize,
+ bool aStart);
+
+ nscoord GetBStartEdge(BCBorderOwner& aOwner,
+ bool& aStart) const;
+
+ void SetBStartEdge(BCBorderOwner aOwner,
+ nscoord aSize,
+ bool aStart);
+
+ BCPixelSize GetCorner(mozilla::LogicalSide& aCornerOwner,
+ bool& aBevel) const;
+
+ void SetCorner(BCPixelSize aSubSize,
+ mozilla::LogicalSide aOwner,
+ bool aBevel);
+
+ bool IsIStartStart() const;
+
+ void SetIStartStart(bool aValue);
+
+ bool IsBStartStart() const;
+
+ void SetBStartStart(bool aValue);
+
+
+protected:
+ BCPixelSize mIStartSize; // size in pixels of iStart border
+ BCPixelSize mBStartSize; // size in pixels of bStart border
+ BCPixelSize mCornerSubSize; // size of the largest border not in the
+ // dominant plane (for example, if corner is
+ // owned by the segment to its bStart or bEnd,
+ // then the size is the max of the border
+ // sizes of the segments to its iStart or iEnd.
+ unsigned mIStartOwner: 4; // owner of iStart border
+ unsigned mBStartOwner: 4; // owner of bStart border
+ unsigned mIStartStart: 1; // set if this is the start of a block-dir border segment
+ unsigned mBStartStart: 1; // set if this is the start of an inline-dir border segment
+ unsigned mCornerSide: 2; // LogicalSide of the owner of the bStart-iStart corner relative to the corner
+ unsigned mCornerBevel: 1; // is the corner beveled (only two segments, perpendicular, not dashed or dotted).
+};
+
+// BCCellData entries replace CellData entries in the cell map if the border collapsing model is in
+// effect. BCData for a row and col entry contains the left and top borders of cell at that row and
+// col and the corner connecting the two. The right borders of the cells in the last col and the bottom
+// borders of the last row are stored in separate BCData entries in the cell map.
+class BCCellData : public CellData
+{
+public:
+ explicit BCCellData(nsTableCellFrame* aOrigCell);
+ ~BCCellData();
+
+ BCData mData;
+};
+
+
+// The layout of a celldata is as follows. The top 10 bits are the colspan
+// offset (which is enough to represent our allowed values 1-1000 for colspan).
+// Then there are two bits of flags.
+// XXXmats Then one unused bit that we should decide how to use in bug 862624.
+// Then 16 bits of rowspan offset (which
+// lets us represent numbers up to 65535. Then another 3 bits of flags.
+
+// num bits to shift right to get right aligned col span
+#define COL_SPAN_SHIFT 22
+// num bits to shift right to get right aligned row span
+#define ROW_SPAN_SHIFT 3
+
+// the col offset to the data containing the original cell.
+#define COL_SPAN_OFFSET (0x3FF << COL_SPAN_SHIFT)
+// the row offset to the data containing the original cell
+#define ROW_SPAN_OFFSET (0xFFFF << ROW_SPAN_SHIFT)
+
+// And the flags
+#define SPAN 0x00000001 // there a row or col span
+#define ROW_SPAN 0x00000002 // there is a row span
+#define ROW_SPAN_0 0x00000004 // the row span is 0
+#define COL_SPAN (1 << (COL_SPAN_SHIFT - 2)) // there is a col span
+#define OVERLAP (1 << (COL_SPAN_SHIFT - 1)) // there is a row span and
+ // col span but not by
+ // same cell
+
+inline nsTableCellFrame* CellData::GetCellFrame() const
+{
+ if (SPAN != (SPAN & mBits)) {
+ return mOrigCell;
+ }
+ return nullptr;
+}
+
+inline void CellData::Init(nsTableCellFrame* aCellFrame)
+{
+ mOrigCell = aCellFrame;
+}
+
+inline bool CellData::IsOrig() const
+{
+ return ((nullptr != mOrigCell) && (SPAN != (SPAN & mBits)));
+}
+
+inline bool CellData::IsDead() const
+{
+ return (0 == mBits);
+}
+
+inline bool CellData::IsSpan() const
+{
+ return (SPAN == (SPAN & mBits));
+}
+
+inline bool CellData::IsRowSpan() const
+{
+ return (SPAN == (SPAN & mBits)) &&
+ (ROW_SPAN == (ROW_SPAN & mBits));
+}
+
+inline bool CellData::IsZeroRowSpan() const
+{
+ return (SPAN == (SPAN & mBits)) &&
+ (ROW_SPAN == (ROW_SPAN & mBits)) &&
+ (ROW_SPAN_0 == (ROW_SPAN_0 & mBits));
+}
+
+inline void CellData::SetZeroRowSpan(bool aIsZeroSpan)
+{
+ if (SPAN == (SPAN & mBits)) {
+ if (aIsZeroSpan) {
+ mBits |= ROW_SPAN_0;
+ }
+ else {
+ mBits &= ~ROW_SPAN_0;
+ }
+ }
+}
+
+inline uint32_t CellData::GetRowSpanOffset() const
+{
+ if ((SPAN == (SPAN & mBits)) && ((ROW_SPAN == (ROW_SPAN & mBits)))) {
+ return (uint32_t)((mBits & ROW_SPAN_OFFSET) >> ROW_SPAN_SHIFT);
+ }
+ return 0;
+}
+
+inline void CellData::SetRowSpanOffset(uint32_t aSpan)
+{
+ mBits &= ~ROW_SPAN_OFFSET;
+ mBits |= (aSpan << ROW_SPAN_SHIFT);
+ mBits |= SPAN;
+ mBits |= ROW_SPAN;
+}
+
+inline bool CellData::IsColSpan() const
+{
+ return (SPAN == (SPAN & mBits)) &&
+ (COL_SPAN == (COL_SPAN & mBits));
+}
+
+inline uint32_t CellData::GetColSpanOffset() const
+{
+ if ((SPAN == (SPAN & mBits)) && ((COL_SPAN == (COL_SPAN & mBits)))) {
+ return (uint32_t)((mBits & COL_SPAN_OFFSET) >> COL_SPAN_SHIFT);
+ }
+ return 0;
+}
+
+inline void CellData::SetColSpanOffset(uint32_t aSpan)
+{
+ mBits &= ~COL_SPAN_OFFSET;
+ mBits |= (aSpan << COL_SPAN_SHIFT);
+
+ mBits |= SPAN;
+ mBits |= COL_SPAN;
+}
+
+inline bool CellData::IsOverlap() const
+{
+ return (SPAN == (SPAN & mBits)) && (OVERLAP == (OVERLAP & mBits));
+}
+
+inline void CellData::SetOverlap(bool aOverlap)
+{
+ if (SPAN == (SPAN & mBits)) {
+ if (aOverlap) {
+ mBits |= OVERLAP;
+ }
+ else {
+ mBits &= ~OVERLAP;
+ }
+ }
+}
+
+inline BCData::BCData()
+{
+ mIStartOwner = mBStartOwner = eCellOwner;
+ mIStartStart = mBStartStart = 1;
+ mIStartSize = mCornerSubSize = mBStartSize = 0;
+ mCornerSide = mozilla::eLogicalSideBStart;
+ mCornerBevel = false;
+}
+
+inline BCData::~BCData()
+{
+}
+
+inline nscoord BCData::GetIStartEdge(BCBorderOwner& aOwner,
+ bool& aStart) const
+{
+ aOwner = (BCBorderOwner)mIStartOwner;
+ aStart = (bool)mIStartStart;
+
+ return (nscoord)mIStartSize;
+}
+
+inline void BCData::SetIStartEdge(BCBorderOwner aOwner,
+ nscoord aSize,
+ bool aStart)
+{
+ mIStartOwner = aOwner;
+ mIStartSize = (aSize > MAX_BORDER_WIDTH) ? MAX_BORDER_WIDTH : aSize;
+ mIStartStart = aStart;
+}
+
+inline nscoord BCData::GetBStartEdge(BCBorderOwner& aOwner,
+ bool& aStart) const
+{
+ aOwner = (BCBorderOwner)mBStartOwner;
+ aStart = (bool)mBStartStart;
+
+ return (nscoord)mBStartSize;
+}
+
+inline void BCData::SetBStartEdge(BCBorderOwner aOwner,
+ nscoord aSize,
+ bool aStart)
+{
+ mBStartOwner = aOwner;
+ mBStartSize = (aSize > MAX_BORDER_WIDTH) ? MAX_BORDER_WIDTH : aSize;
+ mBStartStart = aStart;
+}
+
+inline BCPixelSize BCData::GetCorner(mozilla::LogicalSide& aOwnerSide,
+ bool& aBevel) const
+{
+ aOwnerSide = mozilla::LogicalSide(mCornerSide);
+ aBevel = (bool)mCornerBevel;
+ return mCornerSubSize;
+}
+
+inline void BCData::SetCorner(BCPixelSize aSubSize,
+ mozilla::LogicalSide aOwnerSide,
+ bool aBevel)
+{
+ mCornerSubSize = aSubSize;
+ mCornerSide = aOwnerSide;
+ mCornerBevel = aBevel;
+}
+
+inline bool BCData::IsIStartStart() const
+{
+ return (bool)mIStartStart;
+}
+
+inline void BCData::SetIStartStart(bool aValue)
+{
+ mIStartStart = aValue;
+}
+
+inline bool BCData::IsBStartStart() const
+{
+ return (bool)mBStartStart;
+}
+
+inline void BCData::SetBStartStart(bool aValue)
+{
+ mBStartStart = aValue;
+}
+
+#endif