diff --git a/mozilla/layout/html/table/src/nsTableBorderCollapser.cpp b/mozilla/layout/html/table/src/nsTableBorderCollapser.cpp
new file mode 100644
index 00000000000..7d9319ab0c8
--- /dev/null
+++ b/mozilla/layout/html/table/src/nsTableBorderCollapser.cpp
@@ -0,0 +1,872 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * The contents of this file are subject to the Netscape Public License
+ * Version 1.0 (the "NPL"); you may not use this file except in
+ * compliance with the NPL. You may obtain a copy of the NPL at
+ * http://www.mozilla.org/NPL/
+ *
+ * Software distributed under the NPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
+ * for the specific language governing rights and limitations under the
+ * NPL.
+ *
+ * The Initial Developer of this code under the NPL is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation. All Rights
+ * Reserved.
+ */
+
+#include "nsIPresContext.h"
+#include "nsTableBorderCollapser.h"
+#include "nsTableFrame.h"
+#include "nsTableCellFrame.h"
+#include "nsTableColFrame.h"
+#include "nsCellMap.h"
+#include "cellData.h"
+
+nsTableBorderCollapser::nsTableBorderCollapser(nsTableFrame& aTableFrame)
+:mTableFrame(aTableFrame)
+{
+}
+
+nsTableBorderCollapser::~nsTableBorderCollapser()
+{
+ for (PRInt32 sideX = 0; sideX < 4; sideX++) {
+ nsBorderEdge* border = (nsBorderEdge *)(mBorderEdges.mEdges[sideX].ElementAt(0));
+ while (border) {
+ delete border;
+ mBorderEdges.mEdges[sideX].RemoveElementAt(0);
+ border = (nsBorderEdge *)(mBorderEdges.mEdges[sideX].ElementAt(0));
+ }
+ }
+}
+
+void nsTableBorderCollapser::SetBorderEdgeLength(PRUint8 aSide,
+ PRInt32 aIndex,
+ nscoord aLength)
+{
+ nsBorderEdge* border = (nsBorderEdge *)(mBorderEdges.mEdges[aSide].ElementAt(aIndex));
+ if (border) {
+ border->mLength = aLength;
+ }
+}
+
+void nsTableBorderCollapser::DidComputeHorizontalBorders(nsIPresContext& aPresContext,
+ PRInt32 aStartRowIndex,
+ PRInt32 aEndRowIndex)
+{
+ // XXX: for now, this only does table edges. May need to do interior edges also? Probably not.
+ PRInt32 lastRowIndex = mTableFrame.GetRowCount() - 1;
+ PRInt32 lastColIndex = mTableFrame.GetColCount() - 1;
+ if (0 == aStartRowIndex) {
+ nsTableCellFrame* cellFrame = mTableFrame.GetCellInfoAt(0, 0);
+ nsRect rowRect(0,0,0,0);
+ if (cellFrame) {
+ nsIFrame* rowFrame;
+ cellFrame->GetParent(&rowFrame);
+ rowFrame->GetRect(rowRect);
+ nsBorderEdge* leftBorder = (nsBorderEdge *)(mBorderEdges.mEdges[NS_SIDE_LEFT].ElementAt(0));
+ nsBorderEdge* rightBorder = (nsBorderEdge *)(mBorderEdges.mEdges[NS_SIDE_RIGHT].ElementAt(0));
+ nsBorderEdge* topBorder = (nsBorderEdge *)(mBorderEdges.mEdges[NS_SIDE_TOP].ElementAt(0));
+ if (leftBorder)
+ leftBorder->mLength = rowRect.height + topBorder->mWidth;
+ if (topBorder)
+ topBorder = (nsBorderEdge *)(mBorderEdges.mEdges[NS_SIDE_TOP].ElementAt(lastColIndex));
+ if (rightBorder)
+ rightBorder->mLength = rowRect.height + topBorder->mWidth;
+ }
+ }
+
+ if (lastRowIndex <= aEndRowIndex) {
+ nsTableCellFrame* cellFrame = mTableFrame.GetCellInfoAt(lastRowIndex, 0);
+ nsRect rowRect(0,0,0,0);
+ if (cellFrame) {
+ nsIFrame* rowFrame;
+ cellFrame->GetParent(&rowFrame);
+ rowFrame->GetRect(rowRect);
+ nsBorderEdge* leftBorder = (nsBorderEdge *)(mBorderEdges.mEdges[NS_SIDE_LEFT].ElementAt(lastRowIndex));
+ nsBorderEdge* rightBorder = (nsBorderEdge *)(mBorderEdges.mEdges[NS_SIDE_RIGHT].ElementAt(lastRowIndex));
+ nsBorderEdge* bottomBorder = (nsBorderEdge *)(mBorderEdges.mEdges[NS_SIDE_BOTTOM].ElementAt(0));
+ if (leftBorder)
+ leftBorder->mLength = rowRect.height + bottomBorder->mWidth;
+ if (bottomBorder)
+ bottomBorder = (nsBorderEdge *)(mBorderEdges.mEdges[NS_SIDE_BOTTOM].ElementAt(lastColIndex));
+ if (rightBorder)
+ rightBorder->mLength = rowRect.height + bottomBorder->mWidth;
+ }
+ }
+
+ for (PRInt32 borderX = NS_SIDE_TOP; borderX <= NS_SIDE_LEFT; borderX++) {
+ if (!mBorderEdges.mEdges[borderX].ElementAt(0)) {
+ mBorderEdges.mEdges[borderX].AppendElement(new nsBorderEdge());
+ }
+ }
+}
+
+
+ // For every row between aStartRowIndex and aEndRowIndex (-1 == the end of the table),
+ // walk across every edge and compute the border at that edge.
+ // We compute each edge only once, arbitrarily choosing to compute right and bottom edges,
+ // except for exterior cells that share a left or top edge with the table itself.
+ // Distribute half the computed border to the appropriate adjacent objects
+ // (always a cell frame or the table frame.) In the case of odd width,
+ // the object on the right/bottom gets the extra portion
+
+/* compute the top and bottom collapsed borders between aStartRowIndex and aEndRowIndex, inclusive */
+void nsTableBorderCollapser::ComputeHorizontalBorders(nsIPresContext& aPresContext,
+ PRInt32 aStartRowIndex,
+ PRInt32 aEndRowIndex)
+{
+ PRInt32 colCount = mTableFrame.GetColCount();
+ PRInt32 rowCount = mTableFrame.GetRowCount();
+ if (aStartRowIndex >= rowCount) {
+ return; // we don't have the requested row yet
+ }
+
+ for (PRInt32 rowIndex = aStartRowIndex; (rowIndex < rowCount) && (rowIndex <= aEndRowIndex); rowIndex++) {
+ for (PRInt32 colIndex = 0; colIndex < colCount; colIndex++) {
+ if (0 == rowIndex) { // table is top neighbor
+ ComputeTopBorderForEdgeAt(aPresContext, rowIndex, colIndex);
+ }
+ ComputeBottomBorderForEdgeAt(aPresContext, rowIndex, colIndex);
+ }
+ }
+}
+
+/* compute the left and right collapsed borders between aStartRowIndex and aEndRowIndex, inclusive */
+void nsTableBorderCollapser::ComputeVerticalBorders(nsIPresContext& aPresContext,
+ PRInt32 aStartRowIndex,
+ PRInt32 aEndRowIndex)
+{
+ //nsCellMap* cellMap = mTableFrame.GetCellMap();
+ //if (nsnull == cellMap)
+ // return; // no info yet, so nothing useful to do
+
+ mTableFrame.CacheColFrames(aPresContext); // XXX why here?
+
+ // compute all the collapsing border values for the entire table
+ // XXX: we have to make this more incremental!
+
+ PRInt32 colCount = mTableFrame.GetColCount();
+ PRInt32 rowCount = mTableFrame.GetRowCount();
+ PRInt32 endRowIndex = aEndRowIndex;
+ if (-1 == endRowIndex)
+ endRowIndex = rowCount-1;
+ if (aStartRowIndex >= rowCount) {
+ return; // we don't have the requested row yet
+ }
+
+ for (PRInt32 rowX = aStartRowIndex; (rowX < rowCount) && (rowX <= endRowIndex); rowX++) {
+ for (PRInt32 colX = 0; colX < colCount; colX++) {
+ if (0 == colX) { // table is left neighbor
+ ComputeLeftBorderForEdgeAt(aPresContext, rowX, colX);
+ }
+ ComputeRightBorderForEdgeAt(aPresContext, rowX, colX);
+ }
+ }
+}
+
+void nsTableBorderCollapser::ComputeLeftBorderForEdgeAt(nsIPresContext& aPresContext,
+ PRInt32 aRowIndex,
+ PRInt32 aColIndex)
+{
+ PRInt32 numSegments = mBorderEdges.mEdges[NS_SIDE_LEFT].Count();
+ while (numSegments <= aRowIndex) {
+ nsBorderEdge* borderToAdd = new nsBorderEdge();
+ mBorderEdges.mEdges[NS_SIDE_LEFT].AppendElement(borderToAdd);
+ numSegments++;
+ }
+ // "border" is the border segment we are going to set
+ nsBorderEdge *border = (nsBorderEdge *)(mBorderEdges.mEdges[NS_SIDE_LEFT].ElementAt(aRowIndex));
+ if (!border)
+ return;
+
+ // collect all the incident frames and compute the dominant border
+ nsVoidArray styles;
+ // styles are added to the array in the order least dominant -> most dominant
+ // 1. table
+ const nsStyleSpacing *spacing;
+ mTableFrame.GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
+ styles.AppendElement((void*)spacing);
+ // 2. colgroup
+ nsTableColFrame* colFrame;
+ mTableFrame.GetColumnFrame(aColIndex, colFrame);
+ nsIFrame* colGroupFrame;
+ colFrame->GetParent(&colGroupFrame);
+ colGroupFrame->GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
+ styles.AppendElement((void*)spacing);
+ // 3. col
+ colFrame->GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
+ styles.AppendElement((void*)spacing);
+ // 4. rowgroup
+ nsTableCellFrame* cellFrame = mTableFrame.GetCellInfoAt(aRowIndex, aColIndex);
+ nsRect rowRect(0,0,0,0);
+ if (cellFrame) {
+ nsIFrame* rowFrame;
+ cellFrame->GetParent(&rowFrame);
+ rowFrame->GetRect(rowRect);
+ nsIFrame* rowGroupFrame;
+ rowFrame->GetParent(&rowGroupFrame);
+ rowGroupFrame->GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
+ styles.AppendElement((void*)spacing);
+ // 5. row
+ rowFrame->GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
+ styles.AppendElement((void*)spacing);
+ // 6. cell (need to do something smart for rowspanner with row frame)
+ cellFrame->GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
+ styles.AppendElement((void*)spacing);
+ }
+ ComputeBorderSegment(NS_SIDE_LEFT, &styles, *border, PR_FALSE);
+ // now give half the computed border to the table segment, and half to the cell
+ // to avoid rounding errors, we convert up to pixels, divide by 2, and
+ // we give the odd pixel to the table border
+ float t2p;
+ aPresContext.GetTwipsToPixels(&t2p);
+ float p2t;
+ aPresContext.GetPixelsToTwips(&p2t);
+ nscoord widthAsPixels = NSToCoordRound((float)(border->mWidth)*t2p);
+ nscoord widthToAdd = 0;
+ border->mWidth = widthAsPixels/2;
+ if ((border->mWidth*2)!=widthAsPixels)
+ widthToAdd = NSToCoordCeil(p2t);
+ border->mWidth *= NSToCoordCeil(p2t);
+ border->mLength = rowRect.height;
+ border->mInsideNeighbor = cellFrame->mBorderEdges;
+ // we need to factor in the table's horizontal borders.
+ // but we can't compute that length here because we don't know how thick top and bottom borders are
+ // see DidComputeHorizontalCollapsingBorders
+ if (nsnull!=cellFrame)
+ {
+ cellFrame->SetBorderEdge(NS_SIDE_LEFT, aRowIndex, aColIndex, border, 0); // set the left edge of the cell frame
+ }
+ border->mWidth += widthToAdd;
+ mBorderEdges.mMaxBorderWidth.left = PR_MAX(border->mWidth, mBorderEdges.mMaxBorderWidth.left);
+}
+
+void nsTableBorderCollapser::ComputeRightBorderForEdgeAt(nsIPresContext& aPresContext,
+ PRInt32 aRowIndex,
+ PRInt32 aColIndex)
+{
+ nsCellMap* cellMap = mTableFrame.GetCellMap();
+ if (!cellMap) {
+ return;
+ }
+
+ PRInt32 colCount = mTableFrame.GetColCount();
+ PRInt32 numSegments = mBorderEdges.mEdges[NS_SIDE_RIGHT].Count();
+ while (numSegments <= aRowIndex) {
+ nsBorderEdge* borderToAdd = new nsBorderEdge();
+ mBorderEdges.mEdges[NS_SIDE_RIGHT].AppendElement(borderToAdd);
+ numSegments++;
+ }
+ // "border" is the border segment we are going to set
+ nsBorderEdge border;
+
+ // collect all the incident frames and compute the dominant border
+ nsVoidArray styles;
+ // styles are added to the array in the order least dominant -> most dominant
+ // 1. table, only if this cell is in the right-most column and no rowspanning cell is
+ // to it's right. Otherwise, we remember what cell is the right neighbor
+ nsTableCellFrame* rightNeighborFrame=nsnull;
+
+ if ((colCount - 1) != aColIndex) {
+ for (PRInt32 colIndex = aColIndex + 1; colIndex < colCount; colIndex++) {
+ CellData* cd = cellMap->GetCellAt(aRowIndex, colIndex);
+ if (cd) { // there's really a cell at (aRowIndex, colIndex)
+ if (!cd->mOrigCell) { // the cell at (aRowIndex, colIndex) is the result of a span
+ nsTableCellFrame* cell = nsnull;
+ if (cd->mRowSpanData)
+ cell = cd->mRowSpanData->mOrigCell;
+ else if (cd->mColSpanData)
+ cell = cd->mColSpanData->mOrigCell;
+ NS_ASSERTION(cell, "bad cell map state, missing real cell");
+ PRInt32 realRowIndex;
+ cell->GetRowIndex (realRowIndex);
+ if (realRowIndex!=aRowIndex) { // the span is caused by a rowspan
+ rightNeighborFrame = cd->mRowSpanData->mOrigCell;
+ break;
+ }
+ }
+ else {
+ rightNeighborFrame = cd->mOrigCell;
+ break;
+ }
+ }
+ }
+ }
+ const nsStyleSpacing *spacing;
+ if (!rightNeighborFrame) {
+ // if rightNeighborFrame is null, our right neighbor is the table
+ mTableFrame.GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
+ styles.AppendElement((void*)spacing);
+ }
+ // 2. colgroup //XXX: need to test if we're really on a colgroup border
+ nsTableColFrame* colFrame = cellMap->GetColumnFrame(aColIndex);
+ nsIFrame* colGroupFrame;
+ colFrame->GetParent(&colGroupFrame);
+ colGroupFrame->GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
+ styles.AppendElement((void*)spacing);
+ // 3. col
+ colFrame->GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
+ styles.AppendElement((void*)spacing);
+ // 4. rowgroup
+ nsTableCellFrame* cellFrame = cellMap->GetCellInfoAt(aRowIndex, aColIndex);
+ nsRect rowRect(0,0,0,0);
+ if (cellFrame) {
+ nsIFrame* rowFrame;
+ cellFrame->GetParent(&rowFrame);
+ rowFrame->GetRect(rowRect);
+ nsIFrame* rowGroupFrame;
+ rowFrame->GetParent(&rowGroupFrame);
+ if (!rightNeighborFrame) {
+ // if rightNeighborFrame is null, our right neighbor is the table so we include the rowgroup and row
+ rowGroupFrame->GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
+ styles.AppendElement((void*)spacing);
+ // 5. row
+ rowFrame->GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
+ styles.AppendElement((void*)spacing);
+ }
+ // 6. cell (need to do something smart for rowspanner with row frame)
+ cellFrame->GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
+ styles.AppendElement((void*)spacing);
+ }
+ // 7. left edge of rightNeighborCell, if there is one
+ if (rightNeighborFrame) {
+ rightNeighborFrame->GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
+ styles.AppendElement((void*)spacing);
+ }
+ ComputeBorderSegment(NS_SIDE_RIGHT, &styles, border, (nsnull != rightNeighborFrame));
+ // now give half the computed border to each of the two neighbors
+ // (the 2 cells, or the cell and the table)
+ // to avoid rounding errors, we convert up to pixels, divide by 2, and
+ // we give the odd pixel to the right cell border
+ float t2p;
+ aPresContext.GetTwipsToPixels(&t2p);
+ float p2t;
+ aPresContext.GetPixelsToTwips(&p2t);
+ nscoord widthAsPixels = NSToCoordRound((float)(border.mWidth)*t2p);
+ nscoord widthToAdd = 0;
+ border.mWidth = widthAsPixels/2;
+ if ((border.mWidth*2) != widthAsPixels)
+ widthToAdd = NSToCoordCeil(p2t);
+ border.mWidth *= NSToCoordCeil(p2t);
+ border.mLength = rowRect.height;
+ if (cellFrame) {
+ cellFrame->SetBorderEdge(NS_SIDE_RIGHT, aRowIndex, aColIndex, &border, widthToAdd);
+ }
+ if (!rightNeighborFrame) {
+ nsBorderEdge * tableBorder = (nsBorderEdge *)(mBorderEdges.mEdges[NS_SIDE_RIGHT].ElementAt(aRowIndex));
+ *tableBorder = border;
+ if (cellFrame) {
+ tableBorder->mInsideNeighbor = cellFrame->mBorderEdges;
+ }
+ mBorderEdges.mMaxBorderWidth.right = PR_MAX(border.mWidth, mBorderEdges.mMaxBorderWidth.right);
+ // since the table is our right neightbor, we need to factor in the table's horizontal borders.
+ // can't compute that length here because we don't know how thick top and bottom borders are
+ // see DidComputeHorizontalCollapsingBorders
+ }
+ else {
+ rightNeighborFrame->SetBorderEdge(NS_SIDE_LEFT, aRowIndex, aColIndex, &border, 0);
+ }
+}
+
+void nsTableBorderCollapser::ComputeTopBorderForEdgeAt(nsIPresContext& aPresContext,
+ PRInt32 aRowIndex,
+ PRInt32 aColIndex)
+{
+ nsCellMap* cellMap = mTableFrame.GetCellMap();
+ if (!cellMap) {
+ return;
+ }
+
+ PRInt32 numSegments = mBorderEdges.mEdges[NS_SIDE_TOP].Count();
+ while (numSegments<=aColIndex) {
+ nsBorderEdge* borderToAdd = new nsBorderEdge();
+ mBorderEdges.mEdges[NS_SIDE_TOP].AppendElement(borderToAdd);
+ numSegments++;
+ }
+ // "border" is the border segment we are going to set
+ nsBorderEdge *border = (nsBorderEdge *)(mBorderEdges.mEdges[NS_SIDE_TOP].ElementAt(aColIndex));
+ if (!border)
+ return;
+
+ // collect all the incident frames and compute the dominant border
+ nsVoidArray styles;
+ // styles are added to the array in the order least dominant -> most dominant
+ // 1. table
+ const nsStyleSpacing *spacing;
+ mTableFrame.GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
+ styles.AppendElement((void*)spacing);
+ // 2. colgroup
+ nsTableColFrame* colFrame = cellMap->GetColumnFrame(aColIndex);
+ nsIFrame* colGroupFrame;
+ colFrame->GetParent(&colGroupFrame);
+ colGroupFrame->GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
+ styles.AppendElement((void*)spacing);
+ // 3. col
+ colFrame->GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
+ styles.AppendElement((void*)spacing);
+ // 4. rowgroup
+ nsTableCellFrame* cellFrame = cellMap->GetCellInfoAt(aRowIndex, aColIndex);
+ if (cellFrame) {
+ nsIFrame* rowFrame;
+ cellFrame->GetParent(&rowFrame);
+ nsIFrame* rowGroupFrame;
+ rowFrame->GetParent(&rowGroupFrame);
+ rowGroupFrame->GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
+ styles.AppendElement((void*)spacing);
+ // 5. row
+ rowFrame->GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
+ styles.AppendElement((void*)spacing);
+ // 6. cell (need to do something smart for rowspanner with row frame)
+ cellFrame->GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
+ styles.AppendElement((void*)spacing);
+ }
+ ComputeBorderSegment(NS_SIDE_TOP, &styles, *border, PR_FALSE);
+ // now give half the computed border to the table segment, and half to the cell
+ // to avoid rounding errors, we convert up to pixels, divide by 2, and
+ // we give the odd pixel to the right border
+ float t2p;
+ aPresContext.GetTwipsToPixels(&t2p);
+ float p2t;
+ aPresContext.GetPixelsToTwips(&p2t);
+ nscoord widthAsPixels = NSToCoordRound((float)(border->mWidth)*t2p);
+ nscoord widthToAdd = 0;
+ border->mWidth = widthAsPixels/2;
+ if ((border->mWidth*2) != widthAsPixels)
+ widthToAdd = NSToCoordCeil(p2t);
+ border->mWidth *= NSToCoordCeil(p2t);
+ border->mLength = mTableFrame.GetColumnWidth(aColIndex);
+ border->mInsideNeighbor = cellFrame->mBorderEdges;
+ if (0 == aColIndex) {
+ // if we're the first column, factor in the thickness of the left table border
+ nsBorderEdge *leftBorder = (nsBorderEdge *)(mBorderEdges.mEdges[NS_SIDE_LEFT].ElementAt(0));
+ if (leftBorder)
+ border->mLength += leftBorder->mWidth;
+ }
+ if ((cellMap->GetColCount() - 1) == aColIndex) {
+ // if we're the last column, factor in the thickness of the right table border
+ nsBorderEdge* rightBorder = (nsBorderEdge *)(mBorderEdges.mEdges[NS_SIDE_RIGHT].ElementAt(0));
+ if (rightBorder)
+ border->mLength += rightBorder->mWidth;
+ }
+ if (cellFrame) {
+ cellFrame->SetBorderEdge(NS_SIDE_TOP, aRowIndex, aColIndex, border, 0); // set the top edge of the cell frame
+ }
+ border->mWidth += widthToAdd;
+ mBorderEdges.mMaxBorderWidth.top = PR_MAX(border->mWidth, mBorderEdges.mMaxBorderWidth.top);
+}
+
+void nsTableBorderCollapser::ComputeBottomBorderForEdgeAt(nsIPresContext& aPresContext,
+ PRInt32 aRowIndex,
+ PRInt32 aColIndex)
+{
+ nsCellMap* cellMap = mTableFrame.GetCellMap();
+ if (!cellMap) {
+ return;
+ }
+
+ PRInt32 rowCount = cellMap->GetRowCount();
+ PRInt32 numSegments = mBorderEdges.mEdges[NS_SIDE_BOTTOM].Count();
+ while (numSegments <= aColIndex) {
+ nsBorderEdge* borderToAdd = new nsBorderEdge();
+ mBorderEdges.mEdges[NS_SIDE_BOTTOM].AppendElement(borderToAdd);
+ numSegments++;
+ }
+ // "border" is the border segment we are going to set
+ nsBorderEdge border;
+
+ // collect all the incident frames and compute the dominant border
+ nsVoidArray styles;
+ // styles are added to the array in the order least dominant -> most dominant
+ // 1. table, only if this cell is in the bottom-most row and no colspanning cell is
+ // beneath it. Otherwise, we remember what cell is the bottom neighbor
+ nsTableCellFrame* bottomNeighborFrame=nsnull;
+ if ((rowCount-1) != aRowIndex) {
+ for (PRInt32 rowIndex = aRowIndex + 1; rowIndex < rowCount; rowIndex++) {
+ CellData* cd = cellMap->GetCellAt(rowIndex, aColIndex);
+ if (cd) { // there's really a cell at (rowIndex, aColIndex)
+ if (!cd->mOrigCell) {
+ // the cell at (rowIndex, aColIndex) is the result of a span
+ nsTableCellFrame* cell = nsnull;
+ if (cd->mRowSpanData) // XXX should we check for a row span
+ cell = cd->mRowSpanData->mOrigCell;
+ else if (cd->mColSpanData)
+ cell = cd->mColSpanData->mOrigCell;
+ NS_ASSERTION( cell, "bad cell map state, missing real cell");
+ PRInt32 realColIndex;
+ cell->GetColIndex (realColIndex);
+ if (realColIndex!=aColIndex) { // the span is caused by a colspan
+ bottomNeighborFrame = cd->mColSpanData->mOrigCell;
+ break;
+ }
+ }
+ else {
+ bottomNeighborFrame = cd->mOrigCell;
+ break;
+ }
+ }
+ }
+ }
+ const nsStyleSpacing *spacing;
+ if (!bottomNeighborFrame) {
+ // if bottomNeighborFrame is null, our bottom neighbor is the table
+ mTableFrame.GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
+ styles.AppendElement((void*)spacing);
+
+ // 2. colgroup // XXX: need to deterine if we're on a colgroup boundary
+ nsTableColFrame* colFrame = cellMap->GetColumnFrame(aColIndex);
+ nsIFrame* colGroupFrame;
+ colFrame->GetParent(&colGroupFrame);
+ colGroupFrame->GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
+ styles.AppendElement((void*)spacing);
+ // 3. col
+ colFrame->GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
+ styles.AppendElement((void*)spacing);
+ }
+ // 4. rowgroup // XXX: use rowgroup only if we're on a table edge
+ nsTableCellFrame* cellFrame = cellMap->GetCellInfoAt(aRowIndex, aColIndex);
+ nsRect rowRect(0,0,0,0);
+ if (cellFrame) {
+ nsIFrame* rowFrame;
+ cellFrame->GetParent(&rowFrame);
+ rowFrame->GetRect(rowRect);
+ nsIFrame* rowGroupFrame;
+ rowFrame->GetParent(&rowGroupFrame);
+ rowGroupFrame->GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
+ styles.AppendElement((void*)spacing);
+ // 5. row
+ rowFrame->GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
+ styles.AppendElement((void*)spacing);
+ // 6. cell (need to do something smart for rowspanner with row frame)
+ cellFrame->GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
+ styles.AppendElement((void*)spacing);
+ }
+ // 7. top edge of bottomNeighborCell, if there is one
+ if (bottomNeighborFrame) {
+ bottomNeighborFrame->GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
+ styles.AppendElement((void*)spacing);
+ }
+ ComputeBorderSegment(NS_SIDE_BOTTOM, &styles, border, (nsnull != bottomNeighborFrame));
+ // now give half the computed border to each of the two neighbors
+ // (the 2 cells, or the cell and the table)
+ // to avoid rounding errors, we convert up to pixels, divide by 2, and
+ // we give the odd pixel to the right cell border
+ float t2p;
+ aPresContext.GetTwipsToPixels(&t2p);
+ float p2t;
+ aPresContext.GetPixelsToTwips(&p2t);
+ nscoord widthAsPixels = NSToCoordRound((float)(border.mWidth)*t2p);
+ nscoord widthToAdd = 0;
+ border.mWidth = widthAsPixels/2;
+ if ((border.mWidth*2) != widthAsPixels)
+ widthToAdd = NSToCoordCeil(p2t);
+ border.mWidth *= NSToCoordCeil(p2t);
+ border.mLength = mTableFrame.GetColumnWidth(aColIndex);
+ if (cellFrame) {
+ cellFrame->SetBorderEdge(NS_SIDE_BOTTOM, aRowIndex, aColIndex, &border, widthToAdd);
+ }
+ if (!bottomNeighborFrame) {
+ nsBorderEdge* tableBorder = (nsBorderEdge *)(mBorderEdges.mEdges[NS_SIDE_BOTTOM].ElementAt(aColIndex));
+ *tableBorder = border;
+ if (cellFrame) {
+ tableBorder->mInsideNeighbor = cellFrame->mBorderEdges;
+ }
+ mBorderEdges.mMaxBorderWidth.bottom = PR_MAX(border.mWidth, mBorderEdges.mMaxBorderWidth.bottom);
+ // since the table is our bottom neightbor, we need to factor in the table's vertical borders.
+ PRInt32 lastColIndex = cellMap->GetColCount()-1;
+ if (0 == aColIndex) {
+ // if we're the first column, factor in the thickness of the left table border
+ nsBorderEdge *leftBorder = (nsBorderEdge *)(mBorderEdges.mEdges[NS_SIDE_LEFT].ElementAt(rowCount-1));
+ if (leftBorder)
+ tableBorder->mLength += leftBorder->mWidth;
+ }
+ if (lastColIndex == aColIndex) {
+ // if we're the last column, factor in the thickness of the right table border
+ nsBorderEdge *rightBorder = (nsBorderEdge *)(mBorderEdges.mEdges[NS_SIDE_RIGHT].ElementAt(rowCount-1));
+ if (rightBorder)
+ tableBorder->mLength += rightBorder->mWidth;
+ }
+ }
+ else
+ {
+ bottomNeighborFrame->SetBorderEdge(NS_SIDE_TOP, aRowIndex, aColIndex, &border, 0);
+ }
+}
+
+nscoord nsTableBorderCollapser::GetWidthForSide(const nsMargin& aBorder,
+ PRUint8 aSide)
+{
+ if (NS_SIDE_LEFT == aSide)
+ return aBorder.left;
+ else if (NS_SIDE_RIGHT == aSide)
+ return aBorder.right;
+ else if (NS_SIDE_TOP == aSide)
+ return aBorder.top;
+ else
+ return aBorder.bottom;
+}
+
+/* Given an Edge, find the opposing edge (top<-->bottom, left<-->right) */
+PRUint8 nsTableBorderCollapser::GetOpposingEdge(PRUint8 aEdge)
+{
+ PRUint8 result;
+ switch (aEdge)
+ {
+ case NS_SIDE_LEFT:
+ result = NS_SIDE_RIGHT; break;
+ case NS_SIDE_RIGHT:
+ result = NS_SIDE_LEFT; break;
+ case NS_SIDE_TOP:
+ result = NS_SIDE_BOTTOM; break;
+ case NS_SIDE_BOTTOM:
+ result = NS_SIDE_TOP; break;
+ default:
+ result = NS_SIDE_TOP;
+ }
+ return result;
+}
+
+/* returns BORDER_PRECEDENT_LOWER if aStyle1 is lower precedent that aStyle2
+ * BORDER_PRECEDENT_HIGHER if aStyle1 is higher precedent that aStyle2
+ * BORDER_PRECEDENT_EQUAL if aStyle1 and aStyle2 have the same precedence
+ * (note, this is not necessarily the same as saying aStyle1==aStyle2)
+ * this is a method on nsTableFrame because other objects might define their
+ * own border precedence rules.
+ */
+PRUint8 nsTableBorderCollapser::CompareBorderStyles(PRUint8 aStyle1,
+ PRUint8 aStyle2)
+{
+ PRUint8 result=BORDER_PRECEDENT_HIGHER; // if we get illegal types for table borders, HIGHER is the default
+ if (aStyle1 == aStyle2)
+ result = BORDER_PRECEDENT_EQUAL;
+ else if (NS_STYLE_BORDER_STYLE_HIDDEN==aStyle1)
+ result = BORDER_PRECEDENT_HIGHER;
+ else if (NS_STYLE_BORDER_STYLE_NONE==aStyle1)
+ result = BORDER_PRECEDENT_LOWER;
+ else if (NS_STYLE_BORDER_STYLE_NONE==aStyle2)
+ result = BORDER_PRECEDENT_HIGHER;
+ else if (NS_STYLE_BORDER_STYLE_HIDDEN==aStyle2)
+ result = BORDER_PRECEDENT_LOWER;
+ else {
+ switch (aStyle1) {
+ case NS_STYLE_BORDER_STYLE_BG_INSET:
+ result = BORDER_PRECEDENT_LOWER;
+ break;
+
+ case NS_STYLE_BORDER_STYLE_GROOVE:
+ if (NS_STYLE_BORDER_STYLE_BG_INSET==aStyle2)
+ result = BORDER_PRECEDENT_HIGHER;
+ else
+ result = BORDER_PRECEDENT_LOWER;
+ break;
+
+ case NS_STYLE_BORDER_STYLE_BG_OUTSET:
+ if (NS_STYLE_BORDER_STYLE_BG_INSET==aStyle2 ||
+ NS_STYLE_BORDER_STYLE_GROOVE==aStyle2)
+ result = BORDER_PRECEDENT_HIGHER;
+ else
+ result = BORDER_PRECEDENT_LOWER;
+ break;
+
+ case NS_STYLE_BORDER_STYLE_RIDGE:
+ if (NS_STYLE_BORDER_STYLE_BG_INSET==aStyle2 ||
+ NS_STYLE_BORDER_STYLE_GROOVE==aStyle2 ||
+ NS_STYLE_BORDER_STYLE_BG_OUTSET==aStyle2)
+ result = BORDER_PRECEDENT_HIGHER;
+ else
+ result = BORDER_PRECEDENT_LOWER;
+ break;
+
+ case NS_STYLE_BORDER_STYLE_DOTTED:
+ if (NS_STYLE_BORDER_STYLE_BG_INSET==aStyle2 ||
+ NS_STYLE_BORDER_STYLE_GROOVE==aStyle2 ||
+ NS_STYLE_BORDER_STYLE_BG_OUTSET==aStyle2 ||
+ NS_STYLE_BORDER_STYLE_RIDGE==aStyle2)
+ result = BORDER_PRECEDENT_HIGHER;
+ else
+ result = BORDER_PRECEDENT_LOWER;
+ break;
+
+ case NS_STYLE_BORDER_STYLE_DASHED:
+ if (NS_STYLE_BORDER_STYLE_BG_INSET==aStyle2 ||
+ NS_STYLE_BORDER_STYLE_GROOVE==aStyle2 ||
+ NS_STYLE_BORDER_STYLE_BG_OUTSET==aStyle2 ||
+ NS_STYLE_BORDER_STYLE_RIDGE==aStyle2 ||
+ NS_STYLE_BORDER_STYLE_DOTTED==aStyle2)
+ result = BORDER_PRECEDENT_HIGHER;
+ else
+ result = BORDER_PRECEDENT_LOWER;
+ break;
+
+ case NS_STYLE_BORDER_STYLE_SOLID:
+ if (NS_STYLE_BORDER_STYLE_BG_INSET==aStyle2 ||
+ NS_STYLE_BORDER_STYLE_GROOVE==aStyle2 ||
+ NS_STYLE_BORDER_STYLE_BG_OUTSET==aStyle2 ||
+ NS_STYLE_BORDER_STYLE_RIDGE==aStyle2 ||
+ NS_STYLE_BORDER_STYLE_DOTTED==aStyle2 ||
+ NS_STYLE_BORDER_STYLE_DASHED==aStyle2)
+ result = BORDER_PRECEDENT_HIGHER;
+ else
+ result = BORDER_PRECEDENT_LOWER;
+ break;
+
+ case NS_STYLE_BORDER_STYLE_DOUBLE:
+ result = BORDER_PRECEDENT_LOWER;
+ break;
+ }
+ }
+ return result;
+}
+
+/*
+ This method is the CSS2 border conflict resolution algorithm
+ The spec says to resolve conflicts in this order:
+ 1. any border with the style HIDDEN wins
+ 2. the widest border with a style that is not NONE wins
+ 3. the border styles are ranked in this order, highest to lowest precedence:
+ 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.
+ This method assumes that the styles were added to aStyles in the reverse precedence order
+ of their frame type, so that styles that come later in the list win over style
+ earlier in the list if the tie-breaker gets down to #4.
+ This method sets the out-param aBorder with the resolved border attributes
+*/
+void nsTableBorderCollapser::ComputeBorderSegment(PRUint8 aSide,
+ nsVoidArray* aStyles,
+ nsBorderEdge &aBorder,
+ PRBool aFlipLastSide)
+{
+ if (aStyles) {
+ PRInt32 styleCount = aStyles->Count();
+ if (0 != styleCount) {
+ nsVoidArray sameWidthBorders;
+ nsStyleSpacing * spacing;
+ nsStyleSpacing * lastSpacing=nsnull;
+ nsMargin border;
+ PRInt32 maxWidth=0;
+ PRUint8 side = aSide;
+ PRInt32 i;
+ for (i = 0; i < styleCount; i++) {
+ spacing = (nsStyleSpacing *)(aStyles->ElementAt(i));
+ if (aFlipLastSide && (i == styleCount-1)) {
+ side = GetOpposingEdge(aSide);
+ lastSpacing = spacing;
+ }
+ if (spacing->GetBorderStyle(side) == NS_STYLE_BORDER_STYLE_HIDDEN) {
+ aBorder.mStyle=NS_STYLE_BORDER_STYLE_HIDDEN;
+ aBorder.mWidth=0;
+ return;
+ }
+ else if (spacing->GetBorderStyle(side)!=NS_STYLE_BORDER_STYLE_NONE) {
+ spacing->GetBorder(border);
+ nscoord borderWidth = GetWidthForSide(border, side);
+ if (borderWidth == maxWidth)
+ sameWidthBorders.AppendElement(spacing);
+ else if (borderWidth > maxWidth) {
+ maxWidth = borderWidth;
+ sameWidthBorders.Clear();
+ sameWidthBorders.AppendElement(spacing);
+ }
+ }
+ }
+ aBorder.mWidth = maxWidth;
+ // now we've gone through each overlapping border once, and we have a list
+ // of all styles with the same width. If there's more than one, resolve the
+ // conflict based on border style
+ styleCount = sameWidthBorders.Count();
+ if (0 == styleCount) { // all borders were of style NONE
+ aBorder.mWidth=0;
+ aBorder.mStyle=NS_STYLE_BORDER_STYLE_NONE;
+ return;
+ }
+ else if (1 == styleCount) { // there was just one border of the largest width
+ spacing = (nsStyleSpacing *)(sameWidthBorders.ElementAt(0));
+ side = aSide;
+ if (spacing == lastSpacing)
+ side = GetOpposingEdge(aSide);
+ if (!spacing->GetBorderColor(side, aBorder.mColor)) {
+ // XXX EEEK handle transparent border color somehow...
+ }
+ aBorder.mStyle = spacing->GetBorderStyle(side);
+ return;
+ }
+ else {
+ nsStyleSpacing* winningStyleBorder;
+ PRUint8 winningStyle=NS_STYLE_BORDER_STYLE_NONE;
+ for (i = 0; i < styleCount; i++) {
+ spacing = (nsStyleSpacing *)(sameWidthBorders.ElementAt(i));
+ side = aSide;
+ if (spacing == lastSpacing)
+ side = GetOpposingEdge(aSide);
+ PRUint8 thisStyle = spacing->GetBorderStyle(side);
+ PRUint8 borderCompare = CompareBorderStyles(thisStyle, winningStyle);
+ if (BORDER_PRECEDENT_HIGHER == borderCompare) {
+ winningStyle = thisStyle;
+ winningStyleBorder = spacing;
+ }
+ else if (BORDER_PRECEDENT_EQUAL == borderCompare) {
+ // we're in lowest-to-highest precedence order, so later border styles win
+ winningStyleBorder=spacing;
+ }
+ }
+ aBorder.mStyle = winningStyle;
+ side = aSide;
+ if (winningStyleBorder == lastSpacing)
+ side = GetOpposingEdge(aSide);
+ if (!winningStyleBorder->GetBorderColor(side, aBorder.mColor)) {
+ // XXX handle transparent border colors somehow
+ }
+ }
+ }
+ }
+
+}
+
+void nsTableBorderCollapser::GetBorder(nsMargin& aBorder)
+{
+ aBorder = mBorderEdges.mMaxBorderWidth;
+}
+
+void nsTableBorderCollapser::GetBorderAt(PRInt32 aRowIndex,
+ PRInt32 aColIndex,
+ nsMargin& aBorder)
+{
+ nsBorderEdge* border = (nsBorderEdge *)(mBorderEdges.mEdges[NS_SIDE_LEFT].ElementAt(aRowIndex));
+ if (border) {
+ aBorder.left = border->mWidth;
+ }
+ border = (nsBorderEdge *)(mBorderEdges.mEdges[NS_SIDE_RIGHT].ElementAt(aRowIndex));
+ if (border) {
+ aBorder.right = border->mWidth;
+ }
+ border = (nsBorderEdge *)(mBorderEdges.mEdges[NS_SIDE_TOP].ElementAt(aColIndex));
+ if (border) {
+ aBorder.top = border->mWidth;
+ }
+ border = (nsBorderEdge *)(mBorderEdges.mEdges[NS_SIDE_BOTTOM].ElementAt(aColIndex));
+ if (border) {
+ aBorder.bottom = border->mWidth;
+ }
+}
+
+void nsTableBorderCollapser::GetMaxBorder(PRInt32 aStartRowIndex,
+ PRInt32 aEndRowIndex,
+ PRInt32 aStartColIndex,
+ PRInt32 aEndColIndex,
+ nsMargin aBorder)
+{
+ aBorder.top = aBorder.right = aBorder.bottom = aBorder.left = 0;
+ for (PRInt32 rowX = aStartRowIndex; rowX <= aEndRowIndex; rowX++) {
+ for (PRInt32 colX = aStartColIndex; colX <= aEndColIndex; colX++) {
+ nsMargin border;
+ GetBorderAt(rowX, colX, border);
+ aBorder.top = PR_MAX(aBorder.top, border.top);
+ aBorder.right = PR_MAX(aBorder.right, border.right);
+ aBorder.bottom = PR_MAX(aBorder.bottom, border.bottom);
+ aBorder.left = PR_MAX(aBorder.left, border.left);
+ }
+ }
+}
diff --git a/mozilla/layout/html/table/src/nsTableBorderCollapser.h b/mozilla/layout/html/table/src/nsTableBorderCollapser.h
new file mode 100644
index 00000000000..0c460d9e65a
--- /dev/null
+++ b/mozilla/layout/html/table/src/nsTableBorderCollapser.h
@@ -0,0 +1,158 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * The contents of this file are subject to the Netscape Public License
+ * Version 1.0 (the "NPL"); you may not use this file except in
+ * compliance with the NPL. You may obtain a copy of the NPL at
+ * http://www.mozilla.org/NPL/
+ *
+ * Software distributed under the NPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
+ * for the specific language governing rights and limitations under the
+ * NPL.
+ *
+ * The Initial Developer of this code under the NPL is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation. All Rights
+ * Reserved.
+ */
+#ifndef nsTableBorderCollapser_h__
+#define nsTableBorderCollapser_h__
+
+#include "nsIStyleContext.h"
+class nsTableFrame;
+
+/**
+ * Class for handling CSS border-style:collapse
+ */
+class nsTableBorderCollapser
+{
+public:
+ nsTableBorderCollapser(nsTableFrame& aTableFrame);
+
+ ~nsTableBorderCollapser();
+
+ /** notification that top and bottom borders have been computed */
+ void DidComputeHorizontalBorders(nsIPresContext& aPresContext,
+ PRInt32 aStartRowIndex,
+ PRInt32 aEndRowIndex);
+
+ /** compute the left and right collapsed borders between aStartRowIndex and aEndRowIndex, inclusive */
+ void ComputeVerticalBorders(nsIPresContext& aPresContext,
+ PRInt32 aStartRowIndex,
+ PRInt32 aEndRowIndex);
+
+ /** compute the top and bottom collapsed borders between aStartRowIndex and aEndRowIndex, inclusive */
+ void ComputeHorizontalBorders(nsIPresContext& aPresContext,
+ PRInt32 aStartRowIndex,
+ PRInt32 aEndRowIndex);
+
+ /** compute the left borders for the table objects intersecting at (aRowIndex, aColIndex) */
+ void ComputeLeftBorderForEdgeAt(nsIPresContext& aPresContext,
+ PRInt32 aRowIndex,
+ PRInt32 aColIndex);
+
+ /** compute the right border for the table cell at (aRowIndex, aColIndex)
+ * and the appropriate border for that cell's right neighbor
+ * (the left border for a neighboring cell, or the right table edge)
+ */
+ void ComputeRightBorderForEdgeAt(nsIPresContext& aPresContext,
+ PRInt32 aRowIndex,
+ PRInt32 aColIndex);
+
+ /** compute the top borders for the table objects intersecting at (aRowIndex, aColIndex) */
+ void ComputeTopBorderForEdgeAt(nsIPresContext& aPresContext,
+ PRInt32 aRowIndex,
+ PRInt32 aColIndex);
+
+ /** compute the bottom border for the table cell at (aRowIndex, aColIndex)
+ * and the appropriate border for that cell's bottom neighbor
+ * (the top border for a neighboring cell, or the bottom table edge)
+ */
+ void ComputeBottomBorderForEdgeAt(nsIPresContext& aPresContext,
+ PRInt32 aRowIndex,
+ PRInt32 aColIndex);
+
+ /** at the time we initially compute collapsing borders, we don't yet have the
+ * column widths. So we set them as a post-process of the column balancing algorithm.
+ */
+ void SetHorizontalEdgeLengths();
+
+ /** @return the identifier representing the edge opposite from aEdge (left-right, top-bottom) */
+ PRUint8 GetOpposingEdge(PRUint8 aEdge);
+
+ /** @return the computed width for aSide of aBorder */
+ nscoord GetWidthForSide(const nsMargin& aBorder,
+ PRUint8 aSide);
+
+ /** returns BORDER_PRECEDENT_LOWER if aStyle1 is lower precedent that aStyle2
+ * BORDER_PRECEDENT_HIGHER if aStyle1 is higher precedent that aStyle2
+ * BORDER_PRECEDENT_EQUAL if aStyle1 and aStyle2 have the same precedence
+ * (note, this is not necessarily the same as saying aStyle1==aStyle2)
+ * according to the CSS-2 collapsing borders for tables precedent rules.
+ */
+ PRUint8 CompareBorderStyles(PRUint8 aStyle1,
+ PRUint8 aStyle2);
+
+ /** helper to set the length of an edge for aSide border of this table frame */
+ void SetBorderEdgeLength(PRUint8 aSide,
+ PRInt32 aIndex,
+ nscoord aLength);
+
+ /** Compute the style, width, and color of an edge in a collapsed-border table.
+ * This method is the CSS2 border conflict resolution algorithm
+ * The spec says to resolve conflicts in this order:
+ * 1. any border with the style HIDDEN wins
+ * 2. the widest border with a style that is not NONE wins
+ * 3. the border styles are ranked in this order, highest to lowest precedence:
+ * 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.
+ * This method assumes that the styles were added to aStyles in the reverse precedence order
+ * of their frame type, so that styles that come later in the list win over style
+ * earlier in the list if the tie-breaker gets down to #4.
+ * This method sets the out-param aBorder with the resolved border attributes
+ *
+ * @param aSide the side that is being compared
+ * @param aStyles the resolved styles of the table objects intersecting at aSide
+ * styles must be added to this list in reverse precedence order
+ * @param aBorder [OUT] the border edge that we're computing. Results of the computation
+ * are stored in aBorder: style, color, and width.
+ * @param aFlipLastSide an indication of what the bordering object is: another cell, or the table itself.
+ */
+ void ComputeBorderSegment(PRUint8 aSide,
+ nsVoidArray* aStyles,
+ nsBorderEdge& aBorder,
+ PRBool aFlipLastSide);
+
+ void GetBorder(nsMargin& aBorder);
+
+ void GetBorderAt(PRInt32 aRowIndex,
+ PRInt32 aColIndex,
+ nsMargin& aBorder);
+
+ void GetMaxBorder(PRInt32 aStartRowIndex,
+ PRInt32 aEndRowIndex,
+ PRInt32 aStartColIndex,
+ PRInt32 aEndColIndex,
+ nsMargin aBorder);
+
+ nsBorderEdges* GetEdges();
+
+protected:
+ nsBorderEdges mBorderEdges;
+ nsTableFrame& mTableFrame;
+};
+
+inline nsBorderEdges* nsTableBorderCollapser::GetEdges()
+{
+ return &mBorderEdges;
+}
+
+#endif
+
+
+
+
+
+