Пример #1
0
nsresult
TableBackgroundPainter::PaintTableFrame(nsTableFrame*         aTableFrame,
                                        nsTableRowGroupFrame* aFirstRowGroup,
                                        nsTableRowGroupFrame* aLastRowGroup,
                                        const nsMargin&       aDeflate)
{
  NS_PRECONDITION(aTableFrame, "null frame");
  TableBackgroundData tableData;
  tableData.SetFull(aTableFrame);
  tableData.mRect.MoveTo(0,0); //using table's coords
  tableData.mRect.Deflate(aDeflate);
  if (mIsBorderCollapse && tableData.ShouldSetBCBorder()) {
    if (aFirstRowGroup && aLastRowGroup && mNumCols > 0) {
      //only handle non-degenerate tables; we need a more robust BC model
      //to make degenerate tables' borders reasonable to deal with
      nsMargin border, tempBorder;
      nsTableColFrame* colFrame = aTableFrame->GetColFrame(mNumCols - 1);
      if (colFrame) {
        colFrame->GetContinuousBCBorderWidth(tempBorder);
      }
      border.right = tempBorder.right;

      aLastRowGroup->GetContinuousBCBorderWidth(tempBorder);
      border.bottom = tempBorder.bottom;

      nsTableRowFrame* rowFrame = aFirstRowGroup->GetFirstRow();
      if (rowFrame) {
        rowFrame->GetContinuousBCBorderWidth(tempBorder);
        border.top = tempBorder.top;
      }

      border.left = aTableFrame->GetContinuousLeftBCBorderWidth();

      nsresult rv = tableData.SetBCBorder(border, this);
      if (NS_FAILED(rv)) {
        tableData.Destroy(mPresContext);
        return rv;
      }
    }
  }
  if (tableData.IsVisible()) {
    nsCSSRendering::PaintBackgroundWithSC(mPresContext, mRenderingContext,
                                          tableData.mFrame, mDirtyRect,
                                          tableData.mRect + mRenderPt,
                                          tableData.mFrame->StyleContext(),
                                          *tableData.mBorder,
                                          mBGPaintFlags);
  }
  tableData.Destroy(mPresContext);
  return NS_OK;
}
Пример #2
0
DrawResult
TableBackgroundPainter::PaintCell(nsTableCellFrame* aCell,
                                  const TableBackgroundData& aRowGroupBGData,
                                  const TableBackgroundData& aRowBGData,
                                  nsRect&           aCellBGRect,
                                  nsRect&           aRowBGRect,
                                  nsRect&           aRowGroupBGRect,
                                  nsRect&           aColBGRect,
                                  bool              aPassSelf)
{
  MOZ_ASSERT(aCell, "null frame");

  const nsStyleTableBorder* cellTableStyle;
  cellTableStyle = aCell->StyleTableBorder();
  if (NS_STYLE_TABLE_EMPTY_CELLS_SHOW != cellTableStyle->mEmptyCells &&
      aCell->GetContentEmpty() && !mIsBorderCollapse) {
    return DrawResult::SUCCESS;
  }

  int32_t colIndex;
  aCell->GetColIndex(colIndex);
  // We're checking mNumCols instead of mCols.Length() here because mCols can
  // be empty even if mNumCols > 0.
  NS_ASSERTION(size_t(colIndex) < mNumCols, "out-of-bounds column index");
  if (size_t(colIndex) >= mNumCols) {
    return DrawResult::SUCCESS;
  }

  // If callers call PaintRowGroup or PaintRow directly, we haven't processed
  // our columns. Ignore column / col group backgrounds in that case.
  bool haveColumns = !mCols.IsEmpty();

  DrawResult result = DrawResult::SUCCESS;

  //Paint column group background
  if (haveColumns && mCols[colIndex].mColGroup.IsVisible()) {
    DrawResult colGroupResult =
      nsCSSRendering::PaintBackgroundWithSC(mPresContext, mRenderingContext,
                                            mCols[colIndex].mColGroup.mFrame, mDirtyRect,
                                            mCols[colIndex].mColGroup.mRect + mRenderPt,
                                            mCols[colIndex].mColGroup.mFrame->StyleContext(),
                                            mCols[colIndex].mColGroup.StyleBorder(mZeroBorder),
                                            mBGPaintFlags, &aColBGRect);
    UpdateDrawResult(&result, colGroupResult);
  }

  //Paint column background
  if (haveColumns && mCols[colIndex].mCol.IsVisible()) {
    DrawResult colResult =
      nsCSSRendering::PaintBackgroundWithSC(mPresContext, mRenderingContext,
                                            mCols[colIndex].mCol.mFrame, mDirtyRect,
                                            mCols[colIndex].mCol.mRect + mRenderPt,
                                            mCols[colIndex].mCol.mFrame->StyleContext(),
                                            mCols[colIndex].mCol.StyleBorder(mZeroBorder),
                                            mBGPaintFlags, &aColBGRect);
    UpdateDrawResult(&result, colResult);
  }

  //Paint row group background
  if (aRowGroupBGData.IsVisible()) {
    DrawResult rowGroupResult =
      nsCSSRendering::PaintBackgroundWithSC(mPresContext, mRenderingContext,
                                            aRowGroupBGData.mFrame, mDirtyRect,
                                            aRowGroupBGData.mRect + mRenderPt,
                                            aRowGroupBGData.mFrame->StyleContext(),
                                            aRowGroupBGData.StyleBorder(mZeroBorder),
                                            mBGPaintFlags, &aRowGroupBGRect);
    UpdateDrawResult(&result, rowGroupResult);
  }

  //Paint row background
  if (aRowBGData.IsVisible()) {
    DrawResult rowResult =
      nsCSSRendering::PaintBackgroundWithSC(mPresContext, mRenderingContext,
                                            aRowBGData.mFrame, mDirtyRect,
                                            aRowBGData.mRect + mRenderPt,
                                            aRowBGData.mFrame->StyleContext(),
                                            aRowBGData.StyleBorder(mZeroBorder),
                                            mBGPaintFlags, &aRowBGRect);
    UpdateDrawResult(&result, rowResult);
  }

  //Paint cell background in border-collapse unless we're just passing
  if (mIsBorderCollapse && !aPassSelf) {
    DrawResult cellResult =
      aCell->PaintCellBackground(mRenderingContext, mDirtyRect,
                                 aCellBGRect.TopLeft(), mBGPaintFlags);
    UpdateDrawResult(&result, cellResult);
  }

  return result;
}
Пример #3
0
DrawResult
TableBackgroundPainter::PaintRow(nsTableRowFrame* aFrame,
                                 const TableBackgroundData& aRowGroupBGData,
                                 TableBackgroundData aRowBGData,
                                 bool             aPassThrough)
{
  MOZ_ASSERT(aFrame, "null frame");

  /* Load row data */
  WritingMode wm = aFrame->GetWritingMode();
  if (aPassThrough) {
    aRowBGData.MakeInvisible();
  } else {
    if (mIsBorderCollapse && aRowBGData.ShouldSetBCBorder()) {
      LogicalMargin border(wm);
      nsTableRowFrame* nextRow = aFrame->GetNextRow();
      if (nextRow) { //outer bStart after us is inner bEnd for us
        border.BEnd(wm) = nextRow->GetOuterBStartContBCBorderWidth();
      }
      else { //acquire rg's bEnd border
        nsTableRowGroupFrame* rowGroup = static_cast<nsTableRowGroupFrame*>(aFrame->GetParent());
        rowGroup->GetContinuousBCBorderWidth(wm, border);
      }
      //get the rest of the borders; will overwrite all but bEnd
      aFrame->GetContinuousBCBorderWidth(wm, border);

      aRowBGData.SetBCBorder(border.GetPhysicalMargin(wm));
    }
    aPassThrough = !aRowBGData.IsVisible();
  }

  /* Translate */
  if (eOrigin_TableRow == mOrigin) {
    /* If we originate from the row, then make the row the origin. */
    aRowBGData.mRect.MoveTo(0, 0);
  }
  //else: Use row group's coord system -> no translation necessary

  DrawResult result = DrawResult::SUCCESS;

  for (nsTableCellFrame* cell = aFrame->GetFirstCell(); cell; cell = cell->GetNextCell()) {
    nsRect cellBGRect, rowBGRect, rowGroupBGRect, colBGRect;
    ComputeCellBackgrounds(cell, aRowGroupBGData, aRowBGData,
                           cellBGRect, rowBGRect,
                           rowGroupBGRect, colBGRect);

    // Find the union of all the cell background layers.
    nsRect combinedRect(cellBGRect);
    combinedRect.UnionRect(combinedRect, rowBGRect);
    combinedRect.UnionRect(combinedRect, rowGroupBGRect);
    combinedRect.UnionRect(combinedRect, colBGRect);

    if (combinedRect.Intersects(mDirtyRect)) {
      bool passCell = aPassThrough || cell->IsPseudoStackingContextFromStyle();
      DrawResult cellResult =
        PaintCell(cell, aRowGroupBGData, aRowBGData,
                  cellBGRect, rowBGRect, rowGroupBGRect, colBGRect, passCell);

      UpdateDrawResult(&result, cellResult);
    }
  }

  return result;
}
Пример #4
0
DrawResult
TableBackgroundPainter::PaintRowGroup(nsTableRowGroupFrame* aFrame,
                                      TableBackgroundData   aRowGroupBGData,
                                      bool                  aPassThrough)
{
  MOZ_ASSERT(aFrame, "null frame");

  nsTableRowFrame* firstRow = aFrame->GetFirstRow();
  WritingMode wm = aFrame->GetWritingMode();

  /* Load row group data */
  if (aPassThrough) {
    aRowGroupBGData.MakeInvisible();
  } else {
    if (mIsBorderCollapse && aRowGroupBGData.ShouldSetBCBorder()) {
      LogicalMargin border(wm);
      if (firstRow) {
        //pick up first row's bstart border (= rg bstart border)
        firstRow->GetContinuousBCBorderWidth(wm, border);
        /* (row group doesn't store its bstart border) */
      }
      //overwrite sides+bottom borders with rg's own
      aFrame->GetContinuousBCBorderWidth(wm, border);
      aRowGroupBGData.SetBCBorder(border.GetPhysicalMargin(wm));
    }
    aPassThrough = !aRowGroupBGData.IsVisible();
  }

  /* translate everything into row group coord system*/
  if (eOrigin_TableRowGroup != mOrigin) {
    TranslateContext(aRowGroupBGData.mRect.x, aRowGroupBGData.mRect.y);
  }
  nsRect rgRect = aRowGroupBGData.mRect;
  aRowGroupBGData.mRect.MoveTo(0, 0);

  /* Find the right row to start with */

  // Note that mDirtyRect  - mRenderPt is guaranteed to be in the row
  // group's coordinate system here, so passing its .y to
  // GetFirstRowContaining is ok.
  nscoord overflowAbove;
  nsIFrame* cursor = aFrame->GetFirstRowContaining(mDirtyRect.y - mRenderPt.y, &overflowAbove);

  // Sadly, it seems like there may be non-row frames in there... or something?
  // There are certainly null-checks in GetFirstRow() and GetNextRow().  :(
  while (cursor && cursor->GetType() != nsGkAtoms::tableRowFrame) {
    cursor = cursor->GetNextSibling();
  }

  // It's OK if cursor is null here.
  nsTableRowFrame* row = static_cast<nsTableRowFrame*>(cursor);
  if (!row) {
    // No useful cursor; just start at the top.  Don't bother to set up a
    // cursor; if we've gotten this far then we've already built the display
    // list for the rowgroup, so not having a cursor means that there's some
    // good reason we don't have a cursor and we shouldn't create one here.
    row = firstRow;
  }

  DrawResult result = DrawResult::SUCCESS;

  /* Finally paint */
  for (; row; row = row->GetNextRow()) {
    TableBackgroundData rowBackgroundData(row);

    // Be sure to consider our positions both pre- and post-relative
    // positioning, since we potentially need to paint at both places.
    nscoord rowY = std::min(rowBackgroundData.mRect.y, row->GetNormalPosition().y);

    // Intersect wouldn't handle rowspans.
    if (cursor &&
        (mDirtyRect.YMost() - mRenderPt.y) <= (rowY - overflowAbove)) {
      // All done; cells originating in later rows can't intersect mDirtyRect.
      break;
    }

    DrawResult rowResult =
      PaintRow(row, aRowGroupBGData, rowBackgroundData,
               aPassThrough || row->IsPseudoStackingContextFromStyle());

    UpdateDrawResult(&result, rowResult);
  }

  /* translate back into table coord system */
  if (eOrigin_TableRowGroup != mOrigin) {
    TranslateContext(-rgRect.x, -rgRect.y);
  }

  return result;
}