Bug 1159990 - Add TableArea struct and replace nsIntRect with it for table damage area. r=roc
authorXidorn Quan <quanxunzhen@gmail.com>
Fri, 01 May 2015 09:46:59 +1200
changeset 273306 e42e4e3139c5ae9fd2ca373819e327d4a5a6d051
parent 273305 796c77a8118b0ab5b4a5361780fea1ff3c09366a
child 273307 7d4feaf04bcabbdbbf5e03ae6ef671929377cd6b
push id863
push userraliiev@mozilla.com
push dateMon, 03 Aug 2015 13:22:43 +0000
treeherdermozilla-release@f6321b14228d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs1159990
milestone40.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1159990 - Add TableArea struct and replace nsIntRect with it for table damage area. r=roc
layout/tables/TableArea.h
layout/tables/nsCellMap.cpp
layout/tables/nsCellMap.h
layout/tables/nsTableCellFrame.cpp
layout/tables/nsTableColFrame.cpp
layout/tables/nsTableColGroupFrame.cpp
layout/tables/nsTableFrame.cpp
layout/tables/nsTableFrame.h
layout/tables/nsTableRowFrame.cpp
layout/tables/nsTableRowGroupFrame.cpp
new file mode 100644
--- /dev/null
+++ b/layout/tables/TableArea.h
@@ -0,0 +1,41 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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 mozilla_TableArea_h_
+#define mozilla_TableArea_h_
+
+#include "nsRect.h"
+
+namespace mozilla {
+
+struct TableArea
+{
+  TableArea() : mRect() { }
+  TableArea(int32_t aStartCol, int32_t aStartRow,
+            int32_t aColCount, int32_t aRowCount)
+    : mRect(aStartCol, aStartRow, aColCount, aRowCount) { }
+
+  int32_t& StartCol() { return mRect.x; }
+  int32_t& StartRow() { return mRect.y; }
+  int32_t& ColCount() { return mRect.width; }
+  int32_t& RowCount() { return mRect.height; }
+
+  int32_t StartCol() const { return mRect.x; }
+  int32_t StartRow() const { return mRect.y; }
+  int32_t ColCount() const { return mRect.width; }
+  int32_t RowCount() const { return mRect.height; }
+  int32_t EndCol() const { return mRect.XMost(); }
+  int32_t EndRow() const { return mRect.YMost(); }
+
+  void UnionArea(const TableArea& aArea1, const TableArea& aArea2)
+    { mRect.UnionRect(aArea1.mRect, aArea2.mRect); }
+
+private:
+  nsIntRect mRect;
+};
+
+}
+
+#endif // mozilla_TableArea_h_
--- a/layout/tables/nsCellMap.cpp
+++ b/layout/tables/nsCellMap.cpp
@@ -6,32 +6,33 @@
 #include "nsTArray.h"
 #include "nsCellMap.h"
 #include "nsTableFrame.h"
 #include "nsTableCellFrame.h"
 #include "nsTableRowFrame.h"
 #include "nsTableRowGroupFrame.h"
 #include <algorithm>
 
+using namespace mozilla;
 
 static void
-SetDamageArea(int32_t aXOrigin,
-              int32_t aYOrigin,
-              int32_t aWidth,
-              int32_t aHeight,
-              nsIntRect& aDamageArea)
+SetDamageArea(int32_t aStartCol,
+              int32_t aStartRow,
+              int32_t aColCount,
+              int32_t aRowCount,
+              TableArea& aDamageArea)
 {
-  NS_ASSERTION(aXOrigin >= 0, "negative col index");
-  NS_ASSERTION(aYOrigin >= 0, "negative row index");
-  NS_ASSERTION(aWidth >= 0, "negative horizontal damage");
-  NS_ASSERTION(aHeight >= 0, "negative vertical damage");
-  aDamageArea.x      = aXOrigin;
-  aDamageArea.y      = aYOrigin;
-  aDamageArea.width  = aWidth;
-  aDamageArea.height = aHeight;
+  NS_ASSERTION(aStartCol >= 0, "negative col index");
+  NS_ASSERTION(aStartRow >= 0, "negative row index");
+  NS_ASSERTION(aColCount >= 0, "negative col count");
+  NS_ASSERTION(aRowCount >= 0, "negative row count");
+  aDamageArea.StartCol() = aStartCol;
+  aDamageArea.StartRow() = aStartRow;
+  aDamageArea.ColCount() = aColCount;
+  aDamageArea.RowCount() = aRowCount;
 }
 
 // Empty static array used for SafeElementAt() calls on mRows.
 static nsCellMap::CellDataArray * sEmptyRow;
 
 // CellData
 
 CellData::CellData(nsTableCellFrame* aOrigCell)
