зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1130817 - Refactor nsTablePainter a little. r=roc
This patch makes the following changes: - Ownership of the col groups' TableBackgroundData has moved into the mColGroups array. - nsStyleBorder instances for painting are created on the stack instead of in the allocation arena of the pres context, so now we no longer need to call Destroy on them. - Not having to call Destroy lets us get rid of a lot of destruction code. - TableBackgroundData for the current row group and the current row no longer live in member variables of nsTablePainter. They're now on the stack and get passed to the methods that need them as usual. - All methods now return void instead of nsresult. - TableBackgroundData instances are no longer reused.
This commit is contained in:
Родитель
9e603c0955
Коммит
11cfcac596
|
@ -1358,8 +1358,7 @@ nsTableFrame::PaintTableBorderBackground(nsRenderingContext& aRenderingContext,
|
|||
nsMargin deflate = GetDeflationForBackground(presContext);
|
||||
// If 'deflate' is (0,0,0,0) then we'll paint the table background
|
||||
// in a separate display item, so don't do it here.
|
||||
nsresult rv = painter.PaintTable(this, deflate, deflate != nsMargin(0, 0, 0, 0));
|
||||
if (NS_FAILED(rv)) return;
|
||||
painter.PaintTable(this, deflate, deflate != nsMargin(0, 0, 0, 0));
|
||||
|
||||
if (StyleVisibility()->IsVisible()) {
|
||||
if (!IsBorderCollapse()) {
|
||||
|
|
|
@ -76,10 +76,8 @@
|
|||
in the data struct since collapsed borders aren't the same width as style-
|
||||
assigned borders. The data struct optimizes by only doing this if there's
|
||||
an image background; otherwise we don't care. //XXX should also check background-origin
|
||||
The class then loops through the row groups, rows, and cells. It uses
|
||||
the mRowGroup and mRow TableBackgroundData structs to cache data for
|
||||
the current frame in the loop. At the cell level, it paints the backgrounds,
|
||||
one over the other, inside the cell rect.
|
||||
The class then loops through the row groups, rows, and cells. At the cell
|
||||
level, it paints the backgrounds, one over the other, inside the cell rect.
|
||||
|
||||
The exception to this pattern is when a table element creates a (pseudo)
|
||||
stacking context. Elements with stacking contexts (e.g., 'opacity' applied)
|
||||
|
@ -98,67 +96,22 @@
|
|||
*/
|
||||
|
||||
TableBackgroundPainter::TableBackgroundData::TableBackgroundData()
|
||||
: mFrame(nullptr),
|
||||
mVisible(false),
|
||||
mBorder(nullptr),
|
||||
mSynthBorder(nullptr)
|
||||
: mFrame(nullptr)
|
||||
, mVisible(false)
|
||||
, mUsesSynthBorder(false)
|
||||
{
|
||||
MOZ_COUNT_CTOR(TableBackgroundData);
|
||||
}
|
||||
|
||||
TableBackgroundPainter::TableBackgroundData::~TableBackgroundData()
|
||||
TableBackgroundPainter::TableBackgroundData::TableBackgroundData(nsIFrame* aFrame)
|
||||
: mFrame(aFrame)
|
||||
, mRect(aFrame->GetRect())
|
||||
, mVisible(mFrame->IsVisibleForPainting())
|
||||
, mUsesSynthBorder(false)
|
||||
{
|
||||
NS_ASSERTION(!mSynthBorder, "must call Destroy before dtor");
|
||||
MOZ_COUNT_DTOR(TableBackgroundData);
|
||||
}
|
||||
|
||||
void
|
||||
TableBackgroundPainter::TableBackgroundData::Destroy(nsPresContext* aPresContext)
|
||||
{
|
||||
NS_PRECONDITION(aPresContext, "null prescontext");
|
||||
if (mSynthBorder) {
|
||||
mSynthBorder->Destroy(aPresContext);
|
||||
mSynthBorder = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TableBackgroundPainter::TableBackgroundData::Clear()
|
||||
{
|
||||
mRect.SetEmpty();
|
||||
mFrame = nullptr;
|
||||
mBorder = nullptr;
|
||||
mVisible = false;
|
||||
}
|
||||
|
||||
void
|
||||
TableBackgroundPainter::TableBackgroundData::SetFrame(nsIFrame* aFrame)
|
||||
{
|
||||
NS_PRECONDITION(aFrame, "null frame");
|
||||
mFrame = aFrame;
|
||||
mRect = aFrame->GetRect();
|
||||
}
|
||||
|
||||
void
|
||||
TableBackgroundPainter::TableBackgroundData::SetData()
|
||||
{
|
||||
NS_PRECONDITION(mFrame, "null frame");
|
||||
if (mFrame->IsVisibleForPainting()) {
|
||||
mVisible = true;
|
||||
mBorder = mFrame->StyleBorder();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TableBackgroundPainter::TableBackgroundData::SetFull(nsIFrame* aFrame)
|
||||
{
|
||||
NS_PRECONDITION(aFrame, "null frame");
|
||||
SetFrame(aFrame);
|
||||
SetData();
|
||||
}
|
||||
|
||||
inline bool
|
||||
TableBackgroundPainter::TableBackgroundData::ShouldSetBCBorder()
|
||||
TableBackgroundPainter::TableBackgroundData::ShouldSetBCBorder() const
|
||||
{
|
||||
/* we only need accurate border data when positioning background images*/
|
||||
if (!mVisible) {
|
||||
|
@ -173,23 +126,29 @@ TableBackgroundPainter::TableBackgroundData::ShouldSetBCBorder()
|
|||
return false;
|
||||
}
|
||||
|
||||
nsresult
|
||||
TableBackgroundPainter::TableBackgroundData::SetBCBorder(nsMargin& aBorder,
|
||||
TableBackgroundPainter* aPainter)
|
||||
void
|
||||
TableBackgroundPainter::TableBackgroundData::SetBCBorder(const nsMargin& aBorder)
|
||||
{
|
||||
NS_PRECONDITION(aPainter, "null painter");
|
||||
if (!mSynthBorder) {
|
||||
mSynthBorder = new (aPainter->mPresContext)
|
||||
nsStyleBorder(aPainter->mZeroBorder);
|
||||
if (!mSynthBorder) return NS_ERROR_OUT_OF_MEMORY;
|
||||
mUsesSynthBorder = true;
|
||||
mSynthBorderWidths = aBorder;
|
||||
}
|
||||
|
||||
nsStyleBorder
|
||||
TableBackgroundPainter::TableBackgroundData::StyleBorder(const nsStyleBorder& aZeroBorder) const
|
||||
{
|
||||
MOZ_ASSERT(mVisible, "Don't call StyleBorder on an invisible TableBackgroundData");
|
||||
|
||||
if (mUsesSynthBorder) {
|
||||
nsStyleBorder result = aZeroBorder;
|
||||
NS_FOR_CSS_SIDES(side) {
|
||||
result.SetBorderWidth(side, mSynthBorderWidths.Side(side));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_FOR_CSS_SIDES(side) {
|
||||
mSynthBorder->SetBorderWidth(side, aBorder.Side(side));
|
||||
}
|
||||
|
||||
mBorder = mSynthBorder;
|
||||
return NS_OK;
|
||||
MOZ_ASSERT(mFrame);
|
||||
|
||||
return *mFrame->StyleBorder();
|
||||
}
|
||||
|
||||
TableBackgroundPainter::TableBackgroundPainter(nsTableFrame* aTableFrame,
|
||||
|
@ -204,7 +163,6 @@ TableBackgroundPainter::TableBackgroundPainter(nsTableFrame* aTableFrame,
|
|||
mRenderPt(aRenderPt),
|
||||
mDirtyRect(aDirtyRect),
|
||||
mOrigin(aOrigin),
|
||||
mCols(nullptr),
|
||||
mZeroBorder(aPresContext),
|
||||
mBGPaintFlags(aBGPaintFlags)
|
||||
{
|
||||
|
@ -224,36 +182,17 @@ TableBackgroundPainter::TableBackgroundPainter(nsTableFrame* aTableFrame,
|
|||
|
||||
TableBackgroundPainter::~TableBackgroundPainter()
|
||||
{
|
||||
if (mCols) {
|
||||
TableBackgroundData* lastColGroup = nullptr;
|
||||
for (uint32_t i = 0; i < mNumCols; i++) {
|
||||
if (mCols[i].mColGroup != lastColGroup) {
|
||||
lastColGroup = mCols[i].mColGroup;
|
||||
NS_ASSERTION(mCols[i].mColGroup, "colgroup data should not be null - bug 237421");
|
||||
// we need to wallpaper a over zero pointer deref, bug 237421 will have the real fix
|
||||
if(lastColGroup)
|
||||
lastColGroup->Destroy(mPresContext);
|
||||
delete lastColGroup;
|
||||
}
|
||||
mCols[i].mColGroup = nullptr;
|
||||
mCols[i].mCol.Destroy(mPresContext);
|
||||
}
|
||||
delete [] mCols;
|
||||
}
|
||||
mRowGroup.Destroy(mPresContext);
|
||||
mRow.Destroy(mPresContext);
|
||||
MOZ_COUNT_DTOR(TableBackgroundPainter);
|
||||
}
|
||||
|
||||
nsresult
|
||||
void
|
||||
TableBackgroundPainter::PaintTableFrame(nsTableFrame* aTableFrame,
|
||||
nsTableRowGroupFrame* aFirstRowGroup,
|
||||
nsTableRowGroupFrame* aLastRowGroup,
|
||||
const nsMargin& aDeflate)
|
||||
{
|
||||
NS_PRECONDITION(aTableFrame, "null frame");
|
||||
TableBackgroundData tableData;
|
||||
tableData.SetFull(aTableFrame);
|
||||
MOZ_ASSERT(aTableFrame, "null frame");
|
||||
TableBackgroundData tableData(aTableFrame);
|
||||
tableData.mRect.MoveTo(0,0); //using table's coords
|
||||
tableData.mRect.Deflate(aDeflate);
|
||||
if (mIsBorderCollapse && tableData.ShouldSetBCBorder()) {
|
||||
|
@ -278,11 +217,7 @@ TableBackgroundPainter::PaintTableFrame(nsTableFrame* aTableFrame,
|
|||
|
||||
border.left = aTableFrame->GetContinuousLeftBCBorderWidth();
|
||||
|
||||
nsresult rv = tableData.SetBCBorder(border, this);
|
||||
if (NS_FAILED(rv)) {
|
||||
tableData.Destroy(mPresContext);
|
||||
return rv;
|
||||
}
|
||||
tableData.SetBCBorder(border);
|
||||
}
|
||||
}
|
||||
if (tableData.IsVisible()) {
|
||||
|
@ -290,11 +225,9 @@ TableBackgroundPainter::PaintTableFrame(nsTableFrame* aTableFrame,
|
|||
tableData.mFrame, mDirtyRect,
|
||||
tableData.mRect + mRenderPt,
|
||||
tableData.mFrame->StyleContext(),
|
||||
*tableData.mBorder,
|
||||
tableData.StyleBorder(mZeroBorder),
|
||||
mBGPaintFlags);
|
||||
}
|
||||
tableData.Destroy(mPresContext);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -302,23 +235,21 @@ TableBackgroundPainter::TranslateContext(nscoord aDX,
|
|||
nscoord aDY)
|
||||
{
|
||||
mRenderPt += nsPoint(aDX, aDY);
|
||||
if (mCols) {
|
||||
TableBackgroundData* lastColGroup = nullptr;
|
||||
for (uint32_t i = 0; i < mNumCols; i++) {
|
||||
mCols[i].mCol.mRect.MoveBy(-aDX, -aDY);
|
||||
if (lastColGroup != mCols[i].mColGroup) {
|
||||
NS_ASSERTION(mCols[i].mColGroup, "colgroup data should not be null - bug 237421");
|
||||
// we need to wallpaper a over zero pointer deref, bug 237421 will have the real fix
|
||||
if (!mCols[i].mColGroup)
|
||||
return;
|
||||
mCols[i].mColGroup->mRect.MoveBy(-aDX, -aDY);
|
||||
lastColGroup = mCols[i].mColGroup;
|
||||
}
|
||||
}
|
||||
for (auto& col : mCols) {
|
||||
col.mCol.mRect.MoveBy(-aDX, -aDY);
|
||||
}
|
||||
for (auto& colGroup : mColGroups) {
|
||||
colGroup.mRect.MoveBy(-aDX, -aDY);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
TableBackgroundPainter::ColData::ColData(nsIFrame* aFrame, TableBackgroundData& aColGroupBGData)
|
||||
: mCol(aFrame)
|
||||
, mColGroup(aColGroupBGData)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
TableBackgroundPainter::PaintTable(nsTableFrame* aTableFrame,
|
||||
const nsMargin& aDeflate,
|
||||
bool aPaintTableBackground)
|
||||
|
@ -333,7 +264,7 @@ TableBackgroundPainter::PaintTable(nsTableFrame* aTableFrame,
|
|||
PaintTableFrame(aTableFrame, nullptr, nullptr, nsMargin(0,0,0,0));
|
||||
}
|
||||
/* No cells; nothing else to paint */
|
||||
return NS_OK;
|
||||
return;
|
||||
}
|
||||
|
||||
if (aPaintTableBackground) {
|
||||
|
@ -346,15 +277,8 @@ TableBackgroundPainter::PaintTable(nsTableFrame* aTableFrame,
|
|||
nsFrameList& colGroupList = aTableFrame->GetColGroups();
|
||||
NS_ASSERTION(colGroupList.FirstChild(), "table should have at least one colgroup");
|
||||
|
||||
mCols = new ColData[mNumCols];
|
||||
if (!mCols) return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
TableBackgroundData* cgData = nullptr;
|
||||
nsMargin border;
|
||||
/* BC left borders aren't stored on cols, but the previous column's
|
||||
right border is the next one's left border.*/
|
||||
//Start with table's left border.
|
||||
nscoord lastLeftBorder = aTableFrame->GetContinuousLeftBCBorderWidth();
|
||||
// Collect all col group frames first so that we know how many there are.
|
||||
nsTArray<nsTableColGroupFrame*> colGroupFrames;
|
||||
for (nsTableColGroupFrame* cgFrame = static_cast<nsTableColGroupFrame*>(colGroupList.FirstChild());
|
||||
cgFrame; cgFrame = static_cast<nsTableColGroupFrame*>(cgFrame->GetNextSibling())) {
|
||||
|
||||
|
@ -362,62 +286,54 @@ TableBackgroundPainter::PaintTable(nsTableFrame* aTableFrame,
|
|||
//No columns, no cells, so no need for data
|
||||
continue;
|
||||
}
|
||||
colGroupFrames.AppendElement(cgFrame);
|
||||
}
|
||||
|
||||
// Ensure that mColGroups won't reallocate during the loop below, because
|
||||
// we grab references to its contents and need those to stay valid until
|
||||
// mColGroups is destroyed as part of TablePainter destruction.
|
||||
mColGroups.SetCapacity(colGroupFrames.Length());
|
||||
|
||||
nsMargin border;
|
||||
/* BC left borders aren't stored on cols, but the previous column's
|
||||
right border is the next one's left border.*/
|
||||
//Start with table's left border.
|
||||
nscoord lastLeftBorder = aTableFrame->GetContinuousLeftBCBorderWidth();
|
||||
|
||||
for (nsTableColGroupFrame* cgFrame : colGroupFrames) {
|
||||
/*Create data struct for column group*/
|
||||
cgData = new TableBackgroundData;
|
||||
if (!cgData) return NS_ERROR_OUT_OF_MEMORY;
|
||||
cgData->SetFull(cgFrame);
|
||||
if (mIsBorderCollapse && cgData->ShouldSetBCBorder()) {
|
||||
TableBackgroundData& cgData = *mColGroups.AppendElement(TableBackgroundData(cgFrame));
|
||||
if (mIsBorderCollapse && cgData.ShouldSetBCBorder()) {
|
||||
border.left = lastLeftBorder;
|
||||
cgFrame->GetContinuousBCBorderWidth(border);
|
||||
nsresult rv = cgData->SetBCBorder(border, this);
|
||||
if (NS_FAILED(rv)) {
|
||||
cgData->Destroy(mPresContext);
|
||||
delete cgData;
|
||||
return rv;
|
||||
}
|
||||
cgData.SetBCBorder(border);
|
||||
}
|
||||
|
||||
// Boolean that indicates whether mCols took ownership of cgData
|
||||
bool cgDataOwnershipTaken = false;
|
||||
|
||||
/*Loop over columns in this colgroup*/
|
||||
for (nsTableColFrame* col = cgFrame->GetFirstColumn(); col;
|
||||
col = static_cast<nsTableColFrame*>(col->GetNextSibling())) {
|
||||
/*Create data struct for column*/
|
||||
uint32_t colIndex = col->GetColIndex();
|
||||
NS_ASSERTION(colIndex < mNumCols, "prevent array boundary violation");
|
||||
if (mNumCols <= colIndex)
|
||||
break;
|
||||
mCols[colIndex].mCol.SetFull(col);
|
||||
MOZ_ASSERT(size_t(col->GetColIndex()) == mCols.Length());
|
||||
// Store a reference to the colGroup in the ColData element.
|
||||
ColData& colData = *mCols.AppendElement(ColData(col, cgData));
|
||||
//Bring column mRect into table's coord system
|
||||
mCols[colIndex].mCol.mRect.MoveBy(cgData->mRect.x, cgData->mRect.y);
|
||||
//link to parent colgroup's data
|
||||
mCols[colIndex].mColGroup = cgData;
|
||||
cgDataOwnershipTaken = true;
|
||||
colData.mCol.mRect.MoveBy(cgData.mRect.x, cgData.mRect.y);
|
||||
if (mIsBorderCollapse) {
|
||||
border.left = lastLeftBorder;
|
||||
lastLeftBorder = col->GetContinuousBCBorderWidth(border);
|
||||
if (mCols[colIndex].mCol.ShouldSetBCBorder()) {
|
||||
nsresult rv = mCols[colIndex].mCol.SetBCBorder(border, this);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (colData.mCol.ShouldSetBCBorder()) {
|
||||
colData.mCol.SetBCBorder(border);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!cgDataOwnershipTaken) {
|
||||
cgData->Destroy(mPresContext);
|
||||
delete cgData;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < rowGroups.Length(); i++) {
|
||||
nsTableRowGroupFrame* rg = rowGroups[i];
|
||||
mRowGroup.SetFrame(rg);
|
||||
TableBackgroundData rowGroupBGData(rg);
|
||||
// Need to compute the right rect via GetOffsetTo, since the row
|
||||
// group may not be a child of the table.
|
||||
mRowGroup.mRect.MoveTo(rg->GetOffsetTo(aTableFrame));
|
||||
rowGroupBGData.mRect.MoveTo(rg->GetOffsetTo(aTableFrame));
|
||||
|
||||
// We have to draw backgrounds not only within the overflow region of this
|
||||
// row group, but also possibly (in the case of column / column group
|
||||
|
@ -427,29 +343,31 @@ TableBackgroundPainter::PaintTable(nsTableFrame* aTableFrame,
|
|||
nsRect rgNormalRect = rgVisualOverflow + rg->GetNormalPosition();
|
||||
|
||||
if (rgOverflowRect.Union(rgNormalRect).Intersects(mDirtyRect - mRenderPt)) {
|
||||
nsresult rv = PaintRowGroup(rg, rg->IsPseudoStackingContextFromStyle());
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
PaintRowGroup(rg, rowGroupBGData, rg->IsPseudoStackingContextFromStyle());
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
void
|
||||
TableBackgroundPainter::PaintRowGroup(nsTableRowGroupFrame* aFrame)
|
||||
{
|
||||
PaintRowGroup(aFrame, TableBackgroundData(aFrame), false);
|
||||
}
|
||||
|
||||
void
|
||||
TableBackgroundPainter::PaintRowGroup(nsTableRowGroupFrame* aFrame,
|
||||
TableBackgroundData aRowGroupBGData,
|
||||
bool aPassThrough)
|
||||
{
|
||||
NS_PRECONDITION(aFrame, "null frame");
|
||||
|
||||
if (!mRowGroup.mFrame) {
|
||||
mRowGroup.SetFrame(aFrame);
|
||||
}
|
||||
MOZ_ASSERT(aFrame, "null frame");
|
||||
|
||||
nsTableRowFrame* firstRow = aFrame->GetFirstRow();
|
||||
|
||||
/* Load row group data */
|
||||
if (!aPassThrough) {
|
||||
mRowGroup.SetData();
|
||||
if (mIsBorderCollapse && mRowGroup.ShouldSetBCBorder()) {
|
||||
if (aPassThrough) {
|
||||
aRowGroupBGData.MakeInvisible();
|
||||
} else {
|
||||
if (mIsBorderCollapse && aRowGroupBGData.ShouldSetBCBorder()) {
|
||||
nsMargin border;
|
||||
if (firstRow) {
|
||||
//pick up first row's top border (= rg top border)
|
||||
|
@ -458,20 +376,17 @@ TableBackgroundPainter::PaintRowGroup(nsTableRowGroupFrame* aFrame,
|
|||
}
|
||||
//overwrite sides+bottom borders with rg's own
|
||||
aFrame->GetContinuousBCBorderWidth(border);
|
||||
nsresult res = mRowGroup.SetBCBorder(border, this);
|
||||
if (!NS_SUCCEEDED(res)) {
|
||||
return res;
|
||||
}
|
||||
aRowGroupBGData.SetBCBorder(border);
|
||||
}
|
||||
aPassThrough = !mRowGroup.IsVisible();
|
||||
aPassThrough = !aRowGroupBGData.IsVisible();
|
||||
}
|
||||
|
||||
/* translate everything into row group coord system*/
|
||||
if (eOrigin_TableRowGroup != mOrigin) {
|
||||
TranslateContext(mRowGroup.mRect.x, mRowGroup.mRect.y);
|
||||
TranslateContext(aRowGroupBGData.mRect.x, aRowGroupBGData.mRect.y);
|
||||
}
|
||||
nsRect rgRect = mRowGroup.mRect;
|
||||
mRowGroup.mRect.MoveTo(0, 0);
|
||||
nsRect rgRect = aRowGroupBGData.mRect;
|
||||
aRowGroupBGData.mRect.MoveTo(0, 0);
|
||||
|
||||
/* Find the right row to start with */
|
||||
|
||||
|
@ -499,10 +414,11 @@ TableBackgroundPainter::PaintRowGroup(nsTableRowGroupFrame* aFrame,
|
|||
|
||||
/* Finally paint */
|
||||
for (; row; row = row->GetNextRow()) {
|
||||
mRow.SetFrame(row);
|
||||
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(mRow.mRect.y, row->GetNormalPosition().y);
|
||||
nscoord rowY = std::min(rowBackgroundData.mRect.y, row->GetNormalPosition().y);
|
||||
|
||||
// Intersect wouldn't handle rowspans.
|
||||
if (cursor &&
|
||||
|
@ -511,35 +427,35 @@ TableBackgroundPainter::PaintRowGroup(nsTableRowGroupFrame* aFrame,
|
|||
break;
|
||||
}
|
||||
|
||||
nsresult rv = PaintRow(row, aPassThrough || row->IsPseudoStackingContextFromStyle());
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
PaintRow(row, aRowGroupBGData, rowBackgroundData,
|
||||
aPassThrough || row->IsPseudoStackingContextFromStyle());
|
||||
}
|
||||
|
||||
/* translate back into table coord system */
|
||||
if (eOrigin_TableRowGroup != mOrigin) {
|
||||
TranslateContext(-rgRect.x, -rgRect.y);
|
||||
}
|
||||
|
||||
/* unload rg data */
|
||||
mRowGroup.Clear();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
void
|
||||
TableBackgroundPainter::PaintRow(nsTableRowFrame* aFrame)
|
||||
{
|
||||
return PaintRow(aFrame, TableBackgroundData(), TableBackgroundData(aFrame), false);
|
||||
}
|
||||
|
||||
void
|
||||
TableBackgroundPainter::PaintRow(nsTableRowFrame* aFrame,
|
||||
const TableBackgroundData& aRowGroupBGData,
|
||||
TableBackgroundData aRowBGData,
|
||||
bool aPassThrough)
|
||||
{
|
||||
NS_PRECONDITION(aFrame, "null frame");
|
||||
|
||||
if (!mRow.mFrame) {
|
||||
mRow.SetFrame(aFrame);
|
||||
}
|
||||
MOZ_ASSERT(aFrame, "null frame");
|
||||
|
||||
/* Load row data */
|
||||
if (!aPassThrough) {
|
||||
mRow.SetData();
|
||||
if (mIsBorderCollapse && mRow.ShouldSetBCBorder()) {
|
||||
if (aPassThrough) {
|
||||
aRowBGData.MakeInvisible();
|
||||
} else {
|
||||
if (mIsBorderCollapse && aRowBGData.ShouldSetBCBorder()) {
|
||||
nsMargin border;
|
||||
nsTableRowFrame* nextRow = aFrame->GetNextRow();
|
||||
if (nextRow) { //outer top below us is inner bottom for us
|
||||
|
@ -552,24 +468,22 @@ TableBackgroundPainter::PaintRow(nsTableRowFrame* aFrame,
|
|||
//get the rest of the borders; will overwrite all but bottom
|
||||
aFrame->GetContinuousBCBorderWidth(border);
|
||||
|
||||
nsresult res = mRow.SetBCBorder(border, this);
|
||||
if (!NS_SUCCEEDED(res)) {
|
||||
return res;
|
||||
}
|
||||
aRowBGData.SetBCBorder(border);
|
||||
}
|
||||
aPassThrough = !mRow.IsVisible();
|
||||
aPassThrough = !aRowBGData.IsVisible();
|
||||
}
|
||||
|
||||
/* Translate */
|
||||
if (eOrigin_TableRow == mOrigin) {
|
||||
/* If we originate from the row, then make the row the origin. */
|
||||
mRow.mRect.MoveTo(0, 0);
|
||||
aRowBGData.mRect.MoveTo(0, 0);
|
||||
}
|
||||
//else: Use row group's coord system -> no translation necessary
|
||||
|
||||
for (nsTableCellFrame* cell = aFrame->GetFirstCell(); cell; cell = cell->GetNextCell()) {
|
||||
nsRect cellBGRect, rowBGRect, rowGroupBGRect, colBGRect;
|
||||
ComputeCellBackgrounds(cell, cellBGRect, rowBGRect,
|
||||
ComputeCellBackgrounds(cell, aRowGroupBGData, aRowBGData,
|
||||
cellBGRect, rowBGRect,
|
||||
rowGroupBGRect, colBGRect);
|
||||
|
||||
// Find the union of all the cell background layers.
|
||||
|
@ -580,77 +494,80 @@ TableBackgroundPainter::PaintRow(nsTableRowFrame* aFrame,
|
|||
|
||||
if (combinedRect.Intersects(mDirtyRect)) {
|
||||
bool passCell = aPassThrough || cell->IsPseudoStackingContextFromStyle();
|
||||
nsresult rv = PaintCell(cell, cellBGRect, rowBGRect, rowGroupBGRect,
|
||||
colBGRect, passCell);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
PaintCell(cell, aRowGroupBGData, aRowBGData,
|
||||
cellBGRect, rowBGRect, rowGroupBGRect, colBGRect, passCell);
|
||||
}
|
||||
}
|
||||
|
||||
/* Unload row data */
|
||||
mRow.Clear();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
void
|
||||
TableBackgroundPainter::PaintCell(nsTableCellFrame* aCell,
|
||||
const TableBackgroundData& aRowGroupBGData,
|
||||
const TableBackgroundData& aRowBGData,
|
||||
nsRect& aCellBGRect,
|
||||
nsRect& aRowBGRect,
|
||||
nsRect& aRowGroupBGRect,
|
||||
nsRect& aColBGRect,
|
||||
bool aPassSelf)
|
||||
{
|
||||
NS_PRECONDITION(aCell, "null frame");
|
||||
MOZ_ASSERT(aCell, "null frame");
|
||||
|
||||
const nsStyleTableBorder* cellTableStyle;
|
||||
cellTableStyle = aCell->StyleTableBorder();
|
||||
if (NS_STYLE_TABLE_EMPTY_CELLS_SHOW != cellTableStyle->mEmptyCells &&
|
||||
aCell->GetContentEmpty() && !mIsBorderCollapse) {
|
||||
return NS_OK;
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t colIndex;
|
||||
aCell->GetColIndex(colIndex);
|
||||
NS_ASSERTION(colIndex < int32_t(mNumCols), "prevent array boundary violation");
|
||||
if (int32_t(mNumCols) <= colIndex)
|
||||
return NS_OK;
|
||||
// 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;
|
||||
|
||||
// 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();
|
||||
|
||||
//Paint column group background
|
||||
if (mCols && mCols[colIndex].mColGroup && mCols[colIndex].mColGroup->IsVisible()) {
|
||||
if (haveColumns && mCols[colIndex].mColGroup.IsVisible()) {
|
||||
nsCSSRendering::PaintBackgroundWithSC(mPresContext, mRenderingContext,
|
||||
mCols[colIndex].mColGroup->mFrame, mDirtyRect,
|
||||
mCols[colIndex].mColGroup->mRect + mRenderPt,
|
||||
mCols[colIndex].mColGroup->mFrame->StyleContext(),
|
||||
*mCols[colIndex].mColGroup->mBorder,
|
||||
mCols[colIndex].mColGroup.mFrame, mDirtyRect,
|
||||
mCols[colIndex].mColGroup.mRect + mRenderPt,
|
||||
mCols[colIndex].mColGroup.mFrame->StyleContext(),
|
||||
mCols[colIndex].mColGroup.StyleBorder(mZeroBorder),
|
||||
mBGPaintFlags, &aColBGRect);
|
||||
}
|
||||
|
||||
//Paint column background
|
||||
if (mCols && mCols[colIndex].mCol.IsVisible()) {
|
||||
if (haveColumns && mCols[colIndex].mCol.IsVisible()) {
|
||||
nsCSSRendering::PaintBackgroundWithSC(mPresContext, mRenderingContext,
|
||||
mCols[colIndex].mCol.mFrame, mDirtyRect,
|
||||
mCols[colIndex].mCol.mRect + mRenderPt,
|
||||
mCols[colIndex].mCol.mFrame->StyleContext(),
|
||||
*mCols[colIndex].mCol.mBorder,
|
||||
mCols[colIndex].mCol.StyleBorder(mZeroBorder),
|
||||
mBGPaintFlags, &aColBGRect);
|
||||
}
|
||||
|
||||
//Paint row group background
|
||||
if (mRowGroup.IsVisible()) {
|
||||
if (aRowGroupBGData.IsVisible()) {
|
||||
nsCSSRendering::PaintBackgroundWithSC(mPresContext, mRenderingContext,
|
||||
mRowGroup.mFrame, mDirtyRect,
|
||||
mRowGroup.mRect + mRenderPt,
|
||||
mRowGroup.mFrame->StyleContext(),
|
||||
*mRowGroup.mBorder,
|
||||
aRowGroupBGData.mFrame, mDirtyRect,
|
||||
aRowGroupBGData.mRect + mRenderPt,
|
||||
aRowGroupBGData.mFrame->StyleContext(),
|
||||
aRowGroupBGData.StyleBorder(mZeroBorder),
|
||||
mBGPaintFlags, &aRowGroupBGRect);
|
||||
}
|
||||
|
||||
//Paint row background
|
||||
if (mRow.IsVisible()) {
|
||||
if (aRowBGData.IsVisible()) {
|
||||
nsCSSRendering::PaintBackgroundWithSC(mPresContext, mRenderingContext,
|
||||
mRow.mFrame, mDirtyRect,
|
||||
mRow.mRect + mRenderPt,
|
||||
mRow.mFrame->StyleContext(),
|
||||
*mRow.mBorder,
|
||||
aRowBGData.mFrame, mDirtyRect,
|
||||
aRowBGData.mRect + mRenderPt,
|
||||
aRowBGData.mFrame->StyleContext(),
|
||||
aRowBGData.StyleBorder(mZeroBorder),
|
||||
mBGPaintFlags, &aRowBGRect);
|
||||
}
|
||||
|
||||
|
@ -659,12 +576,12 @@ TableBackgroundPainter::PaintCell(nsTableCellFrame* aCell,
|
|||
aCell->PaintCellBackground(mRenderingContext, mDirtyRect,
|
||||
aCellBGRect.TopLeft(), mBGPaintFlags);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
TableBackgroundPainter::ComputeCellBackgrounds(nsTableCellFrame* aCell,
|
||||
const TableBackgroundData& aRowGroupBGData,
|
||||
const TableBackgroundData& aRowBGData,
|
||||
nsRect& aCellBGRect,
|
||||
nsRect& aRowBGRect,
|
||||
nsRect& aRowGroupBGRect,
|
||||
|
@ -694,11 +611,11 @@ TableBackgroundPainter::ComputeCellBackgrounds(nsTableCellFrame* aCell,
|
|||
// We cannot rely on the row group background data to be available, since some
|
||||
// callers enter through PaintRow.
|
||||
nsIFrame* rowGroupFrame =
|
||||
mRowGroup.mFrame ? mRowGroup.mFrame : mRow.mFrame->GetParent();
|
||||
aRowGroupBGData.mFrame ? aRowGroupBGData.mFrame : aRowBGData.mFrame->GetParent();
|
||||
|
||||
// The cell background goes at the cell's position, translated to use the same
|
||||
// coordinate system as mRow.
|
||||
aCellBGRect = aCell->GetRect() + mRow.mRect.TopLeft() + mRenderPt;
|
||||
// coordinate system as aRowBGData.
|
||||
aCellBGRect = aCell->GetRect() + aRowBGData.mRect.TopLeft() + mRenderPt;
|
||||
|
||||
// The row background goes at the normal position of the cell, which is to say
|
||||
// the position without relative positioning applied.
|
||||
|
@ -707,7 +624,7 @@ TableBackgroundPainter::ComputeCellBackgrounds(nsTableCellFrame* aCell,
|
|||
// The row group background goes at the position we'd find the cell if neither
|
||||
// the cell's relative positioning nor the row's were applied.
|
||||
aRowGroupBGRect = aRowBGRect +
|
||||
(mRow.mFrame->GetNormalPosition() - mRow.mFrame->GetPosition());
|
||||
(aRowBGData.mFrame->GetNormalPosition() - aRowBGData.mFrame->GetPosition());
|
||||
|
||||
// The column and column group backgrounds (they're always at the same
|
||||
// location, since relative positioning doesn't apply to columns or column
|
||||
|
|
|
@ -81,8 +81,8 @@ class TableBackgroundPainter
|
|||
* @param aPaintTableBackground - if true, the table background
|
||||
* is included, otherwise it isn't
|
||||
*/
|
||||
nsresult PaintTable(nsTableFrame* aTableFrame, const nsMargin& aDeflate,
|
||||
bool aPaintTableBackground);
|
||||
void PaintTable(nsTableFrame* aTableFrame, const nsMargin& aDeflate,
|
||||
bool aPaintTableBackground);
|
||||
|
||||
/** Paint background for the row group and its children down through cells
|
||||
* (Cells themselves will only be painted in border collapse)
|
||||
|
@ -91,8 +91,7 @@ class TableBackgroundPainter
|
|||
* children afterwards
|
||||
* @param aFrame - the table row group frame
|
||||
*/
|
||||
nsresult PaintRowGroup(nsTableRowGroupFrame* aFrame)
|
||||
{ return PaintRowGroup(aFrame, false); }
|
||||
void PaintRowGroup(nsTableRowGroupFrame* aFrame);
|
||||
|
||||
/** Paint background for the row and its children down through cells
|
||||
* (Cells themselves will only be painted in border collapse)
|
||||
|
@ -101,10 +100,10 @@ class TableBackgroundPainter
|
|||
* children afterwards
|
||||
* @param aFrame - the table row frame
|
||||
*/
|
||||
nsresult PaintRow(nsTableRowFrame* aFrame)
|
||||
{ return PaintRow(aFrame, false); }
|
||||
void PaintRow(nsTableRowFrame* aFrame);
|
||||
|
||||
private:
|
||||
struct TableBackgroundData;
|
||||
|
||||
/** Paint table frame's background
|
||||
* @param aTableFrame - the table frame
|
||||
|
@ -115,38 +114,50 @@ class TableBackgroundPainter
|
|||
* @param aDeflate - adjustment to frame's rect (used for quirks BC)
|
||||
* may be null
|
||||
*/
|
||||
nsresult PaintTableFrame(nsTableFrame* aTableFrame,
|
||||
nsTableRowGroupFrame* aFirstRowGroup,
|
||||
nsTableRowGroupFrame* aLastRowGroup,
|
||||
const nsMargin& aDeflate);
|
||||
void PaintTableFrame(nsTableFrame* aTableFrame,
|
||||
nsTableRowGroupFrame* aFirstRowGroup,
|
||||
nsTableRowGroupFrame* aLastRowGroup,
|
||||
const nsMargin& aDeflate);
|
||||
|
||||
/* aPassThrough params indicate whether to paint the element or to just
|
||||
* pass through and paint underlying layers only
|
||||
* pass through and paint underlying layers only.
|
||||
* aRowGroupBGData is not a const reference because the function modifies
|
||||
* its copy. Same for aRowBGData in PaintRow.
|
||||
* See Public versions for function descriptions
|
||||
*/
|
||||
nsresult PaintRowGroup(nsTableRowGroupFrame* aFrame,
|
||||
bool aPassThrough);
|
||||
nsresult PaintRow(nsTableRowFrame* aFrame,
|
||||
bool aPassThrough);
|
||||
void PaintRowGroup(nsTableRowGroupFrame* aFrame,
|
||||
TableBackgroundData aRowGroupBGData,
|
||||
bool aPassThrough);
|
||||
|
||||
void PaintRow(nsTableRowFrame* aFrame,
|
||||
const TableBackgroundData& aRowGroupBGData,
|
||||
TableBackgroundData aRowBGData,
|
||||
bool aPassThrough);
|
||||
|
||||
/** Paint table background layers for this cell space
|
||||
* Also paints cell's own background in border-collapse mode
|
||||
* @param aCell - the cell
|
||||
* @param aRowGroupBGData - background drawing info for the row group
|
||||
* @param aRowBGData - background drawing info for the row
|
||||
* @param aCellBGRect - background rect for the cell
|
||||
* @param aRowBGRect - background rect for the row
|
||||
* @param aRowGroupBGRect - background rect for the row group
|
||||
* @param aColBGRect - background rect for the column and column group
|
||||
* @param aPassSelf - pass this cell; i.e. paint only underlying layers
|
||||
*/
|
||||
nsresult PaintCell(nsTableCellFrame* aCell,
|
||||
nsRect& aCellBGRect,
|
||||
nsRect& aRowBGRect,
|
||||
nsRect& aRowGroupBGRect,
|
||||
nsRect& aColBGRect,
|
||||
bool aPassSelf);
|
||||
void PaintCell(nsTableCellFrame* aCell,
|
||||
const TableBackgroundData& aRowGroupBGData,
|
||||
const TableBackgroundData& aRowBGData,
|
||||
nsRect& aCellBGRect,
|
||||
nsRect& aRowBGRect,
|
||||
nsRect& aRowGroupBGRect,
|
||||
nsRect& aColBGRect,
|
||||
bool aPassSelf);
|
||||
|
||||
/** Compute table background layer positions for this cell space
|
||||
* @param aCell - the cell
|
||||
* @param aRowGroupBGData - background drawing info for the row group
|
||||
* @param aRowBGData - background drawing info for the row
|
||||
* @param aCellBGRectOut - outparam: background rect for the cell
|
||||
* @param aRowBGRectOut - outparam: background rect for the row
|
||||
* @param aRowGroupBGRectOut - outparam: background rect for the row group
|
||||
|
@ -154,6 +165,8 @@ class TableBackgroundPainter
|
|||
and column group
|
||||
*/
|
||||
void ComputeCellBackgrounds(nsTableCellFrame* aCell,
|
||||
const TableBackgroundData& aRowGroupBGData,
|
||||
const TableBackgroundData& aRowBGData,
|
||||
nsRect& aCellBGRect,
|
||||
nsRect& aRowBGRect,
|
||||
nsRect& aRowGroupBGRect,
|
||||
|
@ -167,59 +180,58 @@ class TableBackgroundPainter
|
|||
void TranslateContext(nscoord aDX,
|
||||
nscoord aDY);
|
||||
|
||||
struct TableBackgroundData;
|
||||
friend struct TableBackgroundData;
|
||||
struct TableBackgroundData {
|
||||
nsIFrame* mFrame;
|
||||
/** mRect is the rect of mFrame in the current coordinate system */
|
||||
nsRect mRect;
|
||||
bool mVisible;
|
||||
const nsStyleBorder* mBorder;
|
||||
public:
|
||||
/**
|
||||
* Construct an empty TableBackgroundData instance, which is invisible.
|
||||
*/
|
||||
TableBackgroundData();
|
||||
|
||||
/**
|
||||
* Construct a TableBackgroundData instance for a frame. Visibility will
|
||||
* be derived from the frame and can be overridden using MakeInvisible().
|
||||
*/
|
||||
explicit TableBackgroundData(nsIFrame* aFrame);
|
||||
|
||||
/** Destructor */
|
||||
~TableBackgroundData() {}
|
||||
|
||||
/** Data is valid & frame is visible */
|
||||
bool IsVisible() const { return mVisible; }
|
||||
|
||||
/** Constructor */
|
||||
TableBackgroundData();
|
||||
/** Destructor */
|
||||
~TableBackgroundData();
|
||||
/** Destroys synthesized data. MUST be called before destructor
|
||||
* @param aPresContext - the pres context
|
||||
*/
|
||||
void Destroy(nsPresContext* aPresContext);
|
||||
|
||||
|
||||
/** Clear background data */
|
||||
void Clear();
|
||||
|
||||
/** Calculate and set all data values to represent aFrame */
|
||||
void SetFull(nsIFrame* aFrame);
|
||||
|
||||
/** Set frame data (mFrame, mRect) but leave style data empty */
|
||||
void SetFrame(nsIFrame* aFrame);
|
||||
|
||||
/** Calculate the style data for mFrame */
|
||||
void SetData();
|
||||
/** Override visibility of the frame, force it to be invisible */
|
||||
void MakeInvisible() { mVisible = false; }
|
||||
|
||||
/** True if need to set border-collapse border; must call SetFull beforehand */
|
||||
bool ShouldSetBCBorder();
|
||||
bool ShouldSetBCBorder() const;
|
||||
|
||||
/** Set border-collapse border with aBorderWidth as widths */
|
||||
nsresult SetBCBorder(nsMargin& aBorderWidth,
|
||||
TableBackgroundPainter* aPainter);
|
||||
void SetBCBorder(const nsMargin& aBorderWidth);
|
||||
|
||||
private:
|
||||
nsStyleBorder* mSynthBorder;
|
||||
/**
|
||||
* @param aZeroBorder An nsStyleBorder instance that has been initialized
|
||||
* for the right nsPresContext, with all border widths
|
||||
* set to zero and border styles set to solid.
|
||||
* @return The nsStyleBorder that should be used for rendering
|
||||
* this background.
|
||||
*/
|
||||
nsStyleBorder StyleBorder(const nsStyleBorder& aZeroBorder) const;
|
||||
|
||||
nsIFrame* const mFrame;
|
||||
|
||||
/** mRect is the rect of mFrame in the current coordinate system */
|
||||
nsRect mRect;
|
||||
|
||||
private:
|
||||
nsMargin mSynthBorderWidths;
|
||||
bool mVisible;
|
||||
bool mUsesSynthBorder;
|
||||
};
|
||||
|
||||
struct ColData;
|
||||
friend struct ColData;
|
||||
struct ColData {
|
||||
TableBackgroundData mCol;
|
||||
TableBackgroundData* mColGroup; //link to col's parent colgroup's data (owned by painter)
|
||||
ColData() {
|
||||
mColGroup = nullptr;
|
||||
}
|
||||
ColData(nsIFrame* aFrame, TableBackgroundData& aColGroupBGData);
|
||||
TableBackgroundData mCol;
|
||||
TableBackgroundData& mColGroup; // reference to col's parent colgroup's data, owned by TablePainter in mColGroups
|
||||
};
|
||||
|
||||
nsPresContext* mPresContext;
|
||||
|
@ -232,10 +244,9 @@ class TableBackgroundPainter
|
|||
bool mIsBorderCollapse;
|
||||
Origin mOrigin; //user's table frame type
|
||||
|
||||
ColData* mCols; //array of columns' ColData
|
||||
uint32_t mNumCols;
|
||||
TableBackgroundData mRowGroup; //current row group
|
||||
TableBackgroundData mRow; //current row
|
||||
nsTArray<TableBackgroundData> mColGroups;
|
||||
nsTArray<ColData> mCols;
|
||||
size_t mNumCols;
|
||||
|
||||
nsStyleBorder mZeroBorder; //cached zero-width border
|
||||
uint32_t mBGPaintFlags;
|
||||
|
|
Загрузка…
Ссылка в новой задаче