nsTableFrame::PaintBCBorders(nsIPresContext*      aPresContext,
nsTableFrame::PaintBCBorders(nsPresContext*      aPresContext,
nsTableFrame::PaintBCBorders(nsIPresContext*      aPresContext,                             nsIRenderingContext& aRenderingContext,                             const nsRect&        aDirtyRect){  nsMargin childAreaOffset = GetChildAreaOffset(nsnull);  nsTableFrame* firstInFlow = (nsTableFrame*)GetFirstInFlow(); if (!firstInFlow) ABORT0();  GET_PIXELS_TO_TWIPS(aPresContext, p2t);  PRInt32 startColX = childAreaOffset.left;                    // x position of first col in damage area  PRInt32 startRowY = (mPrevInFlow) ? 0 : childAreaOffset.top; // y position of first row in damage area  const nsStyleBackground* bgColor = nsCSSRendering::FindNonTransparentBackground(mStyleContext);  // determine the damage area in terms of rows and columns and finalize startColX and startRowY  PRUint32 startRowIndex, endRowIndex, startColIndex, endColIndex;  startRowIndex = endRowIndex = startColIndex = endColIndex = 0;  nsAutoVoidArray rowGroups;  PRUint32 numRowGroups;  OrderRowGroups(rowGroups, numRowGroups, nsnull);  PRBool done = PR_FALSE;  PRBool haveIntersect = PR_FALSE;  nsTableRowGroupFrame* inFlowRG  = nsnull;  nsTableRowFrame*      inFlowRow = nsnull;  // find startRowIndex, endRowIndex, startRowY  nscoord onePixel = NSToCoordRound(p2t);  PRInt32 rowY = startRowY;  for (PRUint32 rgX = 0; (rgX < numRowGroups) && !done; rgX++) {    nsIFrame* kidFrame = (nsIFrame*)rowGroups.ElementAt(rgX);    nsTableRowGroupFrame* rgFrame = GetRowGroupFrame(kidFrame); if (!rgFrame) ABORT0();    for (nsTableRowFrame* rowFrame = rgFrame->GetFirstRow(); rowFrame; rowFrame = rowFrame->GetNextRow()) {      // conservatively estimate the half border widths outside the row      nscoord topBorderHalf    = (mPrevInFlow) ? 0 : rowFrame->GetTopBCBorderWidth(&p2t) + onePixel;       nscoord bottomBorderHalf = (mNextInFlow) ? 0 : rowFrame->GetBottomBCBorderWidth(&p2t) + onePixel;      // get the row rect relative to the table rather than the row group      nsSize rowSize = rowFrame->GetSize();      if (haveIntersect) {        if (aDirtyRect.YMost() >= (rowY - topBorderHalf)) {          nsTableRowFrame* fifRow = (nsTableRowFrame*)rowFrame->GetFirstInFlow(); if (!fifRow) ABORT0();          endRowIndex = fifRow->GetRowIndex();        }        else done = PR_TRUE;      }      else {        if ((rowY + rowSize.height + bottomBorderHalf) >= aDirtyRect.y) {          inFlowRG  = rgFrame;          inFlowRow = rowFrame;          nsTableRowFrame* fifRow = (nsTableRowFrame*)rowFrame->GetFirstInFlow(); if (!fifRow) ABORT0();          startRowIndex = endRowIndex = fifRow->GetRowIndex();          haveIntersect = PR_TRUE;        }        else {          startRowY += rowSize.height;        }      }      rowY += rowSize.height;     }  }  if (!inFlowRG || !inFlowRow) ABORT0();  // find startColIndex, endColIndex, startColX  haveIntersect = PR_FALSE;  PRUint32 numCols = GetColCount();  if (0 == numCols) return;  nscoord x = 0;  for (PRUint32 colX = 0; colX < numCols; colX++) {    nsTableColFrame* colFrame = firstInFlow->GetColFrame(colX); if (!colFrame) ABORT0();    // conservatively estimate the half border widths outside the col    nscoord leftBorderHalf    = colFrame->GetLeftBorderWidth(&p2t) + onePixel;     nscoord rightBorderHalf   = colFrame->GetRightBorderWidth(&p2t) + onePixel;    // get the col rect relative to the table rather than the col group    nsSize size = colFrame->GetSize();    if (haveIntersect) {      if (aDirtyRect.XMost() >= (x - leftBorderHalf)) {        endColIndex = colX;      }      else break;    }    else {      if ((x + size.width + rightBorderHalf) >= aDirtyRect.x) {        startColIndex = endColIndex = colX;        haveIntersect = PR_TRUE;      }      else {        startColX += size.width;      }    }    x += size.width;  }  if (!haveIntersect)    return;  // iterate the cell map and build up border segments  nsRect damageArea(startColIndex, startRowIndex, 1 + endColIndex - startColIndex,                     1 + endRowIndex - startRowIndex);  BCVerticalSeg* verInfo = new BCVerticalSeg[damageArea.width + 1]; if (!verInfo) ABORT0();  BCBorderOwner borderOwner, ignoreBorderOwner;  PRUint8 ownerSide;  nscoord cornerSubWidth, smallHalf, largeHalf;  nsRect rowRect(0,0,0,0);  PRBool isSegStart, ignoreSegStart;  nscoord prevHorSegHeight = 0;  PRPackedBool bevel;  PRInt32 repeatedHeaderY = -99;  PRBool  afterRepeatedHeader = PR_FALSE;  PRBool  startRepeatedFooter = PR_FALSE;  // First, paint all of the vertical borders from top to bottom and left to right as they become complete  // They are painted first, since they are less efficient to paint than horizontal segments. They were   // stored with as few segments as possible (since horizontal borders are painted last and possibly over them).  BCMapBorderIterator iter(*this, *inFlowRG, *inFlowRow, damageArea);   for (iter.First(); !iter.atEnd; iter.Next()) {    nscoord verSegWidth = (iter.bcData) ? iter.bcData->GetLeftEdge(borderOwner, isSegStart) : 0;    nscoord horSegHeight = (iter.bcData) ? iter.bcData->GetTopEdge(ignoreBorderOwner, ignoreSegStart) : 0;    PRInt32 xAdj = iter.x - iter.startX;    if (iter.isNewRow) {      prevHorSegHeight = 0;      rowRect = iter.row->GetRect();      if (iter.isRepeatedHeader) {        repeatedHeaderY = iter.y;      }      afterRepeatedHeader = !iter.isRepeatedHeader && (iter.y == (repeatedHeaderY + 1));      startRepeatedFooter = iter.isRepeatedFooter && (iter.y == iter.rowGroupStart) && (iter.y != iter.startY);    }    BCVerticalSeg& info = verInfo[xAdj];    if (!info.col) { // on the first damaged row and the first segment in the col      info.col = iter.IsRightMostTable() ? verInfo[xAdj - 1].col : firstInFlow->GetColFrame(iter.x); if (!info.col) ABORT0();      if (0 == xAdj) {        info.colX = startColX;      }      // set colX for the next column      if (!iter.IsRightMost()) {        verInfo[xAdj + 1].colX = info.colX + info.col->GetSize().width;      }      info.segY = startRowY;       info.Start(iter, borderOwner, verSegWidth, prevHorSegHeight, horSegHeight, p2t, verInfo);      info.lastCell = iter.cell;    }    if (!iter.IsTopMost() && (isSegStart || iter.IsBottomMost() || afterRepeatedHeader || startRepeatedFooter)) {      // paint the previous seg or the current one if iter.IsBottomMost()      if (info.segHeight > 0) {        cornerSubWidth = (iter.bcData) ? iter.bcData->GetCorner(ownerSide, bevel) : 0;        PRBool endBevel = (info.segWidth > 0) ? bevel : PR_FALSE;         nscoord bottomHorSegHeight = PR_MAX(prevHorSegHeight, horSegHeight);         nscoord endOffset = CalcVerCornerOffset(ownerSide, cornerSubWidth, bottomHorSegHeight,                                                 PR_FALSE, endBevel, p2t);        info.segHeight += endOffset;        if (info.segWidth > 0) {               // get the border style, color and paint the segment          PRUint8 side = (iter.IsRightMost()) ? NS_SIDE_RIGHT : NS_SIDE_LEFT;          nsTableRowFrame* row           = info.firstRow;          nsTableRowGroupFrame* rowGroup = info.firstRowGroup;          nsTableColFrame* col           = info.col; if (!col) ABORT0();          nsTableCellFrame* cell         = info.firstCell;           PRUint8 style = NS_STYLE_BORDER_STYLE_SOLID;          nscolor color = 0xFFFFFFFF;          PRBool ignoreIfRules = (iter.IsRightMostTable() || iter.IsLeftMostTable());          switch (info.owner) {          case eTableOwner:            ::GetStyleInfo(*this, side, style, color);            break;          case eAjaColGroupOwner:             side = NS_SIDE_RIGHT;            if (!iter.IsRightMostTable() && (xAdj > 0)) {              col = verInfo[xAdj - 1].col;             } // and fall through          case eColGroupOwner:            if (col) {              nsIFrame* cg = col->GetParent();              if (cg) {                ::GetStyleInfo(*cg, side, style, color, ignoreIfRules);              }            }            break;          case eAjaColOwner:             side = NS_SIDE_RIGHT;            if (!iter.IsRightMostTable() && (xAdj > 0)) {              col = verInfo[xAdj - 1].col;             } // and fall through          case eColOwner:            if (col) {              ::GetStyleInfo(*col, side, style, color, ignoreIfRules);            }            break;          case eAjaRowGroupOwner:            NS_ASSERTION(PR_FALSE, "program error"); // and fall through          case eRowGroupOwner:            NS_ASSERTION(iter.IsLeftMostTable() || iter.IsRightMostTable(), "program error");            if (rowGroup) {              ::GetStyleInfo(*rowGroup, side, style, color, ignoreIfRules);            }            break;          case eAjaRowOwner:            NS_ASSERTION(PR_FALSE, "program error"); // and fall through          case eRowOwner:             NS_ASSERTION(iter.IsLeftMostTable() || iter.IsRightMostTable(), "program error");            if (row) {              ::GetStyleInfo(*row, side, style, color, ignoreIfRules);            }            break;          case eAjaCellOwner:            side = NS_SIDE_RIGHT;            cell = info.ajaCell; // and fall through          case eCellOwner:            if (cell) {              ::GetStyleInfo(*cell, side, style, color);            }            break;          }          DivideBCBorderSize(info.segWidth, smallHalf, largeHalf);          nsRect segRect(info.colX - NSToCoordRound(p2t * (float)largeHalf), info.segY,                          NSToCoordRound(p2t * (float)info.segWidth), info.segHeight);          nscoord bottomBevelOffset = (endBevel) ? NSToCoordRound(p2t * (float)bottomHorSegHeight) : 0;          PRUint8 bottomBevelSide = (horSegHeight > 0) ? NS_SIDE_RIGHT : NS_SIDE_LEFT;          nsCSSRendering::DrawTableBorderSegment(aRenderingContext, style, color, bgColor, segRect, p2t,                                                  info.bevelSide, NSToCoordRound(p2t * (float)info.bevelOffset),                                                  bottomBevelSide, bottomBevelOffset);        } // if (info.segWidth > 0) {         info.segY = info.segY + info.segHeight - endOffset;      } // if (info.segHeight > 0)      info.Start(iter, borderOwner, verSegWidth, prevHorSegHeight, horSegHeight, p2t, verInfo);    } // if (!iter.IsTopMost() && (isSegStart || iter.IsBottomMost())) {    info.lastCell   = iter.cell;    info.segHeight += rowRect.height;    prevHorSegHeight = horSegHeight;  } // for (iter.First(); !iter.atEnd; iter.Next()) {  // Next, paint all of the horizontal border segments from top to bottom reuse the verInfo   // array to keep tract of col widths and vertical segments for corner calculations  memset(verInfo, 0, damageArea.width * sizeof(BCVerticalSeg)); // XXX reinitialize properly  for (PRInt32 xIndex = 0; xIndex < damageArea.width; xIndex++) {    verInfo[xIndex].colWidth = -1;  }  PRInt32 nextY = startRowY;  BCHorizontalSeg horSeg;  iter.Reset(*this, *inFlowRG, *inFlowRow, damageArea);  for (iter.First(); !iter.atEnd; iter.Next()) {    nscoord leftSegWidth = (iter.bcData) ? iter.bcData->GetLeftEdge(ignoreBorderOwner, ignoreSegStart) : 0;    nscoord topSegHeight = (iter.bcData) ? iter.bcData->GetTopEdge(borderOwner, isSegStart) : 0;    PRInt32 xAdj = iter.x - iter.startX;    // store the current col width if it hasn't been already    if (verInfo[xAdj].colWidth < 0) {      if (iter.IsRightMostTable()) {        verInfo[xAdj].colWidth = verInfo[xAdj - 1].colWidth;      }      else {        nsTableColFrame* col = firstInFlow->GetColFrame(iter.x); if (!col) ABORT0();        verInfo[xAdj].colWidth = col->GetSize().width;      }    }    cornerSubWidth = (iter.bcData) ? iter.bcData->GetCorner(ownerSide, bevel) : 0;    nscoord verWidth = PR_MAX(verInfo[xAdj].segWidth, leftSegWidth);    if (iter.isNewRow || (iter.IsLeftMost() && iter.IsBottomMost())) {      horSeg.y = nextY;      nextY    = nextY + iter.row->GetSize().height;      horSeg.x = startColX;      horSeg.Start(iter, borderOwner, ownerSide, cornerSubWidth, bevel, verInfo[xAdj].segWidth,                    leftSegWidth, topSegHeight, verInfo[xAdj].lastCell, p2t);    }    PRBool verOwnsCorner = (NS_SIDE_TOP == ownerSide) || (NS_SIDE_BOTTOM == ownerSide);    if (!iter.IsLeftMost() && (isSegStart || iter.IsRightMost() || verOwnsCorner)) {      // paint the previous seg or the current one if iter.IsRightMost()      if (horSeg.width > 0) {        PRBool endBevel = (horSeg.height > 0) ? bevel : 0;        nscoord endOffset = CalcHorCornerOffset(ownerSide, cornerSubWidth, verWidth, PR_FALSE, endBevel, p2t);        horSeg.width += endOffset;        if (horSeg.height > 0) {          // get the border style, color and paint the segment          PRUint8 side = (iter.IsBottomMost()) ? NS_SIDE_BOTTOM : NS_SIDE_TOP;          nsIFrame* rg   = iter.rg;          if (!rg) ABORT0();          nsIFrame* row  = iter.row;         if (!row) ABORT0();          nsIFrame* cell = horSeg.firstCell; if (!cell) ABORT0();          nsIFrame* col;          PRUint8 style = NS_STYLE_BORDER_STYLE_SOLID;           nscolor color = 0xFFFFFFFF;          PRBool ignoreIfRules = (iter.IsTopMostTable() || iter.IsBottomMostTable());          switch (horSeg.owner) {          case eTableOwner:            ::GetStyleInfo(*this, side, style, color);            break;          case eAjaColGroupOwner:             NS_ASSERTION(PR_FALSE, "program error"); // and fall through          case eColGroupOwner: {            NS_ASSERTION(iter.IsTopMostTable() || iter.IsBottomMostTable(), "program error");            col = firstInFlow->GetColFrame(iter.x - 1); if (!col) ABORT0();            nsIFrame* cg = col->GetParent(); if (!cg) ABORT0();            ::GetStyleInfo(*cg, side, style, color, ignoreIfRules);            break;          }          case eAjaColOwner:             NS_ASSERTION(PR_FALSE, "program error"); // and fall through          case eColOwner:            NS_ASSERTION(iter.IsTopMostTable() || iter.IsBottomMostTable(), "program error");            col = firstInFlow->GetColFrame(iter.x - 1); if (!col) ABORT0();            ::GetStyleInfo(*col, side, style, color, ignoreIfRules);            break;          case eAjaRowGroupOwner:             side = NS_SIDE_BOTTOM;            rg = (iter.IsBottomMostTable()) ? iter.rg : iter.prevRg; // and fall through          case eRowGroupOwner:            if (rg) {              ::GetStyleInfo(*rg, side, style, color, ignoreIfRules);            }            break;          case eAjaRowOwner:             side = NS_SIDE_BOTTOM;            row = iter.prevRow; // and fall through          case eRowOwner:            if (row) {              ::GetStyleInfo(*row, side, style, color, iter.IsBottomMostTable());            }            break;          case eAjaCellOwner:            side = NS_SIDE_BOTTOM;            // if this is null due to the damage area origin-y > 0, then the border won't show up anyway            cell = horSeg.ajaCell;             // and fall through          case eCellOwner:            if (cell) {              ::GetStyleInfo(*cell, side, style, color);            }            break;          }          DivideBCBorderSize(horSeg.height, smallHalf, largeHalf);          nsRect segRec(horSeg.x, horSeg.y - NSToCoordRound(p2t * (float)largeHalf), horSeg.width,                         NSToCoordRound(p2t * (float)horSeg.height));          nscoord rightBevelOffset = (endBevel) ? NSToCoordRound(p2t * (float)verWidth) : 0;          PRUint8 rightBevelSide = (leftSegWidth > 0) ? NS_SIDE_BOTTOM : NS_SIDE_TOP;          nsCSSRendering::DrawTableBorderSegment(aRenderingContext, style, color, bgColor, segRec, p2t, horSeg.leftBevelSide,                                                  NSToCoordRound(p2t * (float)horSeg.leftBevelOffset),                                                  rightBevelSide, rightBevelOffset);        } // if (horSeg.height > 0) {        horSeg.x = horSeg.x + horSeg.width - endOffset;      } // if (horSeg.width > 0) {      horSeg.Start(iter, borderOwner, ownerSide, cornerSubWidth, bevel, verInfo[xAdj].segWidth,                    leftSegWidth, topSegHeight, verInfo[xAdj].lastCell, p2t);    } // if (!iter.IsLeftMost() && (isSegStart || iter.IsRightMost() || verOwnsCorner)) {    horSeg.width += verInfo[xAdj].colWidth;    verInfo[xAdj].segWidth = leftSegWidth;    verInfo[xAdj].lastCell = iter.cell;  }  delete [] verInfo;}