@@ -461,17 +462,17 @@ nsTableCellMap::ClearCols()
   if (mBCInfo)
     mBCInfo->mBottomBorders.Clear();
 }
 void
 nsTableCellMap::InsertRows(nsTableRowGroupFrame*       aParent,
                            nsTArray<nsTableRowFrame*>& aRows,
                            int32_t                     aFirstRowIndex,
                            bool                        aConsiderSpans,
-                           nsIntRect&                  aDamageArea)
+                           TableArea&                  aDamageArea)
 {
   int32_t numNewRows = aRows.Length();
   if ((numNewRows <= 0) || (aFirstRowIndex < 0)) ABORT0();
 
   int32_t rowIndex = aFirstRowIndex;
   int32_t rgStartRowIndex = 0;
   nsCellMap* cellMap = mFirstMap;
   while (cellMap) {
@@ -506,17 +507,17 @@ nsTableCellMap::InsertRows(nsTableRowGro
 
   NS_ERROR("Attempt to insert row into wrong map.");
 }
 
 void
 nsTableCellMap::RemoveRows(int32_t         aFirstRowIndex,
                            int32_t         aNumRowsToRemove,
                            bool            aConsiderSpans,
-                           nsIntRect&      aDamageArea)
+                           TableArea&      aDamageArea)
 {
   int32_t rowIndex = aFirstRowIndex;
   int32_t rgStartRowIndex = 0;
   nsCellMap* cellMap = mFirstMap;
   while (cellMap) {
     int32_t rowCount = cellMap->GetRowCount();
     if (rowCount > rowIndex) {
       cellMap->RemoveRows(*this, rowIndex, aNumRowsToRemove, aConsiderSpans,
@@ -540,17 +541,17 @@ nsTableCellMap::RemoveRows(int32_t      
 }
 
 
 
 CellData*
 nsTableCellMap::AppendCell(nsTableCellFrame& aCellFrame,
                            int32_t           aRowIndex,
                            bool              aRebuildIfNecessary,
-                           nsIntRect&        aDamageArea)
+                           TableArea&        aDamageArea)
 {
   MOZ_ASSERT(&aCellFrame == aCellFrame.FirstInFlow(),
              "invalid call on continuing frame");
   nsIFrame* rgFrame = aCellFrame.GetParent(); // get the row
   if (!rgFrame) return 0;
   rgFrame = rgFrame->GetParent();   // get the row group
   if (!rgFrame) return 0;
 
@@ -576,17 +577,17 @@ nsTableCellMap::AppendCell(nsTableCellFr
   return result;
 }
 
 
 void
 nsTableCellMap::InsertCells(nsTArray<nsTableCellFrame*>& aCellFrames,
                             int32_t                      aRowIndex,
                             int32_t                      aColIndexBefore,
-                            nsIntRect&                   aDamageArea)
+                            TableArea&                   aDamageArea)
 {
   int32_t rowIndex = aRowIndex;
   int32_t rgStartRowIndex = 0;
   nsCellMap* cellMap = mFirstMap;
   while (cellMap) {
     int32_t rowCount = cellMap->GetRowCount();
     if (rowCount > rowIndex) {
       cellMap->InsertCells(*this, aCellFrames, rowIndex, aColIndexBefore,
@@ -601,17 +602,17 @@ nsTableCellMap::InsertCells(nsTArray<nsT
   Dump("after InsertCells");
 #endif
 }
 
 
 void
 nsTableCellMap::RemoveCell(nsTableCellFrame* aCellFrame,
                            int32_t           aRowIndex,
-                           nsIntRect&        aDamageArea)
+                           TableArea&        aDamageArea)
 {
   if (!aCellFrame) ABORT0();
   MOZ_ASSERT(aCellFrame == aCellFrame->FirstInFlow(),
              "invalid call on continuing frame");
   int32_t rowIndex = aRowIndex;
   int32_t rgStartRowIndex = 0;
   nsCellMap* cellMap = mFirstMap;
   while (cellMap) {
@@ -636,17 +637,17 @@ nsTableCellMap::RemoveCell(nsTableCellFr
 }
 
 void
 nsTableCellMap::RebuildConsideringCells(nsCellMap*                   aCellMap,
                                         nsTArray<nsTableCellFrame*>* aCellFrames,
                                         int32_t                      aRowIndex,
                                         int32_t                      aColIndex,
                                         bool                         aInsert,
-                                        nsIntRect&                   aDamageArea)
+                                        TableArea&                   aDamageArea)
 {
   int32_t numOrigCols = GetColCount();
   ClearCols();
   nsCellMap* cellMap = mFirstMap;
   int32_t rowCount = 0;
   while (cellMap) {
     if (cellMap == aCellMap) {
       cellMap->RebuildConsideringCells(*this, numOrigCols, aCellFrames,
@@ -662,17 +663,17 @@ nsTableCellMap::RebuildConsideringCells(
   SetDamageArea(0, 0, GetColCount(), rowCount, aDamageArea);
 }
 
 void
 nsTableCellMap::RebuildConsideringRows(nsCellMap*                  aCellMap,
                                        int32_t                     aStartRowIndex,
                                        nsTArray<nsTableRowFrame*>* aRowsToInsert,
                                        int32_t                     aNumRowsToRemove,
-                                       nsIntRect&                  aDamageArea)
+                                       TableArea&                  aDamageArea)
 {
   NS_PRECONDITION(!aRowsToInsert || aNumRowsToRemove == 0,
                   "Can't handle both removing and inserting rows at once");
 
   int32_t numOrigCols = GetColCount();
   ClearCols();
   nsCellMap* cellMap = mFirstMap;
   int32_t rowCount = 0;
@@ -997,32 +998,32 @@ nsTableCellMap::SetBCBorderEdge(mozilla:
     lastIndex = xPos + aLength - 1;
     for (xIndex = xPos; xIndex <= lastIndex; xIndex++) {
       changed = aChanged && (xIndex == xPos);
       BCData* bcData = nullptr;
       cellData = (BCCellData*)aCellMap.GetDataAt(rgYPos, xIndex);
       if (!cellData) {
         int32_t numRgRows = aCellMap.GetRowCount();
         if (yPos < numRgRows) { // add a dead cell data
-          nsIntRect damageArea;
+          TableArea damageArea;
           cellData = (BCCellData*)aCellMap.AppendCell(*this, nullptr, rgYPos,
                                                        false, 0, damageArea);
           if (!cellData) ABORT0();
         }
         else {
           NS_ASSERTION(aSide == NS_SIDE_BOTTOM, "program error");
           // try the next non empty row group
           nsCellMap* cellMap = aCellMap.GetNextSibling();
           while (cellMap && (0 == cellMap->GetRowCount())) {
             cellMap = cellMap->GetNextSibling();
           }
           if (cellMap) {
             cellData = (BCCellData*)cellMap->GetDataAt(0, xIndex);
             if (!cellData) { // add a dead cell
-              nsIntRect damageArea;
+              TableArea damageArea;
               cellData = (BCCellData*)cellMap->AppendCell(*this, nullptr, 0,
                                                            false, 0,
                                                            damageArea);
             }
           }
           else { // must be at the end of the table
             bcData = GetBottomMostBorder(xIndex);
           }
@@ -1107,30 +1108,30 @@ nsTableCellMap::SetBCBorderCorner(Corner
     NS_ASSERTION(!aIsBottomRight, "should be handled before");
     bcData = GetRightMostBorder(yPos);
   }
   else {
     cellData = (BCCellData*)aCellMap.GetDataAt(rgYPos, xPos);
     if (!cellData) {
       int32_t numRgRows = aCellMap.GetRowCount();
       if (yPos < numRgRows) { // add a dead cell data
-        nsIntRect damageArea;
+        TableArea damageArea;
         cellData = (BCCellData*)aCellMap.AppendCell(*this, nullptr, rgYPos,
                                                      false, 0, damageArea);
       }
       else {
         // try the next non empty row group
         nsCellMap* cellMap = aCellMap.GetNextSibling();
         while (cellMap && (0 == cellMap->GetRowCount())) {
           cellMap = cellMap->GetNextSibling();
         }
         if (cellMap) {
           cellData = (BCCellData*)cellMap->GetDataAt(0, xPos);
           if (!cellData) { // add a dead cell
-            nsIntRect damageArea;
+            TableArea damageArea;
             cellData = (BCCellData*)cellMap->AppendCell(*this, nullptr, 0,
                                                          false, 0, damageArea);
           }
         }
         else { // must be at the bottom of the table
           bcData = GetBottomMostBorder(xPos);
         }
       }
@@ -1327,17 +1328,17 @@ void nsCellMap::GrowRow(CellDataArray& a
 }
 
 void
 nsCellMap::InsertRows(nsTableCellMap&             aMap,
                       nsTArray<nsTableRowFrame*>& aRows,
                       int32_t                     aFirstRowIndex,
                       bool                        aConsiderSpans,
                       int32_t                     aRgFirstRowIndex,
-                      nsIntRect&                  aDamageArea)
+                      TableArea&                  aDamageArea)
 {
   int32_t numCols = aMap.GetColCount();
   NS_ASSERTION(aFirstRowIndex >= 0, "nsCellMap::InsertRows called with negative rowIndex");
   if (uint32_t(aFirstRowIndex) > mRows.Length()) {
     // create (aFirstRowIndex - mRows.Length()) empty rows up to aFirstRowIndex
     int32_t numEmptyRows = aFirstRowIndex - mRows.Length();
     if (!Grow(aMap, numEmptyRows)) {
       return;
@@ -1372,17 +1373,17 @@ nsCellMap::InsertRows(nsTableCellMap&   
 }
 
 void
 nsCellMap::RemoveRows(nsTableCellMap& aMap,
                       int32_t         aFirstRowIndex,
                       int32_t         aNumRowsToRemove,
                       bool            aConsiderSpans,
                       int32_t         aRgFirstRowIndex,
-                      nsIntRect&      aDamageArea)
+                      TableArea&      aDamageArea)
 {
   int32_t numRows = mRows.Length();
   int32_t numCols = aMap.GetColCount();
 
   if (aFirstRowIndex >= numRows) {
     // reduce the content based row count based on the function arguments
     // as they are known to be real rows even if the cell map did not create
     // rows for them before.
@@ -1415,17 +1416,17 @@ nsCellMap::RemoveRows(nsTableCellMap& aM
 
 
 CellData*
 nsCellMap::AppendCell(nsTableCellMap&   aMap,
                       nsTableCellFrame* aCellFrame,
                       int32_t           aRowIndex,
                       bool              aRebuildIfNecessary,
                       int32_t           aRgFirstRowIndex,
-                      nsIntRect&        aDamageArea,
+                      TableArea&        aDamageArea,
                       int32_t*          aColToBeginSearch)
 {
   NS_ASSERTION(!!aMap.mBCInfo == mIsBC, "BC state mismatch");
   int32_t origNumMapRows = mRows.Length();
   int32_t origNumCols = aMap.GetColCount();
   bool    zeroRowSpan = false;
   int32_t rowSpan = (aCellFrame) ? GetRowSpanForNewCell(aCellFrame, aRowIndex,
                                                         zeroRowSpan) : 1;
@@ -1725,17 +1726,17 @@ bool nsCellMap::CellsSpanInOrOut(int32_t
   return false;
 }
 
 void nsCellMap::InsertCells(nsTableCellMap&              aMap,
                             nsTArray<nsTableCellFrame*>& aCellFrames,
                             int32_t                      aRowIndex,
                             int32_t                      aColIndexBefore,
                             int32_t                      aRgFirstRowIndex,
-                            nsIntRect&                   aDamageArea)
+                            TableArea&                   aDamageArea)
 {
   if (aCellFrames.Length() == 0) return;
   NS_ASSERTION(aColIndexBefore >= -1, "index out of range");
   int32_t numCols = aMap.GetColCount();
   if (aColIndexBefore >= numCols) {
     NS_ERROR("Inserting instead of appending cells indicates a serious cellmap error");
     aColIndexBefore = numCols - 1;
   }
@@ -1796,17 +1797,17 @@ void nsCellMap::InsertCells(nsTableCellM
   }
 }
 
 void
 nsCellMap::ExpandWithRows(nsTableCellMap&             aMap,
                           nsTArray<nsTableRowFrame*>& aRowFrames,
                           int32_t                     aStartRowIndexIn,
                           int32_t                     aRgFirstRowIndex,
-                          nsIntRect&                  aDamageArea)
+                          TableArea&                  aDamageArea)
 {
   int32_t startRowIndex = (aStartRowIndexIn >= 0) ? aStartRowIndexIn : 0;
   NS_ASSERTION(uint32_t(startRowIndex) <= mRows.Length(), "caller should have grown cellmap before");
 
   int32_t numNewRows  = aRowFrames.Length();
   mContentRowCount += numNewRows;
 
   int32_t endRowIndex = startRowIndex + numNewRows - 1;
@@ -1843,17 +1844,17 @@ nsCellMap::ExpandWithRows(nsTableCellMap
 
 void nsCellMap::ExpandWithCells(nsTableCellMap&              aMap,
                                 nsTArray<nsTableCellFrame*>& aCellFrames,
                                 int32_t                      aRowIndex,
                                 int32_t                      aColIndex,
                                 int32_t                      aRowSpan, // same for all cells
                                 bool                         aRowSpanIsZero,
                                 int32_t                      aRgFirstRowIndex,
-                                nsIntRect&                   aDamageArea)
+                                TableArea&                   aDamageArea)
 {
   NS_ASSERTION(!!aMap.mBCInfo == mIsBC, "BC state mismatch");
   int32_t endRowIndex = aRowIndex + aRowSpan - 1;
   int32_t startColIndex = aColIndex;
   int32_t endColIndex = aColIndex;
   int32_t numCells = aCellFrames.Length();
   int32_t totalColSpan = 0;
 
@@ -1963,17 +1964,17 @@ void nsCellMap::ExpandWithCells(nsTableC
     }
   }
 }
 
 void nsCellMap::ShrinkWithoutRows(nsTableCellMap& aMap,
                                   int32_t         aStartRowIndex,
                                   int32_t         aNumRowsToRemove,
                                   int32_t         aRgFirstRowIndex,
-                                  nsIntRect&      aDamageArea)
+                                  TableArea&      aDamageArea)
 {
   NS_ASSERTION(!!aMap.mBCInfo == mIsBC, "BC state mismatch");
   int32_t endRowIndex = aStartRowIndex + aNumRowsToRemove - 1;
   uint32_t colCount = aMap.GetColCount();
   for (int32_t rowX = endRowIndex; rowX >= aStartRowIndex; --rowX) {
     CellDataArray& row = mRows[rowX];
     uint32_t colX;
     for (colX = 0; colX < colCount; colX++) {
@@ -2143,17 +2144,17 @@ int32_t nsCellMap::GetRowSpan(int32_t  a
   return rowSpan;
 }
 
 void nsCellMap::ShrinkWithoutCell(nsTableCellMap&   aMap,
                                   nsTableCellFrame& aCellFrame,
                                   int32_t           aRowIndex,
                                   int32_t           aColIndex,
                                   int32_t           aRgFirstRowIndex,
-                                  nsIntRect&        aDamageArea)
+                                  TableArea&        aDamageArea)
 {
   NS_ASSERTION(!!aMap.mBCInfo == mIsBC, "BC state mismatch");
   uint32_t colX, rowX;
 
   // get the rowspan and colspan from the cell map since the content may have changed
   bool zeroColSpan;
   uint32_t numCols = aMap.GetColCount();
   int32_t rowSpan = GetRowSpan(aRowIndex, aColIndex, true);
@@ -2268,17 +2269,17 @@ nsCellMap::RebuildConsideringRows(nsTabl
 
   // aStartRowIndex might be after all existing rows so we should limit the
   // copy to the amount of exisiting rows
   uint32_t copyEndRowIndex = std::min(numOrigRows, uint32_t(aStartRowIndex));
 
   // rowX keeps track of where we are in mRows while setting up the
   // new cellmap.
   uint32_t rowX = 0;
-  nsIntRect damageArea;
+  TableArea damageArea;
   // put back the rows before the affected ones just as before.  Note that we
   // can't just copy the old rows in bit-for-bit, because they might be
   // spanning out into the rows we're adding/removing.
   for ( ; rowX < copyEndRowIndex; rowX++) {
     const CellDataArray& row = origRows[rowX];
     uint32_t numCols = row.Length();
     for (uint32_t colX = 0; colX < numCols; colX++) {
       // put in the original cell from the cell map
@@ -2358,17 +2359,17 @@ nsCellMap::RebuildConsideringCells(nsTab
 
   // the new cells might extend the previous column number
   NS_ASSERTION(aNumOrigCols >= aColIndex, "Appending cells far beyond cellmap data?!");
   int32_t numCols = aInsert ? std::max(aNumOrigCols, aColIndex + 1) : aNumOrigCols;
 
   // build the new cell map.  Hard to say what, if anything, we can preallocate
   // here...  Should come back to that sometime, perhaps.
   int32_t rowX;
-  nsIntRect damageArea;
+  TableArea damageArea;
   for (rowX = 0; rowX < numOrigRows; rowX++) {
     const CellDataArray& row = origRows[rowX];
     for (int32_t colX = 0; colX < numCols; colX++) {
       if ((rowX == aRowIndex) && (colX == aColIndex)) {
         if (aInsert) { // put in the new cells
           for (int32_t cellX = 0; cellX < numNewCells; cellX++) {
             nsTableCellFrame* cell = aCellFrames->ElementAt(cellX);
             if (cell) {
@@ -2411,17 +2412,17 @@ nsCellMap::RebuildConsideringCells(nsTab
   }
 
 }
 
 void nsCellMap::RemoveCell(nsTableCellMap&   aMap,
                            nsTableCellFrame* aCellFrame,
                            int32_t           aRowIndex,
                            int32_t           aRgFirstRowIndex,
-                           nsIntRect&        aDamageArea)
+                           TableArea&        aDamageArea)
 {
   uint32_t numRows = mRows.Length();
   if (uint32_t(aRowIndex) >= numRows) {
     NS_ERROR("bad arg in nsCellMap::RemoveCell");
     return;
   }
   int32_t numCols = aMap.GetColCount();
 
--- a/layout/tables/nsCellMap.h
+++ b/layout/tables/nsCellMap.h
@@ -9,16 +9,17 @@
 #include "celldata.h"
 #include "nsTArray.h"
 #include "nsTArray.h"
 #include "nsCOMPtr.h"
 #include "nsAlgorithm.h"
 #include "nsAutoPtr.h"
 #include "nsRect.h"
 #include <algorithm>
+#include "TableArea.h"
 
 #undef DEBUG_TABLE_CELLMAP
 
 class nsTableCellFrame;
 class nsTableRowFrame;
 class nsTableRowGroupFrame;
 class nsTableFrame;
 class nsCellMap;
@@ -47,16 +48,18 @@ struct BCInfo
 {
   nsTArray<BCData> mRightBorders;
   nsTArray<BCData> mBottomBorders;
   BCData           mLowerRightCorner;
 };
 
 class nsTableCellMap
 {
+  typedef mozilla::TableArea TableArea;
+
 public:
   nsTableCellMap(nsTableFrame&   aTableFrame,
                  bool            aBorderCollapse);
 
   /** destructor
     * NOT VIRTUAL BECAUSE THIS CLASS SHOULD **NEVER** BE SUBCLASSED
     */
   ~nsTableCellMap();
@@ -92,38 +95,38 @@ public:
   // this function creates a col if needed
   nsColInfo* GetColInfoAt(int32_t aColIndex);
 
   /** append the cellFrame at the end of the row at aRowIndex and return the col index
     */
   CellData* AppendCell(nsTableCellFrame&     aCellFrame,
                        int32_t               aRowIndex,
                        bool                  aRebuildIfNecessary,
-                       nsIntRect&            aDamageArea);
+                       TableArea&            aDamageArea);
 
   void InsertCells(nsTArray<nsTableCellFrame*>& aCellFrames,
                    int32_t                      aRowIndex,
                    int32_t                      aColIndexBefore,
-                   nsIntRect&                   aDamageArea);
+                   TableArea&                   aDamageArea);
 
   void RemoveCell(nsTableCellFrame* aCellFrame,
                   int32_t           aRowIndex,
-                  nsIntRect&        aDamageArea);
+                  TableArea&        aDamageArea);
   /** Remove the previously gathered column information */
   void ClearCols();
   void InsertRows(nsTableRowGroupFrame*       aRowGroup,
                   nsTArray<nsTableRowFrame*>& aRows,
                   int32_t                     aFirstRowIndex,
                   bool                        aConsiderSpans,
-                  nsIntRect&                  aDamageArea);
+                  TableArea&                  aDamageArea);
 
   void RemoveRows(int32_t         aFirstRowIndex,
                   int32_t         aNumRowsToRemove,
                   bool            aConsiderSpans,
-                  nsIntRect&      aDamageArea);
+                  TableArea&      aDamageArea);
 
   int32_t GetNumCellsOriginatingInRow(int32_t aRowIndex) const;
   int32_t GetNumCellsOriginatingInCol(int32_t aColIndex) const;
 
   /** indicate whether the row has more than one cell that either originates
     * or is spanned from the rows above
     */
   bool HasMoreThanOneCell(int32_t aRowIndex) const;
@@ -172,32 +175,32 @@ public:
 
   bool RowIsSpannedInto(int32_t aRowIndex, int32_t aNumEffCols) const;
   bool RowHasSpanningCells(int32_t aRowIndex, int32_t aNumEffCols) const;
   void RebuildConsideringCells(nsCellMap*                   aCellMap,
                                nsTArray<nsTableCellFrame*>* aCellFrames,
                                int32_t                      aRowIndex,
                                int32_t                      aColIndex,
                                bool                         aInsert,
-                               nsIntRect&                   aDamageArea);
+                               TableArea&                   aDamageArea);
 
 protected:
   /**
    * Rebuild due to rows being inserted or deleted with cells spanning
    * into or out of the rows.  This function can only handle insertion
    * or deletion but NOT both.  So either aRowsToInsert must be null
    * or aNumRowsToRemove must be 0.
    *
    * // XXXbz are both allowed to happen?  That'd be a no-op...
    */
   void RebuildConsideringRows(nsCellMap*                  aCellMap,
                               int32_t                     aStartRowIndex,
                               nsTArray<nsTableRowFrame*>* aRowsToInsert,
                               int32_t                     aNumRowsToRemove,
-                              nsIntRect&                  aDamageArea);
+                              TableArea&                  aDamageArea);
 
 public:
   void ExpandZeroColSpans();
 
   void ResetTopStart(uint8_t    aSide,
                      nsCellMap& aCellMap,
                      uint32_t   aYPos,
                      uint32_t   aXPos,
@@ -262,16 +265,18 @@ protected:
   * @see nsTableFrame::GrowCellMap
   * @see nsTableFrame::BuildCellIntoMap
   *
   * mRows is an array of rows.  Each row is an array of cells.  a cell
   * can be null.
   */
 class nsCellMap
 {
+  typedef mozilla::TableArea TableArea;
+
 public:
   /** constructor
     * @param aRowGroupFrame the row group frame this is a cellmap for
     * @param aIsBC whether the table is doing border-collapse
     */
   nsCellMap(nsTableRowGroupFrame* aRowGroupFrame, bool aIsBC);
 
   /** destructor
@@ -342,17 +347,17 @@ public:
     * @return                   - a pointer to the celldata entry inserted into
     *                             the cellmap
     */
   CellData* AppendCell(nsTableCellMap&   aMap,
                        nsTableCellFrame* aCellFrame,
                        int32_t           aRowIndex,
                        bool              aRebuildIfNecessary,
                        int32_t           aRgFirstRowIndex,
-                       nsIntRect&        aDamageArea,
+                       TableArea&        aDamageArea,
                        int32_t*          aBeginSearchAtCol = nullptr);
 
   /** Function to be called when a cell is added at a location which is spanned
     * to by a zero colspan.  We handle this situation by collapsing the zero
     * colspan, since there is really no good way to deal with it (trying to
     * increase the number of columns to hold the new cell would just mean the
     * zero colspan needs to expand).
 
@@ -366,37 +371,37 @@ public:
                            int32_t         aRowIndex,
                            int32_t         aColIndex);
 
   void InsertCells(nsTableCellMap&              aMap,
                    nsTArray<nsTableCellFrame*>& aCellFrames,
                    int32_t                      aRowIndex,
                    int32_t                      aColIndexBefore,
                    int32_t                      aRgFirstRowIndex,
-                   nsIntRect&                   aDamageArea);
+                   TableArea&                   aDamageArea);
 
   void RemoveCell(nsTableCellMap&   aMap,
                   nsTableCellFrame* aCellFrame,
                   int32_t           aRowIndex,
                   int32_t           aRgFirstRowIndex,
-                  nsIntRect&        aDamageArea);
+                  TableArea&        aDamageArea);
 
   void InsertRows(nsTableCellMap&             aMap,
                   nsTArray<nsTableRowFrame*>& aRows,
                   int32_t                     aFirstRowIndex,
                   bool                        aConsiderSpans,
                   int32_t                     aRgFirstRowIndex,
-                  nsIntRect&                  aDamageArea);
+                  TableArea&                  aDamageArea);
 
   void RemoveRows(nsTableCellMap& aMap,
                   int32_t         aFirstRowIndex,
                   int32_t         aNumRowsToRemove,
                   bool            aConsiderSpans,
                   int32_t         aRgFirstRowIndex,
-                  nsIntRect&      aDamageArea);
+                  TableArea&      aDamageArea);
 
   int32_t GetNumCellsOriginatingInRow(int32_t aRowIndex) const;
   int32_t GetNumCellsOriginatingInCol(int32_t aColIndex) const;
 
   /** return the number of rows in the table represented by this CellMap */
   int32_t GetRowCount(bool aConsiderDeadRowSpanRows = false) const;
 
   nsTableCellFrame* GetCellInfoAt(const nsTableCellMap& aMap,
@@ -468,39 +473,39 @@ protected:
                       int32_t         aColIndex) const;
 
   int32_t GetNumCellsIn(int32_t aColIndex) const;
 
   void ExpandWithRows(nsTableCellMap&             aMap,
                       nsTArray<nsTableRowFrame*>& aRowFrames,
                       int32_t                     aStartRowIndex,
                       int32_t                     aRgFirstRowIndex,
-                      nsIntRect&                  aDamageArea);
+                      TableArea&                  aDamageArea);
 
   void ExpandWithCells(nsTableCellMap&              aMap,
                        nsTArray<nsTableCellFrame*>& aCellFrames,
                        int32_t                      aRowIndex,
                        int32_t                      aColIndex,
                        int32_t                      aRowSpan,
                        bool                         aRowSpanIsZero,
                        int32_t                      aRgFirstRowIndex,
-                       nsIntRect&                   aDamageArea);
+                       TableArea&                   aDamageArea);
 
   void ShrinkWithoutRows(nsTableCellMap& aMap,
                          int32_t         aFirstRowIndex,
                          int32_t         aNumRowsToRemove,
                          int32_t         aRgFirstRowIndex,
-                         nsIntRect&      aDamageArea);
+                         TableArea&      aDamageArea);
 
   void ShrinkWithoutCell(nsTableCellMap&   aMap,
                          nsTableCellFrame& aCellFrame,
                          int32_t           aRowIndex,
                          int32_t           aColIndex,
                          int32_t           aRgFirstRowIndex,
-                         nsIntRect&        aDamageArea);
+                         TableArea&        aDamageArea);
 
   /**
    * Rebuild due to rows being inserted or deleted with cells spanning
    * into or out of the rows.  This function can only handle insertion
    * or deletion but NOT both.  So either aRowsToInsert must be null
    * or aNumRowsToRemove must be 0.
    *
    * // XXXbz are both allowed to happen?  That'd be a no-op...
--- a/layout/tables/nsTableCellFrame.cpp
+++ b/layout/tables/nsTableCellFrame.cpp
@@ -236,17 +236,17 @@ nsTableCellFrame::DidSetStyleContext(nsS
   nsTableFrame* tableFrame = GetTableFrame();
   if (tableFrame->IsBorderCollapse() &&
       tableFrame->BCRecalcNeeded(aOldStyleContext, StyleContext())) {
     int32_t colIndex, rowIndex;
     GetColIndex(colIndex);
     GetRowIndex(rowIndex);
     // row span needs to be clamped as we do not create rows in the cellmap
     // which do not have cells originating in them
-    nsIntRect damageArea(colIndex, rowIndex, GetColSpan(),
+    TableArea damageArea(colIndex, rowIndex, GetColSpan(),
       std::min(GetRowSpan(), tableFrame->GetRowCount() - rowIndex));
     tableFrame->AddBCDamageArea(damageArea);
   }
 }
 
 #ifdef DEBUG
 void
 nsTableCellFrame::AppendFrames(ChildListID     aListID,
--- a/layout/tables/nsTableColFrame.cpp
+++ b/layout/tables/nsTableColFrame.cpp
@@ -14,16 +14,18 @@
 #include "nsIContent.h"
 
 #define COL_TYPE_BITS                 (NS_FRAME_STATE_BIT(28) | \
                                        NS_FRAME_STATE_BIT(29) | \
                                        NS_FRAME_STATE_BIT(30) | \
                                        NS_FRAME_STATE_BIT(31))
 #define COL_TYPE_OFFSET               28
 
+using namespace mozilla;
+
 nsTableColFrame::nsTableColFrame(nsStyleContext* aContext) :
   nsSplittableFrame(aContext)
 {
   SetColType(eColContent);
   ResetIntrinsics();
   ResetSpanIntrinsics();
   ResetFinalISize();
 }
@@ -57,17 +59,17 @@ nsTableColFrame::DidSetStyleContext(nsSt
   nsSplittableFrame::DidSetStyleContext(aOldStyleContext);
 
   if (!aOldStyleContext) //avoid this on init
     return;
 
   nsTableFrame* tableFrame = GetTableFrame();
   if (tableFrame->IsBorderCollapse() &&
       tableFrame->BCRecalcNeeded(aOldStyleContext, StyleContext())) {
-    nsIntRect damageArea(GetColIndex(), 0, 1, tableFrame->GetRowCount());
+    TableArea damageArea(GetColIndex(), 0, 1, tableFrame->GetRowCount());
     tableFrame->AddBCDamageArea(damageArea);
   }
 }
 
 void nsTableColFrame::SetContinuousBCBorderWidth(uint8_t     aForSide,
                                                  BCPixelSize aPixelValue)
 {
   switch (aForSide) {
--- a/layout/tables/nsTableColGroupFrame.cpp
+++ b/layout/tables/nsTableColGroupFrame.cpp
@@ -158,17 +158,17 @@ nsTableColGroupFrame::DidSetStyleContext
     return;
      
   nsTableFrame* tableFrame = GetTableFrame();
   if (tableFrame->IsBorderCollapse() &&
       tableFrame->BCRecalcNeeded(aOldStyleContext, StyleContext())) {
     int32_t colCount = GetColCount();
     if (!colCount)
       return; // this is a degenerated colgroup 
-    nsIntRect damageArea(GetFirstColumn()->GetColIndex(), 0, colCount,
+    TableArea damageArea(GetFirstColumn()->GetColIndex(), 0, colCount,
                          tableFrame->GetRowCount());
     tableFrame->AddBCDamageArea(damageArea);
   }
 }
 
 void
 nsTableColGroupFrame::AppendFrames(ChildListID     aListID,
                                    nsFrameList&    aFrameList)
--- a/layout/tables/nsTableFrame.cpp
+++ b/layout/tables/nsTableFrame.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=2 sw=2 et tw=80: */
 /* 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/. */
 
 #include "mozilla/Likely.h"
 #include "mozilla/MathAlgorithms.h"
+#include "mozilla/IntegerRange.h"
 
 #include "nsCOMPtr.h"
 #include "nsTableFrame.h"
 #include "nsRenderingContext.h"
 #include "nsStyleContext.h"
 #include "nsStyleConsts.h"
 #include "nsIContent.h"
 #include "nsCellMap.h"
@@ -121,17 +122,17 @@ struct nsTableReflowState {
  ** nsTableFrame                                                               **
  ********************************************************************************/
 
 struct BCPropertyData
 {
   BCPropertyData() : mTopBorderWidth(0), mRightBorderWidth(0),
                      mBottomBorderWidth(0), mLeftBorderWidth(0),
                      mLeftCellBorderWidth(0), mRightCellBorderWidth(0) {}
-  nsIntRect mDamageArea;
+  TableArea mDamageArea;
   BCPixelSize mTopBorderWidth;
   BCPixelSize mRightBorderWidth;
   BCPixelSize mBottomBorderWidth;
   BCPixelSize mLeftBorderWidth;
   BCPixelSize mLeftCellBorderWidth;
   BCPixelSize mRightCellBorderWidth;
 };
 
@@ -606,17 +607,17 @@ void nsTableFrame::InsertCol(nsTableColF
       }
       if (!removedFromCache) {
         cellMap->AddColsAtEnd(1);
       }
     }
   }
   // for now, just bail and recalc all of the collapsing borders
   if (IsBorderCollapse()) {
-    nsIntRect damageArea(aColIndex, 0, 1, GetRowCount());
+    TableArea damageArea(aColIndex, 0, 1, GetRowCount());
     AddBCDamageArea(damageArea);
   }
 }
 
 void nsTableFrame::RemoveCol(nsTableColGroupFrame* aColGroupFrame,
                              int32_t               aColIndex,
                              bool                  aRemoveFromCache,
                              bool                  aRemoveFromCellMap)
@@ -627,17 +628,17 @@ void nsTableFrame::RemoveCol(nsTableColG
   if (aRemoveFromCellMap) {
     nsTableCellMap* cellMap = GetCellMap();
     if (cellMap) {
       AppendAnonymousColFrames(1);
     }
   }
   // for now, just bail and recalc all of the collapsing borders
   if (IsBorderCollapse()) {
-    nsIntRect damageArea(0, 0, GetColCount(), GetRowCount());
+    TableArea damageArea(0, 0, GetColCount(), GetRowCount());
     AddBCDamageArea(damageArea);
   }
 }
 
 /** Get the cell map for this table frame.  It is not always mCellMap.
   * Only the first-in-flow has a legit cell map.
   */
 nsTableCellMap*
@@ -795,32 +796,32 @@ nsTableFrame::DidResizeColumns()
 }
 
 void
 nsTableFrame::AppendCell(nsTableCellFrame& aCellFrame,
                          int32_t           aRowIndex)
 {
   nsTableCellMap* cellMap = GetCellMap();
   if (cellMap) {
-    nsIntRect damageArea(0,0,0,0);
+    TableArea damageArea(0, 0, 0, 0);
     cellMap->AppendCell(aCellFrame, aRowIndex, true, damageArea);
     MatchCellMapToColCache(cellMap);
     if (IsBorderCollapse()) {
       AddBCDamageArea(damageArea);
     }
   }
 }
 
 void nsTableFrame::InsertCells(nsTArray<nsTableCellFrame*>& aCellFrames,
                                int32_t                      aRowIndex,
                                int32_t                      aColIndexBefore)
 {
   nsTableCellMap* cellMap = GetCellMap();
   if (cellMap) {
-    nsIntRect damageArea(0,0,0,0);
+    TableArea damageArea(0, 0, 0, 0);
     cellMap->InsertCells(aCellFrames, aRowIndex, aColIndexBefore, damageArea);
     MatchCellMapToColCache(cellMap);
     if (IsBorderCollapse()) {
       AddBCDamageArea(damageArea);
     }
   }
 }
 
@@ -850,17 +851,17 @@ nsTableFrame::DestroyAnonymousColFrames(
   return (aNumFrames - numColsRemoved);
 }
 
 void nsTableFrame::RemoveCell(nsTableCellFrame* aCellFrame,
                               int32_t           aRowIndex)
 {
   nsTableCellMap* cellMap = GetCellMap();
   if (cellMap) {
-    nsIntRect damageArea(0,0,0,0);
+    TableArea damageArea(0, 0, 0, 0);
     cellMap->RemoveCell(aCellFrame, aRowIndex, damageArea);
     MatchCellMapToColCache(cellMap);
     if (IsBorderCollapse()) {
       AddBCDamageArea(damageArea);
     }
   }
 }
 
@@ -904,17 +905,17 @@ nsTableFrame::InsertRows(nsTableRowGroup
 #ifdef DEBUG_TABLE_CELLMAP
   printf("=== insertRowsBefore firstRow=%d \n", aRowIndex);
   Dump(true, false, true);
 #endif
 
   int32_t numColsToAdd = 0;
   nsTableCellMap* cellMap = GetCellMap();
   if (cellMap) {
-    nsIntRect damageArea(0,0,0,0);
+    TableArea damageArea(0, 0, 0, 0);
     int32_t origNumRows = cellMap->GetRowCount();
     int32_t numNewRows = aRowFrames.Length();
     cellMap->InsertRows(aRowGroupFrame, aRowFrames, aRowIndex, aConsiderSpans, damageArea);
     MatchCellMapToColCache(cellMap);
     if (aRowIndex < origNumRows) {
       AdjustRowIndices(aRowIndex, numNewRows);
     }
     // assign the correct row indices to the new rows. If they were adjusted above
@@ -958,17 +959,17 @@ void nsTableFrame::RemoveRows(nsTableRow
 
   int32_t firstRowIndex = aFirstRowFrame.GetRowIndex();
 #ifdef DEBUG_TABLE_CELLMAP
   printf("=== removeRowsBefore firstRow=%d numRows=%d\n", firstRowIndex, aNumRowsToRemove);
   Dump(true, false, true);
 #endif
   nsTableCellMap* cellMap = GetCellMap();
   if (cellMap) {
-    nsIntRect damageArea(0,0,0,0);
+    TableArea damageArea(0, 0, 0, 0);
     cellMap->RemoveRows(firstRowIndex, aNumRowsToRemove, aConsiderSpans, damageArea);
     MatchCellMapToColCache(cellMap);
     if (IsBorderCollapse()) {
       AddBCDamageArea(damageArea);
     }
   }
   AdjustRowIndices(firstRowIndex, -aNumRowsToRemove);
 #ifdef DEBUG_TABLE_CELLMAP
@@ -2490,17 +2491,17 @@ nsTableFrame::DoRemoveFrame(ChildListID 
     // remove the row group frame from the sibling chain
     mFrames.DestroyFrame(aOldFrame);
 
     // the removal of a row group changes the cellmap, the columns might change
     if (cellMap) {
       cellMap->Synchronize(this);
       // Create an empty slice
       ResetRowIndices(nsFrameList::Slice(mFrames, nullptr, nullptr));
-      nsIntRect damageArea;
+      TableArea damageArea;
       cellMap->RebuildConsideringCells(nullptr, nullptr, 0, 0, false, damageArea);
 
       static_cast<nsTableFrame*>(FirstInFlow())->MatchCellMapToColCache(cellMap);
     }
   }
 }
 
 void
@@ -3983,81 +3984,81 @@ nsTableFrame::ColumnHasCellSpacingBefore
  *     double, solid, dashed, dotted, ridge, outset, groove, inset
  *  4) borders that are of equal width and style (differ only in color) have this precedence:
  *     cell, row, rowgroup, col, colgroup, table
  *  5) if all border styles are NONE, then that's the computed border style.
  *******************************************************************************/
 
 #ifdef DEBUG
 #define VerifyNonNegativeDamageRect(r)                                  \
-  NS_ASSERTION((r).x >= 0, "negative col index");                       \
-  NS_ASSERTION((r).y >= 0, "negative row index");                       \
-  NS_ASSERTION((r).width >= 0, "negative horizontal damage");           \
-  NS_ASSERTION((r).height >= 0, "negative vertical damage");
+  NS_ASSERTION((r).StartCol() >= 0, "negative col index");              \
+  NS_ASSERTION((r).StartRow() >= 0, "negative row index");              \
+  NS_ASSERTION((r).ColCount() >= 0, "negative cols damage");            \
+  NS_ASSERTION((r).RowCount() >= 0, "negative rows damage");
 #define VerifyDamageRect(r)                                             \
   VerifyNonNegativeDamageRect(r);                                       \
-  NS_ASSERTION((r).XMost() <= GetColCount(),                            \
-               "horizontal damage extends outside table");              \
-  NS_ASSERTION((r).YMost() <= GetRowCount(),                            \
-               "vertical damage extends outside table");
+  NS_ASSERTION((r).EndCol() <= GetColCount(),                           \
+               "cols damage extends outside table");                    \
+  NS_ASSERTION((r).EndRow() <= GetRowCount(),                           \
+               "rows damage extends outside table");
 #endif
 
 void
-nsTableFrame::AddBCDamageArea(const nsIntRect& aValue)
+nsTableFrame::AddBCDamageArea(const TableArea& aValue)
 {
   NS_ASSERTION(IsBorderCollapse(), "invalid AddBCDamageArea call");
 #ifdef DEBUG
   VerifyDamageRect(aValue);
 #endif
 
   SetNeedToCalcBCBorders(true);
   // Get the property
   BCPropertyData* value = GetBCProperty(true);
   if (value) {
 #ifdef DEBUG
     VerifyNonNegativeDamageRect(value->mDamageArea);
 #endif
     // Clamp the old damage area to the current table area in case it shrunk.
     int32_t cols = GetColCount();
-    if (value->mDamageArea.XMost() > cols) {
-      if (value->mDamageArea.x > cols) {
-        value->mDamageArea.x = cols;
-        value->mDamageArea.width = 0;
+    if (value->mDamageArea.EndCol() > cols) {
+      if (value->mDamageArea.StartCol() > cols) {
+        value->mDamageArea.StartCol() = cols;
+        value->mDamageArea.ColCount() = 0;
       }
       else {
-        value->mDamageArea.width = cols - value->mDamageArea.x;
+        value->mDamageArea.ColCount() = cols - value->mDamageArea.StartCol();
       }
     }
     int32_t rows = GetRowCount();
-    if (value->mDamageArea.YMost() > rows) {
-      if (value->mDamageArea.y > rows) {
-        value->mDamageArea.y = rows;
-        value->mDamageArea.height = 0;
+    if (value->mDamageArea.EndRow() > rows) {
+      if (value->mDamageArea.StartRow() > rows) {
+        value->mDamageArea.StartRow() = rows;
+        value->mDamageArea.RowCount() = 0;
       }
       else {
-        value->mDamageArea.height = rows - value->mDamageArea.y;
+        value->mDamageArea.RowCount() = rows - value->mDamageArea.StartRow();
       }
     }
 
     // Construct a union of the new and old damage areas.
-    value->mDamageArea.UnionRect(value->mDamageArea, aValue);
+    value->mDamageArea.UnionArea(value->mDamageArea, aValue);
   }
 }
 
 
 void
 nsTableFrame::SetFullBCDamageArea()
 {
   NS_ASSERTION(IsBorderCollapse(), "invalid SetFullBCDamageArea call");
 
   SetNeedToCalcBCBorders(true);
 
   BCPropertyData* value = GetBCProperty(true);
   if (value) {
-    value->mDamageArea = nsIntRect(0, 0, GetColCount(), GetRowCount());
+    value->mDamageArea = TableArea(0, 0, GetColCount(), GetRowCount());
   }
 }
 
 
 /* BCCellBorder represents a border segment which can be either a horizontal
  * or a vertical segment. For each segment we need to know the color, width,
  * style, who owns it and how long it is in cellmap coordinates.
  * Ownership of these segments is important to calculate which corners should
@@ -4263,17 +4264,17 @@ inline int32_t BCMapCellInfo::GetCellEnd
   return mColIndex + mColSpan - 1;
 }
 
 
 class BCMapCellIterator
 {
 public:
   BCMapCellIterator(nsTableFrame* aTableFrame,
-                    const nsIntRect& aDamageArea);
+                    const TableArea& aDamageArea);
 
   void First(BCMapCellInfo& aMapCellInfo);
 
   void Next(BCMapCellInfo& aMapCellInfo);
 
   void PeekRight(BCMapCellInfo& aRefInfo,
                  uint32_t     aRowIndex,
                  BCMapCellInfo& aAjaInfo);
@@ -4309,25 +4310,25 @@ private:
   int32_t               mRowIndex;
   uint32_t              mNumTableCols;
   int32_t               mColIndex;
   nsPoint               mAreaStart;
   nsPoint               mAreaEnd;
 };
 
 BCMapCellIterator::BCMapCellIterator(nsTableFrame* aTableFrame,
-                                     const nsIntRect& aDamageArea)
+                                     const TableArea& aDamageArea)
 :mTableFrame(aTableFrame)
 {
   mTableCellMap  = aTableFrame->GetCellMap();
 
-  mAreaStart.x   = aDamageArea.x;
-  mAreaStart.y   = aDamageArea.y;
-  mAreaEnd.y     = aDamageArea.y + aDamageArea.height - 1;
-  mAreaEnd.x     = aDamageArea.x + aDamageArea.width - 1;
+  mAreaStart.x   = aDamageArea.StartCol();
+  mAreaStart.y   = aDamageArea.StartRow();
+  mAreaEnd.x     = aDamageArea.EndCol() - 1;
+  mAreaEnd.y     = aDamageArea.EndRow() - 1;
 
   mNumTableRows  = mTableFrame->GetRowCount();
   mRow           = nullptr;
   mRowIndex      = 0;
   mNumTableCols  = mTableFrame->GetColCount();
   mColIndex      = 0;
   mRowGroupIndex = -1;
 
@@ -4446,17 +4447,17 @@ BCMapCellIterator::SetNewRow(nsTableRowF
     int32_t rgRowIndex = mRowIndex - mRowGroupStart;
     if (uint32_t(rgRowIndex) >= mCellMap->mRows.Length())
       ABORT1(false);
     const nsCellMap::CellDataArray& row = mCellMap->mRows[rgRowIndex];
 
     for (mColIndex = mAreaStart.x; mColIndex <= mAreaEnd.x; mColIndex++) {
       CellData* cellData = row.SafeElementAt(mColIndex);
       if (!cellData) { // add a dead cell data
-        nsIntRect damageArea;
+        TableArea damageArea;
         cellData = mCellMap->AppendCell(*mTableCellMap, nullptr, rgRowIndex,
                                         false, 0, damageArea);
         if (!cellData) ABORT1(false);
       }
       if (cellData && (cellData->IsOrig() || cellData->IsDead())) {
         break;
       }
     }
@@ -4542,17 +4543,17 @@ BCMapCellIterator::Next(BCMapCellInfo& a
   mIsNewRow = false;
   mColIndex++;
   while ((mRowIndex <= mAreaEnd.y) && !mAtEnd) {
     for (; mColIndex <= mAreaEnd.x; mColIndex++) {
       int32_t rgRowIndex = mRowIndex - mRowGroupStart;
       BCCellData* cellData =
          static_cast<BCCellData*>(mCellMap->GetDataAt(rgRowIndex, mColIndex));
       if (!cellData) { // add a dead cell data
-        nsIntRect damageArea;
+        TableArea damageArea;
         cellData =
           static_cast<BCCellData*>(mCellMap->AppendCell(*mTableCellMap, nullptr,
                                                          rgRowIndex, false, 0,
                                                          damageArea));
         if (!cellData) ABORT0();
       }
       if (cellData && (cellData->IsOrig() || cellData->IsDead())) {
         aMapInfo.SetInfo(mRow, mColIndex, cellData, this);
@@ -4577,17 +4578,17 @@ BCMapCellIterator::PeekRight(BCMapCellIn
   aAjaInfo.ResetCellInfo();
   int32_t colIndex = aRefInfo.mColIndex + aRefInfo.mColSpan;
   uint32_t rgRowIndex = aRowIndex - mRowGroupStart;
 
   BCCellData* cellData =
     static_cast<BCCellData*>(mCellMap->GetDataAt(rgRowIndex, colIndex));
   if (!cellData) { // add a dead cell data
     NS_ASSERTION(colIndex < mTableCellMap->GetColCount(), "program error");
-    nsIntRect damageArea;
+    TableArea damageArea;
     cellData =
       static_cast<BCCellData*>(mCellMap->AppendCell(*mTableCellMap, nullptr,
                                                      rgRowIndex, false, 0,
                                                      damageArea));
     if (!cellData) ABORT0();
   }
   nsTableRowFrame* row = nullptr;
   if (cellData->IsRowSpan()) {
@@ -4635,17 +4636,17 @@ BCMapCellIterator::PeekBottom(BCMapCellI
       nextRow = nextRow->GetNextRow(); if (!nextRow) ABORT0();
     }
   }
 
   BCCellData* cellData =
     static_cast<BCCellData*>(cellMap->GetDataAt(rgRowIndex, aColIndex));
   if (!cellData) { // add a dead cell data
     NS_ASSERTION(rgRowIndex < cellMap->GetRowCount(), "program error");
-    nsIntRect damageArea;
+    TableArea damageArea;
     cellData =
       static_cast<BCCellData*>(cellMap->AppendCell(*mTableCellMap, nullptr,
                                                     rgRowIndex, false, 0,
                                                     damageArea));
     if (!cellData) ABORT0();
   }
   if (cellData->IsColSpan()) {
     aColIndex -= cellData->GetColSpanOffset();
@@ -5170,25 +5171,25 @@ SetHorBorder(const BCCellBorder& aNewBor
   return startSeg;
 }
 
 // Make the damage area larger on the top and bottom by at least one row and on the left and right
 // at least one column. This is done so that adjacent elements are part of the border calculations.
 // The extra segments and borders outside the actual damage area will not be updated in the cell map,
 // because they in turn would need info from adjacent segments outside the damage area to be accurate.
 void
-nsTableFrame::ExpandBCDamageArea(nsIntRect& aRect) const
+nsTableFrame::ExpandBCDamageArea(TableArea& aArea) const
 {
   int32_t numRows = GetRowCount();
   int32_t numCols = GetColCount();
 
-  int32_t dStartX = aRect.x;
-  int32_t dEndX   = aRect.XMost() - 1;
-  int32_t dStartY = aRect.y;
-  int32_t dEndY   = aRect.YMost() - 1;
+  int32_t dStartX = aArea.StartCol();
+  int32_t dEndX   = aArea.EndCol() - 1;
+  int32_t dStartY = aArea.StartRow();
+  int32_t dEndY   = aArea.EndRow() - 1;
 
   // expand the damage area in each direction
   if (dStartX > 0) {
     dStartX--;
   }
   if (dEndX < (numCols - 1)) {
     dEndX++;
   }
@@ -5284,26 +5285,26 @@ nsTableFrame::ExpandBCDamageArea(nsIntRe
             }
           }
         }
       }
     }
   }
   if (haveSpanner) {
     // make the damage area the whole table
-    aRect.x      = 0;
-    aRect.y      = 0;
-    aRect.width  = numCols;
-    aRect.height = numRows;
+    aArea.StartCol() = 0;
+    aArea.StartRow() = 0;
+    aArea.ColCount() = numCols;
+    aArea.RowCount() = numRows;
   }
   else {
-    aRect.x      = dStartX;
-    aRect.y      = dStartY;
-    aRect.width  = 1 + dEndX - dStartX;
-    aRect.height = 1 + dEndY - dStartY;
+    aArea.StartCol() = dStartX;
+    aArea.StartRow() = dStartY;
+    aArea.ColCount() = 1 + dEndX - dStartX;
+    aArea.RowCount() = 1 + dEndY - dStartY;
   }
 }
 
 
 #define ADJACENT    true
 #define HORIZONTAL  true
 
 void
@@ -5708,53 +5709,55 @@ nsTableFrame::CalcBCBorders()
 
   // Get the property holding the table damage area and border widths
   BCPropertyData* propData = GetBCProperty();
   if (!propData) ABORT0();
 
 
 
   // calculate an expanded damage area
-  nsIntRect damageArea(propData->mDamageArea);
+  TableArea damageArea(propData->mDamageArea);
   ExpandBCDamageArea(damageArea);
 
   // segments that are on the table border edges need
   // to be initialized only once
   bool tableBorderReset[4];
   for (uint32_t sideX = NS_SIDE_TOP; sideX <= NS_SIDE_LEFT; sideX++) {
     tableBorderReset[sideX] = false;
   }
 
   // vertical borders indexed in x-direction (cols)
-  BCCellBorders lastVerBorders(damageArea.width + 1, damageArea.x);
+  BCCellBorders lastVerBorders(damageArea.ColCount() + 1,
+                               damageArea.StartCol());
   if (!lastVerBorders.borders) ABORT0();
   BCCellBorder  lastTopBorder, lastBottomBorder;
   // horizontal borders indexed in x-direction (cols)
-  BCCellBorders lastBottomBorders(damageArea.width + 1, damageArea.x);
+  BCCellBorders lastBottomBorders(damageArea.ColCount() + 1,
+                                  damageArea.StartCol());
   if (!lastBottomBorders.borders) ABORT0();
   bool startSeg;
   bool gotRowBorder = false;
 
   BCMapCellInfo  info(this), ajaInfo(this);
 
   BCCellBorder currentBorder, adjacentBorder;
-  BCCorners topCorners(damageArea.width + 1, damageArea.x);
+  BCCorners topCorners(damageArea.ColCount() + 1, damageArea.StartCol());
   if (!topCorners.corners) ABORT0();
-  BCCorners bottomCorners(damageArea.width + 1, damageArea.x);
+  BCCorners bottomCorners(damageArea.ColCount() + 1, damageArea.StartCol());
   if (!bottomCorners.corners) ABORT0();
 
   BCMapCellIterator iter(this, damageArea);
   for (iter.First(info); !iter.mAtEnd; iter.Next(info)) {
     // see if lastTopBorder, lastBottomBorder need to be reset
     if (iter.IsNewRow()) {
       gotRowBorder = false;
       lastTopBorder.Reset(info.mRowIndex, info.mRowSpan);
       lastBottomBorder.Reset(info.GetCellEndRowIndex() + 1, info.mRowSpan);
     }
-    else if (info.mColIndex > damageArea.x) {
+    else if (info.mColIndex > damageArea.StartCol()) {
       lastBottomBorder = lastBottomBorders[info.mColIndex - 1];
       if (info.mRowIndex >
           (lastBottomBorder.rowIndex - lastBottomBorder.rowSpan)) {
         // the top border's left edge butts against the middle of a rowspan
         lastTopBorder.Reset(info.mRowIndex, info.mRowSpan);
       }
       if (lastBottomBorder.rowIndex > (info.GetCellEndRowIndex() + 1)) {
         // the bottom border's left edge butts against the middle of a rowspan
@@ -5913,18 +5916,18 @@ nsTableFrame::CalcBCBorders()
 
         segLength = std::max(1, ajaInfo.mRowIndex + ajaInfo.mRowSpan - rowY);
         segLength = std::min(segLength, info.mRowIndex + info.mRowSpan - rowY);
 
         // update lastVerBorders and see if a new segment starts
         startSeg = SetBorder(currentBorder,
                              lastVerBorders[info.GetCellEndColIndex() + 1]);
         // store the border segment in the cell map and update cellBorders
-        if (info.GetCellEndColIndex() < damageArea.XMost() &&
-            rowY >= damageArea.y && rowY < damageArea.YMost()) {
+        if (info.GetCellEndColIndex() < damageArea.EndCol() &&
+            rowY >= damageArea.StartRow() && rowY < damageArea.EndRow()) {
           tableCellMap->SetBCBorderEdge(NS_SIDE_RIGHT, *iter.mCellMap,
                                         iter.mRowGroupStart, rowY,
                                         info.GetCellEndColIndex(), segLength,
                                         currentBorder.owner,
                                         currentBorder.width, startSeg);
           info.SetRightBorderWidths(currentBorder.width);
           ajaInfo.SetLeftBorderWidths(currentBorder.width);
         }
@@ -5940,18 +5943,18 @@ nsTableFrame::CalcBCBorders()
         if (rowY != info.mRowIndex) {
           currentBorder  = priorAjaInfo.GetBottomInternalBorder();
           adjacentBorder = ajaInfo.GetTopInternalBorder();
           currentBorder = CompareBorders(!CELL_CORNER, currentBorder,
                                           adjacentBorder, HORIZONTAL);
           trCorner->Update(NS_SIDE_RIGHT, currentBorder);
         }
         // store the top right corner in the cell map
-        if (info.GetCellEndColIndex() < damageArea.XMost() &&
-            rowY >= damageArea.y) {
+        if (info.GetCellEndColIndex() < damageArea.EndCol() &&
+            rowY >= damageArea.StartRow()) {
           if (0 != rowY) {
             tableCellMap->SetBCBorderCorner(eTopRight, *iter.mCellMap,
                                             iter.mRowGroupStart, rowY,
                                             info.GetCellEndColIndex(),
                                             mozilla::css::Side(trCorner->ownerSide),
                                             trCorner->subWidth,
                                             trCorner->bevel);
           }
@@ -6050,35 +6053,35 @@ nsTableFrame::CalcBCBorders()
         segLength = std::max(1, ajaInfo.mColIndex + ajaInfo.mColSpan - colX);
         segLength = std::min(segLength, info.mColIndex + info.mColSpan - colX);
 
         // update, store the bottom left corner
         BCCornerInfo& blCorner = bottomCorners[colX]; // bottom left
         bool hitsSpanBelow = (colX > ajaInfo.mColIndex) &&
                                (colX < ajaInfo.mColIndex + ajaInfo.mColSpan);
         bool update = true;
-        if ((colX == info.mColIndex) && (colX > damageArea.x)) {
+        if (colX == info.mColIndex && colX > damageArea.StartCol()) {
           int32_t prevRowIndex = lastBottomBorders[colX - 1].rowIndex;
           if (prevRowIndex > info.GetCellEndRowIndex() + 1) {
             // hits a rowspan on the right
             update = false;
             // the corner was taken care of during the cell on the left
           }
           else if (prevRowIndex < info.GetCellEndRowIndex() + 1) {
             // spans below the cell to the left
             topCorners[colX] = blCorner;
             blCorner.Set(NS_SIDE_RIGHT, currentBorder);
             update = false;
           }
         }
         if (update) {
           blCorner.Update(NS_SIDE_RIGHT, currentBorder);
         }
-        if (info.GetCellEndRowIndex() < damageArea.YMost() &&
-            (colX >= damageArea.x)) {
+        if (info.GetCellEndRowIndex() < damageArea.EndRow() &&
+            colX >= damageArea.StartCol()) {
           if (hitsSpanBelow) {
             tableCellMap->SetBCBorderCorner(eBottomLeft, *iter.mCellMap,
                                             iter.mRowGroupStart,
                                             info.GetCellEndRowIndex(), colX,
                                             mozilla::css::Side(blCorner.ownerSide),
                                             blCorner.subWidth, blCorner.bevel);
           }
           // store any corners this cell spans together with the aja cell
@@ -6105,19 +6108,18 @@ nsTableFrame::CalcBCBorders()
         }
         lastBottomBorder.rowIndex = info.GetCellEndRowIndex() + 1;
         lastBottomBorder.rowSpan = info.mRowSpan;
         for (int32_t cX = colX; cX < colX + segLength; cX++) {
           lastBottomBorders[cX] = lastBottomBorder;
         }
 
         // store the border segment the cell map and update cellBorders
-        if (info.GetCellEndRowIndex() < damageArea.YMost() &&
-            (colX >= damageArea.x) &&
-            (colX < damageArea.XMost())) {
+        if (info.GetCellEndRowIndex() < damageArea.EndRow() &&
+            colX >= damageArea.StartCol() && colX < damageArea.EndCol()) {
           tableCellMap->SetBCBorderEdge(NS_SIDE_BOTTOM, *iter.mCellMap,
                                         iter.mRowGroupStart,
                                         info.GetCellEndRowIndex(),
                                         colX, segLength, currentBorder.owner,
                                         currentBorder.width, startSeg);
           info.SetBottomBorderWidths(currentBorder.width);
           ajaInfo.SetTopBorderWidths(currentBorder.width);
         }
@@ -6160,17 +6162,17 @@ nsTableFrame::CalcBCBorders()
                                         info.GetCellEndColIndex() + 1);
           }
         }
       }
     }
   } // for (iter.First(info); info.mCell; iter.Next(info)) {
   // reset the bc flag and damage area
   SetNeedToCalcBCBorders(false);
-  propData->mDamageArea = nsIntRect(0,0,0,0);
+  propData->mDamageArea = TableArea(0, 0, 0, 0);
 #ifdef DEBUG_TABLE_CELLMAP
   mCellMap->Dump();
 #endif
 }
 
 class BCPaintBorderIterator;
 
 struct BCVerticalSeg
@@ -6338,25 +6340,35 @@ public:
   BCCellData*           mPrevCellData;
   BCCellData*           mCellData;
   BCData*               mBCData;
 
   bool                  IsTableTopMost()    {return (mRowIndex == 0) && !mTable->GetPrevInFlow();}
   bool                  IsTableRightMost()  {return (mColIndex >= mNumTableCols);}
   bool                  IsTableBottomMost() {return (mRowIndex >= mNumTableRows) && !mTable->GetNextInFlow();}
   bool                  IsTableLeftMost()   {return (mColIndex == 0);}
-  bool                  IsDamageAreaTopMost()    {return (mRowIndex == mDamageArea.y);}
-  bool                  IsDamageAreaRightMost()  {return (mColIndex >= mDamageArea.XMost());}
-  bool                  IsDamageAreaBottomMost() {return (mRowIndex >= mDamageArea.YMost());}
-  bool                  IsDamageAreaLeftMost()   {return (mColIndex == mDamageArea.x);}
-  int32_t               GetRelativeColIndex() {return (mColIndex - mDamageArea.x);}
-
-  nsIntRect             mDamageArea;        // damageArea in cellmap coordinates
+  bool IsDamageAreaTopMost() const
+    { return mRowIndex == mDamageArea.StartRow(); }
+  bool IsDamageAreaRightMost() const
+    { return mColIndex >= mDamageArea.EndCol(); }
+  bool IsDamageAreaBottomMost() const
+    { return mRowIndex >= mDamageArea.EndRow(); }
+  bool IsDamageAreaLeftMost() const
+    { return mColIndex == mDamageArea.StartCol(); }
+  int32_t GetRelativeColIndex() const
+    { return mColIndex - mDamageArea.StartCol(); }
+
+  TableArea             mDamageArea;        // damageArea in cellmap coordinates
   bool                  IsAfterRepeatedHeader() { return !mIsRepeatedHeader && (mRowIndex == (mRepeatedHeaderRowIndex + 1));}
-  bool                  StartRepeatedFooter() {return mIsRepeatedFooter && (mRowIndex == mRgFirstRowIndex) && (mRowIndex != mDamageArea.y);}
+  bool StartRepeatedFooter() const
+  {
+    return mIsRepeatedFooter && mRowIndex == mRgFirstRowIndex &&
+      mRowIndex != mDamageArea.StartRow();
+  }
+
   nscoord               mInitialOffsetX;  // offsetX of the first border with
                                             // respect to the table
   nscoord               mInitialOffsetY;    // offsetY of the first border with
                                             // respect to the table
   nscoord               mNextOffsetY;       // offsetY of the next segment
   BCVerticalSeg*        mVerInfo; // this array is used differently when
                                   // horizontal and vertical borders are drawn
                                   // When horizontal border are drawn we cache
@@ -6519,22 +6531,22 @@ BCPaintBorderIterator::SetDamageArea(con
       nsTableColFrame* colFrame = mTableFirstInFlow->GetColFrame(column);
       if (!colFrame) ABORT1(false);
       nsSize size = colFrame->GetSize();
       mInitialOffsetX += mColInc * size.width;
     }
   }
   if (!haveIntersect)
     return false;
-  mDamageArea = nsIntRect(startColIndex, startRowIndex,
+  mDamageArea = TableArea(startColIndex, startRowIndex,
                           1 + DeprecatedAbs<int32_t>(endColIndex - startColIndex),
                           1 + endRowIndex - startRowIndex);
 
   Reset();
-  mVerInfo = new BCVerticalSeg[mDamageArea.width + 1];
+  mVerInfo = new BCVerticalSeg[mDamageArea.ColCount() + 1];
   if (!mVerInfo)
     return false;
   return true;
 }
 
 void
 BCPaintBorderIterator::Reset()
 {
@@ -6614,17 +6626,17 @@ BCPaintBorderIterator::SetNewData(int32_
 bool
 BCPaintBorderIterator::SetNewRow(nsTableRowFrame* aRow)
 {
   mPrevRow = mRow;
   mRow     = (aRow) ? aRow : mRow->GetNextRow();
   if (mRow) {
     mIsNewRow = true;
     mRowIndex = mRow->GetRowIndex();
-    mColIndex = mDamageArea.x;
+    mColIndex = mDamageArea.StartCol();
     mPrevHorSegHeight = 0;
     if (mIsRepeatedHeader) {
       mRepeatedHeaderRowIndex = mRowIndex;
     }
   }
   else {
     mAtEnd = true;
   }
@@ -6656,17 +6668,17 @@ BCPaintBorderIterator::SetNewRowGroup()
     if (SetNewRow(mRg->GetFirstRow())) {
       mCellMap = mTableCellMap->GetMapFor(fifRg, nullptr);
       if (!mCellMap) ABORT1(false);
     }
     if (mRg && mTable->GetPrevInFlow() && !mRg->GetPrevInFlow()) {
       // if mRowGroup doesn't have a prev in flow, then it may be a repeated
       // header or footer
       const nsStyleDisplay* display = mRg->StyleDisplay();
-      if (mRowIndex == mDamageArea.y) {
+      if (mRowIndex == mDamageArea.StartRow()) {
         mIsRepeatedHeader = (NS_STYLE_DISPLAY_TABLE_HEADER_GROUP == display->mDisplay);
       }
       else {
         mIsRepeatedFooter = (NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP == display->mDisplay);
       }
     }
   }
   else {
@@ -6676,34 +6688,34 @@ BCPaintBorderIterator::SetNewRowGroup()
 }
 
 /**
  *  Move the iterator to the first position in the damageArea
  */
 void
 BCPaintBorderIterator::First()
 {
-  if (!mTable || (mDamageArea.x >= mNumTableCols) ||
-      (mDamageArea.y >= mNumTableRows)) ABORT0();
+  if (!mTable || mDamageArea.StartCol() >= mNumTableCols ||
+      mDamageArea.StartRow() >= mNumTableRows) ABORT0();
 
   mAtEnd = false;
 
   uint32_t numRowGroups = mRowGroups.Length();
   for (uint32_t rgY = 0; rgY < numRowGroups; rgY++) {
     nsTableRowGroupFrame* rowG = mRowGroups[rgY];
     int32_t start = rowG->GetStartRowIndex();
     int32_t end   = start + rowG->GetRowCount() - 1;
-    if ((mDamageArea.y >= start) && (mDamageArea.y <= end)) {
+    if (mDamageArea.StartRow() >= start && mDamageArea.StartRow() <= end) {
       mRgIndex = rgY - 1; // SetNewRowGroup increments rowGroupIndex
       if (SetNewRowGroup()) {
-        while ((mRowIndex < mDamageArea.y) && !mAtEnd) {
+        while (mRowIndex < mDamageArea.StartRow() && !mAtEnd) {
           SetNewRow();
         }
         if (!mAtEnd) {
-          SetNewData(mDamageArea.y, mDamageArea.x);
+          SetNewData(mDamageArea.StartRow(), mDamageArea.StartCol());
         }
       }
       return;
     }
   }
   mAtEnd = true;
 }
 
@@ -6712,22 +6724,22 @@ BCPaintBorderIterator::First()
  */
 void
 BCPaintBorderIterator::Next()
 {
   if (mAtEnd) ABORT0();
   mIsNewRow = false;
 
   mColIndex++;
-  if (mColIndex > mDamageArea.XMost()) {
+  if (mColIndex > mDamageArea.EndCol()) {
     mRowIndex++;
-    if (mRowIndex == mDamageArea.YMost()) {
-      mColIndex = mDamageArea.x;
-    }
-    else if (mRowIndex < mDamageArea.YMost()) {
+    if (mRowIndex == mDamageArea.EndRow()) {
+      mColIndex = mDamageArea.StartCol();
+    }
+    else if (mRowIndex < mDamageArea.EndRow()) {
       if (mRowIndex <= mRgLastRowIndex) {
         SetNewRow();
       }
       else {
         SetNewRowGroup();
       }
     }
     else {
@@ -7365,19 +7377,19 @@ BCPaintBorderIterator::AccumulateOrPaint
 
 /**
  * Reset the vertical information cache
  */
 void
 BCPaintBorderIterator::ResetVerInfo()
 {
   if (mVerInfo) {
-    memset(mVerInfo, 0, mDamageArea.width * sizeof(BCVerticalSeg));
+    memset(mVerInfo, 0, mDamageArea.ColCount() * sizeof(BCVerticalSeg));
     // XXX reinitialize properly
-    for (int32_t xIndex = 0; xIndex < mDamageArea.width; xIndex++) {
+    for (auto xIndex : MakeRange(mDamageArea.ColCount())) {
       mVerInfo[xIndex].mColWidth = -1;
     }
   }
 }
 
 /**
  * Method to paint BCBorders, this does not use currently display lists although
  * it will do this in future
--- a/layout/tables/nsTableFrame.h
+++ b/layout/tables/nsTableFrame.h
@@ -10,16 +10,17 @@
 #include "imgIContainer.h"
 #include "nscore.h"
 #include "nsContainerFrame.h"
 #include "nsStyleCoord.h"
 #include "nsStyleConsts.h"
 #include "nsCellMap.h"
 #include "nsGkAtoms.h"
 #include "nsDisplayList.h"
+#include "TableArea.h"
 
 class nsTableCellFrame;
 class nsTableCellMap;
 class nsTableColFrame;
 class nsTableRowGroupFrame;
 class nsTableRowFrame;
 class nsTableColGroupFrame;
 class nsITableLayoutStrategy;
@@ -295,17 +296,17 @@ public:
    *  continue along the length of the whole left side.
    *  see nsTablePainter about continuous borders
    */
   nscoord GetContinuousLeftBCBorderWidth() const;
   void SetContinuousLeftBCBorderWidth(nscoord aValue);
 
   friend class nsDelayedCalcBCBorders;
 
-  void AddBCDamageArea(const nsIntRect& aValue);
+  void AddBCDamageArea(const mozilla::TableArea& aValue);
   bool BCRecalcNeeded(nsStyleContext* aOldStyleContext,
                         nsStyleContext* aNewStyleContext);
   void PaintBCBorders(nsRenderingContext& aRenderingContext,
                       const nsRect&        aDirtyRect);
 
   virtual void MarkIntrinsicISizesDirty() override;
   // For border-collapse tables, the caller must not add padding and
   // border to the results of these functions.
@@ -793,17 +794,17 @@ public:
 protected:
 
   void SetBorderCollapse(bool aValue);
 
   BCPropertyData* GetBCProperty(bool aCreateIfNecessary = false) const;
   void SetFullBCDamageArea();
   void CalcBCBorders();
 
-  void ExpandBCDamageArea(nsIntRect& aRect) const;
+  void ExpandBCDamageArea(mozilla::TableArea& aRect) const;
 
   void SetColumnDimensions(nscoord         aHeight,
                            const nsMargin& aReflowState);
 
   int32_t CollectRows(nsIFrame*                   aFrame,
                       nsTArray<nsTableRowFrame*>& aCollection);
 
 public: /* ----- Cell Map public methods ----- */
--- a/layout/tables/nsTableRowFrame.cpp
+++ b/layout/tables/nsTableRowFrame.cpp
@@ -169,17 +169,17 @@ nsTableRowFrame::DidSetStyleContext(nsSt
   nsContainerFrame::DidSetStyleContext(aOldStyleContext);
 
   if (!aOldStyleContext) //avoid this on init
     return;
 
   nsTableFrame* tableFrame = GetTableFrame();
   if (tableFrame->IsBorderCollapse() &&
       tableFrame->BCRecalcNeeded(aOldStyleContext, StyleContext())) {
-    nsIntRect damageArea(0, GetRowIndex(), tableFrame->GetColCount(), 1);
+    TableArea damageArea(0, GetRowIndex(), tableFrame->GetColCount(), 1);
     tableFrame->AddBCDamageArea(damageArea);
   }
 }
 
 void
 nsTableRowFrame::AppendFrames(ChildListID     aListID,
                               nsFrameList&    aFrameList)
 {
--- a/layout/tables/nsTableRowGroupFrame.cpp
+++ b/layout/tables/nsTableRowGroupFrame.cpp
@@ -1370,17 +1370,17 @@ nsTableRowGroupFrame::DidSetStyleContext
   nsContainerFrame::DidSetStyleContext(aOldStyleContext);
 
   if (!aOldStyleContext) //avoid this on init
     return;
 
   nsTableFrame* tableFrame = GetTableFrame();
   if (tableFrame->IsBorderCollapse() &&
       tableFrame->BCRecalcNeeded(aOldStyleContext, StyleContext())) {
-    nsIntRect damageArea(0, GetStartRowIndex(), tableFrame->GetColCount(),
+    TableArea damageArea(0, GetStartRowIndex(), tableFrame->GetColCount(),
                          GetRowCount());
     tableFrame->AddBCDamageArea(damageArea);
   }
 }
 
 void
 nsTableRowGroupFrame::AppendFrames(ChildListID     aListID,
                                    nsFrameList&    aFrameList)