implement standards compliant (CSS2.1) table background rendering patch by fantasai@escape.com r=bernd sr=bz, dbaron

This commit is contained in:
bmlk%gmx.de 2004-03-09 06:48:35 +00:00
parent 1629547b88
commit ea9e726b8b
41 changed files with 3083 additions and 412 deletions

View File

@ -538,16 +538,24 @@ void nsStyleBorder::RecalcData()
}
if ((mBorderStyle[NS_SIDE_TOP] & BORDER_COLOR_DEFINED) == 0) {
mBorderStyle[NS_SIDE_TOP] = BORDER_COLOR_DEFINED | BORDER_COLOR_FOREGROUND;
NS_ASSERTION(!(mBorderStyle[NS_SIDE_TOP] & BORDER_COLOR_SPECIAL),
"Clearing special border because BORDER_COLOR_DEFINED is not set");
SetBorderToForeground(NS_SIDE_TOP);
}
if ((mBorderStyle[NS_SIDE_BOTTOM] & BORDER_COLOR_DEFINED) == 0) {
mBorderStyle[NS_SIDE_BOTTOM] = BORDER_COLOR_DEFINED | BORDER_COLOR_FOREGROUND;
NS_ASSERTION(!(mBorderStyle[NS_SIDE_BOTTOM] & BORDER_COLOR_SPECIAL),
"Clearing special border because BORDER_COLOR_DEFINED is not set");
SetBorderToForeground(NS_SIDE_BOTTOM);
}
if ((mBorderStyle[NS_SIDE_LEFT]& BORDER_COLOR_DEFINED) == 0) {
mBorderStyle[NS_SIDE_LEFT] = BORDER_COLOR_DEFINED | BORDER_COLOR_FOREGROUND;
if ((mBorderStyle[NS_SIDE_LEFT] & BORDER_COLOR_DEFINED) == 0) {
NS_ASSERTION(!(mBorderStyle[NS_SIDE_LEFT] & BORDER_COLOR_SPECIAL),
"Clearing special border because BORDER_COLOR_DEFINED is not set");
SetBorderToForeground(NS_SIDE_LEFT);
}
if ((mBorderStyle[NS_SIDE_RIGHT] & BORDER_COLOR_DEFINED) == 0) {
mBorderStyle[NS_SIDE_RIGHT] = BORDER_COLOR_DEFINED | BORDER_COLOR_FOREGROUND;
NS_ASSERTION(!(mBorderStyle[NS_SIDE_RIGHT] & BORDER_COLOR_SPECIAL),
"Clearing special border because BORDER_COLOR_DEFINED is not set");
SetBorderToForeground(NS_SIDE_RIGHT);
}
}

View File

@ -2716,7 +2716,8 @@ nsCSSRendering::PaintBackground(nsIPresContext* aPresContext,
const nsRect& aBorderArea,
const nsStyleBorder& aBorder,
const nsStylePadding& aPadding,
PRBool aUsePrintSettings)
PRBool aUsePrintSettings,
nsRect* aBGClipRect)
{
NS_PRECONDITION(aForFrame,
"Frame is expected to be provided to PaintBackground");
@ -2744,7 +2745,7 @@ nsCSSRendering::PaintBackground(nsIPresContext* aPresContext,
if (!isCanvas) {
PaintBackgroundWithSC(aPresContext, aRenderingContext, aForFrame,
aDirtyRect, aBorderArea, *color, aBorder,
aPadding, aUsePrintSettings);
aPadding, aUsePrintSettings, aBGClipRect);
return;
}
@ -2787,7 +2788,7 @@ nsCSSRendering::PaintBackground(nsIPresContext* aPresContext,
PaintBackgroundWithSC(aPresContext, aRenderingContext, aForFrame,
aDirtyRect, aBorderArea, canvasColor,
aBorder, aPadding, aUsePrintSettings);
aBorder, aPadding, aUsePrintSettings, aBGClipRect);
}
void
@ -2799,7 +2800,8 @@ nsCSSRendering::PaintBackgroundWithSC(nsIPresContext* aPresContext,
const nsStyleBackground& aColor,
const nsStyleBorder& aBorder,
const nsStylePadding& aPadding,
PRBool aUsePrintSettings)
PRBool aUsePrintSettings,
nsRect* aBGClipRect)
{
NS_PRECONDITION(aForFrame,
"Frame is expected to be provided to PaintBackground");
@ -2825,14 +2827,20 @@ nsCSSRendering::PaintBackgroundWithSC(nsIPresContext* aPresContext,
}
}
// The background is rendered over the 'background-clip' area.
nsRect bgClipArea(aBorderArea);
if (aColor.mBackgroundClip != NS_STYLE_BG_CLIP_BORDER) {
NS_ASSERTION(aColor.mBackgroundClip == NS_STYLE_BG_CLIP_PADDING,
"unknown background-clip value");
nsMargin border;
aBorder.GetBorder(border);
bgClipArea.Deflate(border);
nsRect bgClipArea;
if (aBGClipRect) {
bgClipArea = *aBGClipRect;
}
else {
// The background is rendered over the 'background-clip' area.
bgClipArea = aBorderArea;
if (aColor.mBackgroundClip != NS_STYLE_BG_CLIP_BORDER) {
NS_ASSERTION(aColor.mBackgroundClip == NS_STYLE_BG_CLIP_PADDING,
"unknown background-clip value");
nsMargin border;
aBorder.GetBorder(border);
bgClipArea.Deflate(border);
}
}
// The actual dirty rect is the intersection of the 'background-clip'
@ -3186,41 +3194,41 @@ nsCSSRendering::PaintBackgroundWithSC(nsIPresContext* aPresContext,
// first do the horizontal case
nscoord x0, x1;
// For scrolling attachment, the anchor is within the 'background-clip'
// For fixed attachment, the anchor is within the bounds of the nearest
// scrolling ancestor (or the viewport)
x0 = (NS_STYLE_BG_ATTACHMENT_SCROLL == aColor.mBackgroundAttachment) ?
bgClipArea.x : 0;
if (repeat & NS_STYLE_BG_REPEAT_X) {
// When tiling in the x direction, adjust the starting position of the
// tile to account for dirtyRect.x. When tiling in x, the anchor.x value
// will be a negative value used to adjust the starting coordinate.
x0 = bgClipArea.x + anchor.x + ((dirtyRect.x - (bgClipArea.x + anchor.x)) / tileWidth) * tileWidth;
x0 += anchor.x +
((dirtyRect.x - (bgClipArea.x + anchor.x)) / tileWidth) * tileWidth;
x1 = x0 + ((dirtyRect.x + dirtyRect.width - x0 + tileWidth - 1) / tileWidth) * tileWidth;
}
else {
// For scrolling attachment, the anchor is within the 'background-clip'
// For fixed attachment, the anchor is within the bounds of the nearest
// scrolling ancestor (or the viewport)
x0 = anchor.x;
if (NS_STYLE_BG_ATTACHMENT_SCROLL == aColor.mBackgroundAttachment) {
x0 += bgClipArea.x;
}
x0 += anchor.x;
x1 = x0 + tileWidth;
}
// now do all that again with the vertical case
nscoord y0, y1;
// For scrolling attachment, the anchor is within the 'background-clip'
// For fixed attachment, the anchor is within the bounds of the nearest
// scrolling ancestor (or the viewport)
y0 = (NS_STYLE_BG_ATTACHMENT_SCROLL == aColor.mBackgroundAttachment) ?
bgClipArea.y : 0;
if (repeat & NS_STYLE_BG_REPEAT_Y) {
// When tiling in the y direction, adjust the starting position of the
// tile to account for dirtyRect.y. When tiling in y, the anchor.y value
// will be a negative value used to adjust the starting coordinate.
y0 = bgClipArea.y + anchor.y + ((dirtyRect.y - (bgClipArea.y + anchor.y)) / tileHeight) * tileHeight;
y0 += anchor.y +
((dirtyRect.y - (bgClipArea.y + anchor.y)) / tileHeight) * tileHeight;
y1 = y0 + ((dirtyRect.y + dirtyRect.height - y0 + tileHeight - 1) / tileHeight) * tileHeight;
}
else {
// For scrolling attachment, the anchor is within the 'background-clip'
// For fixed attachment, the anchor is within the bounds of the nearest
// scrolling ancestor (or the viewport)
y0 = anchor.y;
if (NS_STYLE_BG_ATTACHMENT_SCROLL == aColor.mBackgroundAttachment) {
y0 += bgClipArea.y;
}
y0 += anchor.y;
y1 = y0 + tileHeight;
}

View File

@ -140,7 +140,8 @@ public:
const nsRect& aBorderArea,
const nsStyleBorder& aBorder,
const nsStylePadding& aPadding,
PRBool aUsePrintSettings);
PRBool aUsePrintSettings,
nsRect* aBGClipRect = nsnull);
/**
* Same as |PaintBackground|, except using the provided style context
@ -155,7 +156,9 @@ public:
const nsStyleBackground& aColor,
const nsStyleBorder& aBorder,
const nsStylePadding& aPadding,
PRBool aUsePrintSettings=PR_FALSE);
PRBool aUsePrintSettings = PR_FALSE,
nsRect* aBGClipRect = nsnull);
/**
* Called by the presShell when painting is finished, so we can clear our
* inline background data cache.

View File

@ -150,7 +150,7 @@ plaintext, xmp, pre {
table {
display: table;
border-spacing: 2px;
border-spacing: 2px;
border-collapse: separate;
margin-top: 0;
margin-bottom: 0;
@ -170,11 +170,6 @@ table[align="right"] {
table[rules] {
border-collapse: collapse;
}
/* make sure backgrounds are inherited in tables -- see bug 4510 */
td, th, tr {
background: inherit;
}
/* caption inherits from table not table-outer */
caption {

View File

@ -110,6 +110,10 @@ table {
font-variant: -moz-initial;
}
/* make sure backgrounds are inherited in tables -- see bug 4510*/
td, th, tr {
background: inherit;
}
/* Quirk: collapse top margin of BODY and TD and bottom margin of TD */

View File

@ -2716,7 +2716,8 @@ nsCSSRendering::PaintBackground(nsIPresContext* aPresContext,
const nsRect& aBorderArea,
const nsStyleBorder& aBorder,
const nsStylePadding& aPadding,
PRBool aUsePrintSettings)
PRBool aUsePrintSettings,
nsRect* aBGClipRect)
{
NS_PRECONDITION(aForFrame,
"Frame is expected to be provided to PaintBackground");
@ -2744,7 +2745,7 @@ nsCSSRendering::PaintBackground(nsIPresContext* aPresContext,
if (!isCanvas) {
PaintBackgroundWithSC(aPresContext, aRenderingContext, aForFrame,
aDirtyRect, aBorderArea, *color, aBorder,
aPadding, aUsePrintSettings);
aPadding, aUsePrintSettings, aBGClipRect);
return;
}
@ -2787,7 +2788,7 @@ nsCSSRendering::PaintBackground(nsIPresContext* aPresContext,
PaintBackgroundWithSC(aPresContext, aRenderingContext, aForFrame,
aDirtyRect, aBorderArea, canvasColor,
aBorder, aPadding, aUsePrintSettings);
aBorder, aPadding, aUsePrintSettings, aBGClipRect);
}
void
@ -2799,7 +2800,8 @@ nsCSSRendering::PaintBackgroundWithSC(nsIPresContext* aPresContext,
const nsStyleBackground& aColor,
const nsStyleBorder& aBorder,
const nsStylePadding& aPadding,
PRBool aUsePrintSettings)
PRBool aUsePrintSettings,
nsRect* aBGClipRect)
{
NS_PRECONDITION(aForFrame,
"Frame is expected to be provided to PaintBackground");
@ -2825,14 +2827,20 @@ nsCSSRendering::PaintBackgroundWithSC(nsIPresContext* aPresContext,
}
}
// The background is rendered over the 'background-clip' area.
nsRect bgClipArea(aBorderArea);
if (aColor.mBackgroundClip != NS_STYLE_BG_CLIP_BORDER) {
NS_ASSERTION(aColor.mBackgroundClip == NS_STYLE_BG_CLIP_PADDING,
"unknown background-clip value");
nsMargin border;
aBorder.GetBorder(border);
bgClipArea.Deflate(border);
nsRect bgClipArea;
if (aBGClipRect) {
bgClipArea = *aBGClipRect;
}
else {
// The background is rendered over the 'background-clip' area.
bgClipArea = aBorderArea;
if (aColor.mBackgroundClip != NS_STYLE_BG_CLIP_BORDER) {
NS_ASSERTION(aColor.mBackgroundClip == NS_STYLE_BG_CLIP_PADDING,
"unknown background-clip value");
nsMargin border;
aBorder.GetBorder(border);
bgClipArea.Deflate(border);
}
}
// The actual dirty rect is the intersection of the 'background-clip'
@ -3186,41 +3194,41 @@ nsCSSRendering::PaintBackgroundWithSC(nsIPresContext* aPresContext,
// first do the horizontal case
nscoord x0, x1;
// For scrolling attachment, the anchor is within the 'background-clip'
// For fixed attachment, the anchor is within the bounds of the nearest
// scrolling ancestor (or the viewport)
x0 = (NS_STYLE_BG_ATTACHMENT_SCROLL == aColor.mBackgroundAttachment) ?
bgClipArea.x : 0;
if (repeat & NS_STYLE_BG_REPEAT_X) {
// When tiling in the x direction, adjust the starting position of the
// tile to account for dirtyRect.x. When tiling in x, the anchor.x value
// will be a negative value used to adjust the starting coordinate.
x0 = bgClipArea.x + anchor.x + ((dirtyRect.x - (bgClipArea.x + anchor.x)) / tileWidth) * tileWidth;
x0 += anchor.x +
((dirtyRect.x - (bgClipArea.x + anchor.x)) / tileWidth) * tileWidth;
x1 = x0 + ((dirtyRect.x + dirtyRect.width - x0 + tileWidth - 1) / tileWidth) * tileWidth;
}
else {
// For scrolling attachment, the anchor is within the 'background-clip'
// For fixed attachment, the anchor is within the bounds of the nearest
// scrolling ancestor (or the viewport)
x0 = anchor.x;
if (NS_STYLE_BG_ATTACHMENT_SCROLL == aColor.mBackgroundAttachment) {
x0 += bgClipArea.x;
}
x0 += anchor.x;
x1 = x0 + tileWidth;
}
// now do all that again with the vertical case
nscoord y0, y1;
// For scrolling attachment, the anchor is within the 'background-clip'
// For fixed attachment, the anchor is within the bounds of the nearest
// scrolling ancestor (or the viewport)
y0 = (NS_STYLE_BG_ATTACHMENT_SCROLL == aColor.mBackgroundAttachment) ?
bgClipArea.y : 0;
if (repeat & NS_STYLE_BG_REPEAT_Y) {
// When tiling in the y direction, adjust the starting position of the
// tile to account for dirtyRect.y. When tiling in y, the anchor.y value
// will be a negative value used to adjust the starting coordinate.
y0 = bgClipArea.y + anchor.y + ((dirtyRect.y - (bgClipArea.y + anchor.y)) / tileHeight) * tileHeight;
y0 += anchor.y +
((dirtyRect.y - (bgClipArea.y + anchor.y)) / tileHeight) * tileHeight;
y1 = y0 + ((dirtyRect.y + dirtyRect.height - y0 + tileHeight - 1) / tileHeight) * tileHeight;
}
else {
// For scrolling attachment, the anchor is within the 'background-clip'
// For fixed attachment, the anchor is within the bounds of the nearest
// scrolling ancestor (or the viewport)
y0 = anchor.y;
if (NS_STYLE_BG_ATTACHMENT_SCROLL == aColor.mBackgroundAttachment) {
y0 += bgClipArea.y;
}
y0 += anchor.y;
y1 = y0 + tileHeight;
}

View File

@ -140,7 +140,8 @@ public:
const nsRect& aBorderArea,
const nsStyleBorder& aBorder,
const nsStylePadding& aPadding,
PRBool aUsePrintSettings);
PRBool aUsePrintSettings,
nsRect* aBGClipRect = nsnull);
/**
* Same as |PaintBackground|, except using the provided style context
@ -155,7 +156,9 @@ public:
const nsStyleBackground& aColor,
const nsStyleBorder& aBorder,
const nsStylePadding& aPadding,
PRBool aUsePrintSettings=PR_FALSE);
PRBool aUsePrintSettings = PR_FALSE,
nsRect* aBGClipRect = nsnull);
/**
* Called by the presShell when painting is finished, so we can clear our
* inline background data cache.

View File

@ -52,6 +52,7 @@ CPPSRCS = \
nsTableOuterFrame.cpp \
nsTableRowFrame.cpp \
nsTableRowGroupFrame.cpp \
nsTablePainter.cpp \
$(NULL)
# we don't want the shared lib, but we want to force the creation of a static lib.

View File

@ -88,11 +88,11 @@ nsTableCellMap::nsTableCellMap(nsTableFrame& aTableFrame,
NS_ASSERTION(orderedRowGroups.Count() == (PRInt32) numRowGroups,"problem in OrderRowGroups");
for (PRUint32 rgX = 0; rgX < numRowGroups; rgX++) {
nsTableRowGroupFrame* rgFrame =
aTableFrame.GetRowGroupFrame((nsIFrame*)orderedRowGroups.ElementAt(rgX));
nsTableRowGroupFrame* rgFrame =
nsTableFrame::GetRowGroupFrame((nsIFrame*)orderedRowGroups.ElementAt(rgX));
if (rgFrame) {
nsTableRowGroupFrame* prior = (0 == rgX)
? nsnull : aTableFrame.GetRowGroupFrame((nsIFrame*)orderedRowGroups.ElementAt(rgX - 1));
nsTableRowGroupFrame* prior = (0 == rgX)
? nsnull : nsTableFrame::GetRowGroupFrame((nsIFrame*)orderedRowGroups.ElementAt(rgX - 1));
InsertGroupCellMap(*rgFrame, prior);
}
}

View File

@ -40,6 +40,7 @@
#include "nsTableCellFrame.h"
#include "nsTableFrame.h"
#include "nsTableRowGroupFrame.h"
#include "nsTablePainter.h"
#include "nsReflowPath.h"
#include "nsStyleContext.h"
#include "nsStyleConsts.h"
@ -376,30 +377,23 @@ nsTableCellFrame::PaintUnderlay(nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
PRUint32& aFlags,
const nsStyleTableBorder& aCellTableStyle,
const nsStyleBorder& aStyleBorder,
const nsStylePadding& aStylePadding,
PRBool aVisibleBackground,
PRBool& aPaintChildren)
const nsStyleTableBorder& aCellTableStyle)
{
if (aVisibleBackground) {
nsRect rect(0, 0, mRect.width, mRect.height);
nsCSSRendering::PaintBackground(&aPresContext, aRenderingContext, this,
aDirtyRect, rect, aStyleBorder, aStylePadding,
PR_TRUE);
// draw the border only when there is content or showing empty cells
if (!GetContentEmpty() || NS_STYLE_TABLE_EMPTY_CELLS_SHOW == aCellTableStyle.mEmptyCells) {
PRIntn skipSides = GetSkipSides();
nsCSSRendering::PaintBorder(&aPresContext, aRenderingContext, this,
aDirtyRect, rect, aStyleBorder, mStyleContext, skipSides);
}
nsRect rect(0, 0, mRect.width, mRect.height);
nsCSSRendering::PaintBackground(&aPresContext, aRenderingContext, this,
aDirtyRect, rect, aStyleBorder, aStylePadding,
PR_TRUE);
PRIntn skipSides = GetSkipSides();
if (NS_STYLE_TABLE_EMPTY_CELLS_SHOW == aCellTableStyle.mEmptyCells ||
!GetContentEmpty()) {
nsCSSRendering::PaintBorder(&aPresContext, aRenderingContext, this,
aDirtyRect, rect, aStyleBorder, mStyleContext, skipSides);
}
// tell Paint to paint the children
aPaintChildren = PR_TRUE;
}
NS_METHOD
NS_IMETHODIMP
nsTableCellFrame::Paint(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
@ -412,10 +406,9 @@ nsTableCellFrame::Paint(nsIPresContext* aPresContext,
return NS_OK;
}
PRBool paintChildren = PR_TRUE;
PRBool paintChildren = PR_TRUE;
if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) {
PRBool paintBackground = PR_FALSE;
const nsStyleBorder* myBorder = nsnull;
const nsStylePadding* myPadding = nsnull;
const nsStyleTableBorder* cellTableStyle = nsnull;
@ -425,19 +418,20 @@ nsTableCellFrame::Paint(nsIPresContext* aPresContext,
myPadding = GetStylePadding();
cellTableStyle = GetStyleTableBorder();
// paint the background when the cell is not empty or when showing empty cells or background
paintBackground = (!GetContentEmpty() ||
NS_STYLE_TABLE_EMPTY_CELLS_SHOW == cellTableStyle->mEmptyCells ||
NS_STYLE_TABLE_EMPTY_CELLS_SHOW_BACKGROUND == cellTableStyle->mEmptyCells);
}
PaintUnderlay(*aPresContext, aRenderingContext, aDirtyRect, aFlags, *cellTableStyle,
*myBorder, *myPadding, paintBackground, paintChildren);
// draw the border & background only when there is content or showing empty cells
if (NS_STYLE_TABLE_EMPTY_CELLS_HIDE != cellTableStyle->mEmptyCells ||
!GetContentEmpty()) {
PaintUnderlay(*aPresContext, aRenderingContext, aDirtyRect, aFlags,
*myBorder, *myPadding, *cellTableStyle);
}
if (vis->IsVisible()) {
const nsStyleBackground* myColor = GetStyleBackground();
DecorateForSelection(aPresContext, aRenderingContext,myColor); //ignore return value
}
paintChildren = !(aFlags & NS_PAINT_FLAG_TABLE_CELL_BG_PASS);
//flags were for us; remove them for our children
aFlags &= ~ (NS_PAINT_FLAG_TABLE_CELL_BG_PASS | NS_PAINT_FLAG_TABLE_BG_PAINT);
}
#ifdef DEBUG
@ -931,7 +925,7 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext,
const nsStylePosition* pos = GetStylePosition();
// calculate the min cell width
nscoord onePixel = NSIntPixelsToTwips(1, p2t);
nscoord onePixel = NSIntPixelsToTwips(1, p2t);
nscoord smallestMinWidth = 0;
if (eCompatibility_NavQuirks == compatMode) {
if ((pos->mWidth.GetUnit() != eStyleUnit_Coord) &&
@ -1332,14 +1326,14 @@ nsBCTableCellFrame::PaintUnderlay(nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
PRUint32& aFlags,
const nsStyleTableBorder& aCellTableStyle,
const nsStyleBorder& aStyleBorder,
const nsStylePadding& aStylePadding,
PRBool aVisibleBackground,
PRBool& aPaintChildren)
const nsStyleTableBorder& aCellTableStyle)
{
// Draw the background only during pass1.
if (aVisibleBackground && !(aFlags & BORDER_COLLAPSE_BACKGROUNDS)) {
if (!(aFlags & NS_PAINT_FLAG_TABLE_BG_PAINT)
/*direct call; not table-based paint*/ ||
(aFlags & NS_PAINT_FLAG_TABLE_CELL_BG_PASS)
/*table cell background only pass*/) {
// make border-width reflect border-collapse assigned border
GET_PIXELS_TO_TWIPS(&aPresContext, p2t);
nsMargin borderWidth;
@ -1363,7 +1357,4 @@ nsBCTableCellFrame::PaintUnderlay(nsIPresContext& aPresContext,
PR_TRUE);
// borders are painted by nsTableFrame
}
// don't paint the children if it's pass1
aPaintChildren = (aFlags & BORDER_COLLAPSE_BACKGROUNDS);
}

View File

@ -289,16 +289,13 @@ protected:
friend class nsTableRowFrame;
// paint backgrounds and borders (in separate border model) if aVisibleBackground, always set aPaintChildren
virtual void PaintUnderlay(nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
PRUint32& aFlags,
const nsStyleTableBorder& aCellTableStyle,
const nsStyleBorder& aStyleBorder,
const nsStylePadding& aStylePadding,
PRBool aVisibleBackground,
PRBool& aPaintChildren);
const nsStyleTableBorder& aCellTableStyle);
nsresult DecorateForSelection(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
@ -471,11 +468,9 @@ protected:
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
PRUint32& aFlags,
const nsStyleTableBorder& aCellTableStyle,
const nsStyleBorder& aStyleBorder,
const nsStylePadding& aStylePadding,
PRBool aVisibleBackground,
PRBool& aPaintChildren);
const nsStyleTableBorder& aCellTableStyle);
private:

View File

@ -118,6 +118,24 @@ nsStyleCoord nsTableColFrame::GetStyleWidth() const
return returnWidth;
}
void nsTableColFrame::SetContinuousBCBorderWidth(PRUint8 aForSide,
BCPixelSize aPixelValue)
{
switch (aForSide) {
case NS_SIDE_TOP:
mTopContBorderWidth = aPixelValue;
return;
case NS_SIDE_RIGHT:
mRightContBorderWidth = aPixelValue;
return;
case NS_SIDE_BOTTOM:
mBottomContBorderWidth = aPixelValue;
return;
default:
NS_ERROR("invalid side arg");
}
}
void nsTableColFrame::ResetSizingInfo()
{
memset(mWidths, WIDTH_NOT_SET, NUM_WIDTHS * sizeof(PRInt32));
@ -135,8 +153,6 @@ nsTableColFrame::Paint(nsIPresContext* aPresContext,
if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_FALSE, &isVisible)) && !isVisible) {
return NS_OK;
}
// Standards mode background painting removed. See bug 4510
return NS_OK;
}

View File

@ -39,6 +39,7 @@
#include "nscore.h"
#include "nsContainerFrame.h"
#include "nsTablePainter.h"
class nsVoidArray;
class nsTableCellFrame;
@ -169,9 +170,26 @@ public:
void ResetSizingInfo();
nscoord GetLeftBorderWidth(float* aPixelsToTwips = nsnull);
void SetLeftBorderWidth(nscoord aWidth);
void SetLeftBorderWidth(BCPixelSize aWidth);
nscoord GetRightBorderWidth(float* aPixelsToTwips = nsnull);
void SetRightBorderWidth(nscoord aWidth);
void SetRightBorderWidth(BCPixelSize aWidth);
/**
* Gets inner border widths before collapsing with cell borders
* Caller must get left border from previous column or from table
* GetContinuousBCBorderWidth will not overwrite aBorder.left
* see nsTablePainter about continuous borders
*
* @return outer right border width (left inner for next column)
*/
nscoord GetContinuousBCBorderWidth(float aPixelsToTwips,
nsMargin& aBorder);
/**
* Set full border widths before collapsing with cell borders
* @param aForSide - side to set; only valid for top, right, and bottom
*/
void SetContinuousBCBorderWidth(PRUint8 aForSide,
BCPixelSize aPixelValue);
void Dump(PRInt32 aIndent);
@ -182,8 +200,13 @@ protected:
// the starting index of the column (starting at 0) that this col object represents //
PRUint32 mColIndex: 16;
PRUint32 mLeftBorderWidth: 8; // stored as pixels
PRUint32 mRightBorderWidth: 8; // stored as pixels
// border width in pixels
BCPixelSize mLeftBorderWidth;
BCPixelSize mRightBorderWidth;
BCPixelSize mTopContBorderWidth;
BCPixelSize mRightContBorderWidth;
BCPixelSize mBottomContBorderWidth;
// Widths including MIN_CON, DES_CON, FIX_CON, MIN_ADJ, DES_ADJ, FIX_ADJ, PCT, PCT_ADJ, MIN_PRO, FINAL
// Widths including MIN_CON, DES_CON, FIX_CON, MIN_ADJ, DES_ADJ, FIX_ADJ, PCT, PCT_ADJ, MIN_PRO, FINAL
// XXX these could be stored as pixels and converted to twips for a savings of 10 x 2 bytes.
@ -191,7 +214,7 @@ protected:
};
inline PRInt32 nsTableColFrame::GetColIndex() const
{
{
return mColIndex;
}
@ -206,7 +229,7 @@ inline nscoord nsTableColFrame::GetLeftBorderWidth(float* aPixelsToTwips)
return width;
}
inline void nsTableColFrame::SetLeftBorderWidth(nscoord aWidth)
inline void nsTableColFrame::SetLeftBorderWidth(BCPixelSize aWidth)
{
mLeftBorderWidth = aWidth;
}
@ -217,10 +240,23 @@ inline nscoord nsTableColFrame::GetRightBorderWidth(float* aPixelsToTwips)
return width;
}
inline void nsTableColFrame::SetRightBorderWidth(nscoord aWidth)
inline void nsTableColFrame::SetRightBorderWidth(BCPixelSize aWidth)
{
mRightBorderWidth = aWidth;
}
inline nscoord
nsTableColFrame::GetContinuousBCBorderWidth(float aPixelsToTwips,
nsMargin& aBorder)
{
aBorder.top = BC_BORDER_BOTTOM_HALF_COORD(aPixelsToTwips,
mTopContBorderWidth);
aBorder.right = BC_BORDER_LEFT_HALF_COORD(aPixelsToTwips,
mRightContBorderWidth);
aBorder.bottom = BC_BORDER_TOP_HALF_COORD(aPixelsToTwips,
mBottomContBorderWidth);
return BC_BORDER_RIGHT_HALF_COORD(aPixelsToTwips, mRightContBorderWidth);
}
#endif

View File

@ -391,8 +391,6 @@ nsTableColGroupFrame::Paint(nsIPresContext* aPresContext,
return NS_OK;
}
// Standards mode background painting removed. See bug 4510
PaintChildren(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer);
return NS_OK;
}
@ -646,6 +644,36 @@ void nsTableColGroupFrame::DeleteColFrame(nsIPresContext* aPresContext, nsTableC
mFrames.DestroyFrame(aPresContext, aColFrame);
}
void nsTableColGroupFrame::SetContinuousBCBorderWidth(PRUint8 aForSide,
BCPixelSize aPixelValue)
{
switch (aForSide) {
case NS_SIDE_TOP:
mTopContBorderWidth = aPixelValue;
return;
case NS_SIDE_BOTTOM:
mBottomContBorderWidth = aPixelValue;
return;
default:
NS_ERROR("invalid side arg");
}
}
void nsTableColGroupFrame::GetContinuousBCBorderWidth(float aPixelsToTwips,
nsMargin& aBorder)
{
nsTableFrame* table;
nsTableFrame::GetTableFrame(this, table);
nsTableColFrame* col = table->GetColFrame(mStartColIndex + mColCount - 1);
col->GetContinuousBCBorderWidth(aPixelsToTwips, aBorder);
aBorder.top = BC_BORDER_BOTTOM_HALF_COORD(aPixelsToTwips,
mTopContBorderWidth);
aBorder.bottom = BC_BORDER_TOP_HALF_COORD(aPixelsToTwips,
mBottomContBorderWidth);
return;
}
/* ----- global methods ----- */
nsresult

View File

@ -40,9 +40,9 @@
#include "nscore.h"
#include "nsHTMLContainerFrame.h"
#include "nsTableColFrame.h"
#include "nsTablePainter.h"
class nsTableColFrame;
class nsTableFrame;
enum nsTableColGroupType {
eColGroupContent = 0, // there is real col group content associated
@ -183,6 +183,21 @@ public:
static void ResetColIndices(nsIFrame* aFirstColGroup,
PRInt32 aFirstColIndex,
nsIFrame* aStartColFrame = nsnull);
/**
* Gets inner border widths before collapsing with cell borders
* Caller must get left border from previous column
* GetContinuousBCBorderWidth will not overwrite aBorder.left
* see nsTablePainter about continuous borders
*/
void GetContinuousBCBorderWidth(float aPixelsToTwips,
nsMargin& aBorder);
/**
* Set full border widths before collapsing with cell borders
* @param aForSide - side to set; only accepts top and bottom
*/
void SetContinuousBCBorderWidth(PRUint8 aForSide,
BCPixelSize aPixelValue);
protected:
nsTableColGroupFrame();
@ -221,6 +236,10 @@ protected:
PRInt32 mColCount;
// the starting column index this col group represents. Must be >= 0.
PRInt32 mStartColIndex;
// border width in pixels
BCPixelSize mTopContBorderWidth;
BCPixelSize mBottomContBorderWidth;
};
inline nsTableColGroupFrame::nsTableColGroupFrame()

View File

@ -50,6 +50,7 @@
#include "nsTableRowFrame.h"
#include "nsTableRowGroupFrame.h"
#include "nsTableOuterFrame.h"
#include "nsTablePainter.h"
#include "nsHTMLValue.h"
#include "BasicTableLayoutStrategy.h"
@ -126,18 +127,21 @@ struct nsTableReflowState {
nsTableFrame* table = (nsTableFrame*)aTableFrame.GetFirstInFlow();
nsMargin borderPadding = table->GetChildAreaOffset(&reflowState);
nscoord cellSpacingX = table->GetCellSpacingX();
x = borderPadding.left;
y = borderPadding.top;
x = borderPadding.left + cellSpacingX;
y = borderPadding.top; //cellspacing added during reflow
availSize.width = aAvailWidth;
if (NS_UNCONSTRAINEDSIZE != availSize.width) {
availSize.width -= borderPadding.left + borderPadding.right;
availSize.width -= borderPadding.left + borderPadding.right
+ (2 * cellSpacingX);
}
availSize.height = aAvailHeight;
if (NS_UNCONSTRAINEDSIZE != availSize.height) {
availSize.height -= borderPadding.top + borderPadding.bottom + (2 * table->GetCellSpacingY());
availSize.height -= borderPadding.top + borderPadding.bottom
+ (2 * table->GetCellSpacingY());
}
footerFrame = nsnull;
@ -288,7 +292,7 @@ nsTableFrame::~nsTableFrame()
if (nsnull!=mCellMap) {
delete mCellMap;
mCellMap = nsnull;
}
}
if (nsnull!=mTableLayoutStrategy) {
delete mTableLayoutStrategy;
@ -1230,7 +1234,7 @@ void nsTableFrame::AppendRowGroups(nsIPresContext& aPresContext,
nsTableRowGroupFrame*
nsTableFrame::GetRowGroupFrame(nsIFrame* aFrame,
nsIAtom* aFrameTypeIn) const
nsIAtom* aFrameTypeIn)
{
nsIFrame* rgFrame = nsnull;
nsIAtom* frameType = aFrameTypeIn;
@ -1386,43 +1390,54 @@ nsTableFrame::Paint(nsIPresContext* aPresContext,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags)
{
PRBool visibleBCBorders = PR_FALSE;
if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) {
TableBackgroundPainter painter(this, TableBackgroundPainter::eOrigin_Table,
aPresContext, aRenderingContext, aDirtyRect);
nsresult rv;
if (eCompatibility_NavQuirks == aPresContext->CompatibilityMode()) {
nsMargin deflate(0,0,0,0);
if (IsBorderCollapse()) {
GET_PIXELS_TO_TWIPS(aPresContext, p2t);
BCPropertyData* propData =
(BCPropertyData*)nsTableFrame::GetProperty(aPresContext,
(nsIFrame*)this,
nsLayoutAtoms::tableBCProperty,
PR_FALSE);
if (propData) {
deflate.top = BC_BORDER_TOP_HALF_COORD(p2t, propData->mTopBorderWidth);
deflate.right = BC_BORDER_RIGHT_HALF_COORD(p2t, propData->mRightBorderWidth);
deflate.bottom = BC_BORDER_BOTTOM_HALF_COORD(p2t, propData->mBottomBorderWidth);
deflate.left = BC_BORDER_LEFT_HALF_COORD(p2t, propData->mLeftBorderWidth);
}
}
rv = painter.QuirksPaintTable(this, deflate);
if (NS_FAILED(rv)) return rv;
}
else {
rv = painter.PaintTable(this);
if (NS_FAILED(rv)) return rv;
}
if (GetStyleVisibility()->IsVisible()) {
const nsStyleBorder* border = GetStyleBorder();
const nsStylePadding* padding = GetStylePadding();
nsRect rect(0, 0, mRect.width, mRect.height);
nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, this,
aDirtyRect, rect, *border, *padding,
PR_TRUE);
// paint the border here only for separate borders
if (!IsBorderCollapse()) {
PRIntn skipSides = GetSkipSides();
nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this,
aDirtyRect, rect, *border, mStyleContext, skipSides);
aDirtyRect, rect, *border, mStyleContext,
skipSides);
}
else {
visibleBCBorders = PR_TRUE;
PaintBCBorders(aPresContext, aRenderingContext, aDirtyRect);
}
}
aFlags |= NS_PAINT_FLAG_TABLE_BG_PAINT;
aFlags &= ~NS_PAINT_FLAG_TABLE_CELL_BG_PASS;
}
// for collapsed borders paint the backgrounds of cells, but not their contents (that happens below)
PRUint32 flags = aFlags;
if (visibleBCBorders) {
flags &= ~BORDER_COLLAPSE_BACKGROUNDS; // set bit to 0
}
PaintChildren(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer, flags);
if (visibleBCBorders) {
// for collapsed borders, paint the borders and then the backgrounds of cell
// contents but not the backgrounds of the cells
PaintBCBorders(aPresContext, aRenderingContext, aDirtyRect);
flags |= BORDER_COLLAPSE_BACKGROUNDS; // set bit to 1
PaintChildren(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer, flags);
}
PaintChildren(aPresContext, aRenderingContext, aDirtyRect,
aWhichLayer, aFlags);
#ifdef DEBUG
// for debug...
@ -1583,16 +1598,19 @@ nsTableFrame::AdjustSiblingsAfterReflow(nsIPresContext* aPresContext,
return NS_OK;
}
void
void
nsTableFrame::SetColumnDimensions(nscoord aHeight,
const nsMargin& aBorderPadding)
{
nscoord colHeight = aHeight -= aBorderPadding.top + aBorderPadding.bottom;
nscoord cellSpacingX = GetCellSpacingX();
nscoord cellSpacingY = GetCellSpacingY();
nscoord colHeight = aHeight -= aBorderPadding.top + aBorderPadding.bottom +
2* cellSpacingY;
nsIFrame* colGroupFrame = mColGroups.FirstChild();
PRInt32 colX = 0;
nsPoint colGroupOrigin(aBorderPadding.left + cellSpacingX, aBorderPadding.top);
nsPoint colGroupOrigin(aBorderPadding.left + cellSpacingX,
aBorderPadding.top + cellSpacingY);
PRInt32 numCols = GetColCount();
while (nsnull != colGroupFrame) {
nscoord colGroupWidth = 0;
@ -1606,19 +1624,19 @@ nsTableFrame::SetColumnDimensions(nscoord aHeight,
nsRect colRect(colOrigin.x, colOrigin.y, colWidth, colHeight);
colFrame->SetRect(colRect);
colOrigin.x += colWidth + cellSpacingX;
colGroupWidth += colWidth;
if (numCols - 1 != colX) {
colGroupWidth += cellSpacingX;
}
colGroupWidth += colWidth + cellSpacingX;
colX++;
}
colFrame = colFrame->GetNextSibling();
}
if (colGroupWidth) {
colGroupWidth -= cellSpacingX;
}
nsRect colGroupRect(colGroupOrigin.x, colGroupOrigin.y, colGroupWidth, colHeight);
colGroupFrame->SetRect(colGroupRect);
colGroupFrame = colGroupFrame->GetNextSibling();
colGroupOrigin.x += colGroupWidth;
colGroupOrigin.x += colGroupWidth + cellSpacingX;
}
}
@ -2881,7 +2899,7 @@ nsTableFrame::RecoverState(nsTableReflowState& aReflowState,
if ((NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP == display->mDisplay) &&
!aReflowState.footerFrame) {
aReflowState.footerFrame = childFrame;
}
}
else {
if ((NS_STYLE_DISPLAY_TABLE_ROW_GROUP == display->mDisplay) &&
!aReflowState.firstBodySection) {
@ -3647,7 +3665,7 @@ nsTableFrame::DistributeHeightToRows(const nsHTMLReflowState& aReflowState,
}
yOriginRow += rowRect.height + cellSpacingY;
yEndRG += rowRect.height + cellSpacingY;
}
}
rowFrame = rowFrame->GetNextRow();
}
if (amountUsed > 0) {
@ -5658,7 +5676,7 @@ nsTableFrame::CalcBCBorders(nsIPresContext& aPresContext)
BCCellBorder lastTopBorder, lastBottomBorder;
// horizontal borders indexed in x-direction (cols)
BCCellBorders lastBottomBorders(damageArea.width + 1, damageArea.x); if (!lastBottomBorders.borders) ABORT0();
PRBool startSeg;
PRBool startSeg, gotRowBorder;
BCMapCellInfo info, ajaInfo;
BCBorderOwner owner, ajaOwner;
@ -5680,6 +5698,7 @@ nsTableFrame::CalcBCBorders(nsIPresContext& aPresContext)
PRBool bottomRowSpan = PR_FALSE;
// see if lastTopBorder, lastBottomBorder need to be reset
if (iter.IsNewRow()) {
gotRowBorder = PR_FALSE;
lastTopBorder.Reset(info.rowIndex, info.rowSpan);
lastBottomBorder.Reset(cellEndRowIndex + 1, info.rowSpan);
}
@ -5722,7 +5741,7 @@ nsTableFrame::CalcBCBorders(nsIPresContext& aPresContext)
// update lastTopBorder and see if a new segment starts
startSeg = SetHorBorder(ownerBStyle, ownerWidth, ownerColor, tlCorner, lastTopBorder);
// store the border segment in the cell map
tableCellMap->SetBCBorderEdge(NS_SIDE_TOP, *info.cellMap, 0, 0, colX,
tableCellMap->SetBCBorderEdge(NS_SIDE_TOP, *info.cellMap, 0, 0, colX,
1, owner, ownerWidth, startSeg);
// update the affected borders of the cell, row, and table
DivideBCBorderSize(ownerWidth, smallHalf, largeHalf);
@ -5733,6 +5752,44 @@ nsTableFrame::CalcBCBorders(nsIPresContext& aPresContext)
info.topRow->SetTopBCBorderWidth(PR_MAX(smallHalf, info.topRow->GetTopBCBorderWidth()));
}
propData->mTopBorderWidth = LimitBorderWidth(PR_MAX(propData->mTopBorderWidth, (PRUint8)ownerWidth));
//calculate column continuous borders
//we only need to do this once, so we'll do it only on the first row
CalcDominantBorder(this, cgFrame, colFrame, info.rg, info.topRow,
nsnull, PR_TRUE, NS_SIDE_TOP, PR_FALSE, t2p,
owner, ownerBStyle, ownerWidth, ownerColor);
((nsTableColFrame*)colFrame)->SetContinuousBCBorderWidth(NS_SIDE_TOP,
ownerWidth);
if (numCols == cellEndColIndex + 1) {
CalcDominantBorder(this, cgFrame, colFrame, nsnull, nsnull,
nsnull, PR_TRUE, NS_SIDE_RIGHT, PR_FALSE, t2p,
owner, ownerBStyle, ownerWidth, ownerColor);
}
else {
CalcDominantBorder(nsnull, cgFrame, colFrame, nsnull, nsnull,
nsnull, PR_FALSE, NS_SIDE_RIGHT, PR_FALSE, t2p,
owner, ownerBStyle, ownerWidth, ownerColor);
}
((nsTableColFrame*)colFrame)->SetContinuousBCBorderWidth(NS_SIDE_RIGHT,
ownerWidth);
}
//calculate continuous top first row & rowgroup border: special case
//because it must include the table in the collapse
CalcDominantBorder(this, nsnull, nsnull, info.rg, info.topRow,
nsnull, PR_TRUE, NS_SIDE_TOP, PR_FALSE, t2p,
owner, ownerBStyle, ownerWidth, ownerColor);
info.topRow->SetContinuousBCBorderWidth(NS_SIDE_TOP, ownerWidth);
if (info.cgRight) {
//calculate continuous top colgroup border once per colgroup
CalcDominantBorder(this, info.cg, nsnull, info.rg, info.topRow,
nsnull, PR_TRUE, NS_SIDE_TOP, PR_FALSE, t2p,
owner, ownerBStyle, ownerWidth, ownerColor);
info.cg->SetContinuousBCBorderWidth(NS_SIDE_TOP, ownerWidth);
}
if (0 == info.colIndex) {
CalcDominantBorder(this, info.cg, info.leftCol, nsnull, nsnull,
nsnull, PR_TRUE, NS_SIDE_LEFT, PR_FALSE, t2p,
owner, ownerBStyle, ownerWidth, ownerColor);
mBits.mLeftContBCBorder = ownerWidth;
}
}
else {
@ -5760,10 +5817,10 @@ nsTableFrame::CalcBCBorders(nsIPresContext& aPresContext)
nsTableRowFrame* rowFrame = nsnull;
for (PRInt32 rowX = info.rowIndex; rowX <= cellEndRowIndex; rowX++) {
rowFrame = (rowX == info.rowIndex) ? info.topRow : rowFrame->GetNextRow();
CalcDominantBorder(this, info.cg, info.leftCol, info.rg, rowFrame, info.cell, PR_TRUE, NS_SIDE_LEFT,
CalcDominantBorder(this, info.cg, info.leftCol, info.rg, rowFrame, info.cell, PR_TRUE, NS_SIDE_LEFT,
PR_FALSE, t2p, owner, ownerBStyle, ownerWidth, ownerColor);
BCCornerInfo& tlCorner = (0 == rowX) ? topCorners[0] : bottomCorners[0]; // top left
tlCorner.Update(NS_SIDE_BOTTOM, owner, ownerBStyle, ownerWidth, ownerColor);
tlCorner.Update(NS_SIDE_BOTTOM, owner, ownerBStyle, ownerWidth, ownerColor);
tableCellMap->SetBCBorderCorner(eTopLeft, *info.cellMap, iter.mRowGroupStart, rowX,
0, tlCorner.ownerSide, tlCorner.subWidth, tlCorner.bevel);
bottomCorners[0].Set(NS_SIDE_TOP, owner, ownerBStyle, ownerWidth, ownerColor); // bottom left
@ -5781,6 +5838,17 @@ nsTableFrame::CalcBCBorders(nsIPresContext& aPresContext)
info.leftCol->SetLeftBorderWidth(PR_MAX(smallHalf, info.leftCol->GetLeftBorderWidth()));
}
propData->mLeftBorderWidth = LimitBorderWidth(PR_MAX(propData->mLeftBorderWidth, ownerWidth));
//get row continuous borders
CalcDominantBorder(this, info.cg, info.leftCol, info.rg, rowFrame, nsnull, PR_TRUE, NS_SIDE_LEFT,
PR_FALSE, t2p, owner, ownerBStyle, ownerWidth, ownerColor);
rowFrame->SetContinuousBCBorderWidth(NS_SIDE_LEFT, ownerWidth);
}
//get row group continuous borders
if (info.rgBottom) { //once per row group, so check for bottom
CalcDominantBorder(this, info.cg, info.leftCol, info.rg, nsnull,
nsnull, PR_TRUE, NS_SIDE_LEFT, PR_FALSE, t2p,
owner, ownerBStyle, ownerWidth, ownerColor);
info.rg->SetContinuousBCBorderWidth(NS_SIDE_LEFT, ownerWidth);
}
}
@ -5818,6 +5886,18 @@ nsTableFrame::CalcBCBorders(nsIPresContext& aPresContext)
info.rightCol->SetRightBorderWidth(PR_MAX(largeHalf, info.rightCol->GetRightBorderWidth()));
}
propData->mRightBorderWidth = LimitBorderWidth(PR_MAX(propData->mRightBorderWidth, ownerWidth));
//get row continuous borders
CalcDominantBorder(this, info.cg, info.rightCol, info.rg, rowFrame,
nsnull, PR_TRUE, NS_SIDE_RIGHT, PR_TRUE, t2p,
owner, ownerBStyle, ownerWidth, ownerColor);
rowFrame->SetContinuousBCBorderWidth(NS_SIDE_RIGHT, ownerWidth);
}
//get row group continuous borders
if (info.rgBottom) { //once per rg, so check for bottom
CalcDominantBorder(this, info.cg, info.rightCol, info.rg, nsnull,
nsnull, PR_TRUE, NS_SIDE_RIGHT, PR_TRUE, t2p,
owner, ownerBStyle, ownerWidth, ownerColor);
info.rg->SetContinuousBCBorderWidth(NS_SIDE_RIGHT, ownerWidth);
}
}
else {
@ -5944,17 +6024,32 @@ nsTableFrame::CalcBCBorders(nsIPresContext& aPresContext)
lastBottomBorder.index = cellEndRowIndex + 1;
lastBottomBorder.span = info.rowSpan;
lastBottomBorders[colX] = lastBottomBorder;
//get col continuous border
CalcDominantBorder(this, cgFrame, colFrame, info.rg, info.bottomRow,
nsnull, PR_TRUE, NS_SIDE_BOTTOM, PR_TRUE, t2p,
owner, ownerBStyle, ownerWidth, ownerColor);
((nsTableColFrame*)colFrame)->SetContinuousBCBorderWidth(NS_SIDE_BOTTOM,
ownerWidth);
}
//get row group/col group continuous border
CalcDominantBorder(this, nsnull, nsnull, info.rg, info.bottomRow,
nsnull, PR_TRUE, NS_SIDE_BOTTOM, PR_TRUE, t2p,
owner, ownerBStyle, ownerWidth, ownerColor);
info.rg->SetContinuousBCBorderWidth(NS_SIDE_BOTTOM, ownerWidth);
CalcDominantBorder(this, info.cg, nsnull, info.rg, info.bottomRow,
nsnull, PR_TRUE, NS_SIDE_BOTTOM, PR_TRUE, t2p,
owner, ownerBStyle, ownerWidth, ownerColor);
info.cg->SetContinuousBCBorderWidth(NS_SIDE_BOTTOM, ownerWidth);
}
else {
PRInt32 segLength = 0;
for (PRInt32 colX = info.colIndex; colX <= cellEndColIndex; colX += segLength) {
iter.PeekBottom(info, colX, ajaInfo);
const nsIFrame* rg = (info.rgBottom) ? info.rg : nsnull;
CalcDominantBorder(nsnull, nsnull, nsnull, rg, info.bottomRow, info.cell, PR_FALSE, NS_SIDE_BOTTOM,
CalcDominantBorder(nsnull, nsnull, nsnull, rg, info.bottomRow, info.cell, PR_FALSE, NS_SIDE_BOTTOM,
PR_TRUE, t2p, owner, ownerBStyle, ownerWidth, ownerColor);
rg = (ajaInfo.rgTop) ? ajaInfo.rg : nsnull;
CalcDominantBorder(nsnull, nsnull, nsnull, rg, ajaInfo.topRow, ajaInfo.cell, PR_FALSE, NS_SIDE_TOP,
CalcDominantBorder(nsnull, nsnull, nsnull, rg, ajaInfo.topRow, ajaInfo.cell, PR_FALSE, NS_SIDE_TOP,
PR_FALSE, t2p, ajaOwner, ajaBStyle, ajaWidth, ajaColor);
CalcDominantBorder(PR_FALSE, owner, ownerBStyle, ownerWidth, ownerColor, ajaOwner, ajaBStyle, ajaWidth,
ajaColor, owner, ownerBStyle, ownerWidth, ownerColor, PR_TRUE);
@ -5972,23 +6067,23 @@ nsTableFrame::CalcBCBorders(nsIPresContext& aPresContext)
}
else if (prevRowIndex < cellEndRowIndex + 1) { // spans below the cell to the left
topCorners[colX] = blCorner;
blCorner.Set(NS_SIDE_RIGHT, owner, ownerBStyle, ownerWidth, ownerColor);
blCorner.Set(NS_SIDE_RIGHT, owner, ownerBStyle, ownerWidth, ownerColor);
update = PR_FALSE;
}
}
if (update) {
blCorner.Update(NS_SIDE_RIGHT, owner, ownerBStyle, ownerWidth, ownerColor);
blCorner.Update(NS_SIDE_RIGHT, owner, ownerBStyle, ownerWidth, ownerColor);
}
if (BOTTOM_DAMAGED(cellEndRowIndex) && LEFT_DAMAGED(colX)) {
if (hitsSpanBelow) {
tableCellMap->SetBCBorderCorner(eBottomLeft, *info.cellMap, iter.mRowGroupStart, cellEndRowIndex, colX,
tableCellMap->SetBCBorderCorner(eBottomLeft, *info.cellMap, iter.mRowGroupStart, cellEndRowIndex, colX,
blCorner.ownerSide, blCorner.subWidth, blCorner.bevel);
}
// store any corners this cell spans together with the aja cell
for (PRInt32 cX = colX + 1; cX < colX + segLength; cX++) {
BCCornerInfo& corner = bottomCorners[cX];
BCCornerInfo& corner = bottomCorners[cX];
corner.Set(NS_SIDE_RIGHT, owner, ownerBStyle, ownerWidth, ownerColor);
tableCellMap->SetBCBorderCorner(eBottomLeft, *info.cellMap, iter.mRowGroupStart, cellEndRowIndex,
tableCellMap->SetBCBorderCorner(eBottomLeft, *info.cellMap, iter.mRowGroupStart, cellEndRowIndex,
cX, corner.ownerSide, corner.subWidth, PR_FALSE);
}
}
@ -6008,7 +6103,7 @@ nsTableFrame::CalcBCBorders(nsIPresContext& aPresContext)
// store the border segment the cell map and update cellBorders
if (BOTTOM_DAMAGED(cellEndRowIndex) && LEFT_DAMAGED(colX) && RIGHT_DAMAGED(colX)) {
tableCellMap->SetBCBorderEdge(NS_SIDE_BOTTOM, *info.cellMap, iter.mRowGroupStart, cellEndRowIndex,
tableCellMap->SetBCBorderEdge(NS_SIDE_BOTTOM, *info.cellMap, iter.mRowGroupStart, cellEndRowIndex,
colX, segLength, owner, ownerWidth, startSeg);
// update the borders of the affected cells and rows
DivideBCBorderSize(ownerWidth, smallHalf, largeHalf);
@ -6027,16 +6122,39 @@ nsTableFrame::CalcBCBorders(nsIPresContext& aPresContext)
}
// update bottom right corner
BCCornerInfo& brCorner = bottomCorners[colX + segLength];
brCorner.Update(NS_SIDE_LEFT, owner, ownerBStyle, ownerWidth, ownerColor);
brCorner.Update(NS_SIDE_LEFT, owner, ownerBStyle, ownerWidth, ownerColor);
}
if (!gotRowBorder && 1 == info.rowSpan) {
//get continuous row/row group border
//we need to check the row group's bottom border if this is
//the last row in the row group, but only a cell with rowspan=1
//will know whether *this* row is at the bottom
const nsIFrame* rg = (info.rgBottom) ? info.rg : nsnull;
CalcDominantBorder(nsnull, nsnull, nsnull, rg, info.bottomRow,
nsnull, PR_FALSE, NS_SIDE_BOTTOM, PR_TRUE, t2p,
owner, ownerBStyle, ownerWidth, ownerColor);
rg = (ajaInfo.rgTop) ? ajaInfo.rg : nsnull;
CalcDominantBorder(nsnull, nsnull, nsnull, rg, ajaInfo.topRow,
nsnull, PR_FALSE, NS_SIDE_TOP, PR_FALSE, t2p,
ajaOwner, ajaBStyle, ajaWidth, ajaColor);
CalcDominantBorder(PR_FALSE, owner, ownerBStyle, ownerWidth,
ownerColor, ajaOwner, ajaBStyle, ajaWidth,
ajaColor, owner, ownerBStyle, ownerWidth,
ownerColor, PR_TRUE);
ajaInfo.topRow->SetContinuousBCBorderWidth(NS_SIDE_TOP, ownerWidth);
if (info.rgBottom) {
info.rg->SetContinuousBCBorderWidth(NS_SIDE_BOTTOM, ownerWidth);
}
gotRowBorder = PR_TRUE;
}
}
// see if the cell to the right had a rowspan and its lower left border needs be joined with this one's bottom
if ((numCols != cellEndColIndex + 1) && // there is a cell to the right
if ((numCols != cellEndColIndex + 1) && // there is a cell to the right
(lastBottomBorders[cellEndColIndex + 1].span > 1)) { // cell to right was a rowspan
BCCornerInfo& corner = bottomCorners[cellEndColIndex + 1];
if ((NS_SIDE_TOP != corner.ownerSide) && (NS_SIDE_BOTTOM != corner.ownerSide)) { // not a vertical owner
BCCellBorder& thisBorder = lastBottomBorder;
BCCellBorder& thisBorder = lastBottomBorder;
BCCellBorder& nextBorder = lastBottomBorders[info.colIndex + 1];
if ((thisBorder.color == nextBorder.color) && (thisBorder.width == nextBorder.width) &&
(thisBorder.style == nextBorder.style)) {
@ -7206,7 +7324,7 @@ PRBool nsTableFrame::RowHasSpanningCells(PRInt32 aRowIndex)
nsTableCellMap* cellMap = GetCellMap();
NS_PRECONDITION (cellMap, "bad call, cellMap not yet allocated.");
if (cellMap) {
result = cellMap->RowHasSpanningCells(aRowIndex);
result = cellMap->RowHasSpanningCells(aRowIndex);
}
return result;
}
@ -7217,7 +7335,7 @@ PRBool nsTableFrame::RowIsSpannedInto(PRInt32 aRowIndex)
nsTableCellMap* cellMap = GetCellMap();
NS_PRECONDITION (cellMap, "bad call, cellMap not yet allocated.");
if (cellMap) {
result = cellMap->RowIsSpannedInto(aRowIndex);
result = cellMap->RowIsSpannedInto(aRowIndex);
}
return result;
}

View File

@ -62,10 +62,6 @@ struct nsStylePosition;
enum nsPixelRound {eAlwaysRoundUp=0, eAlwaysRoundDown, eRoundUpIfHalfOrMore};
// flags for Paint, PaintChild, PaintChildren are currently only used by tables.
// use low order bit of flags to distinguish between pass1(0) and pass2(1) border collapse backgrounds
#define BORDER_COLLAPSE_BACKGROUNDS 0x00000001
#ifdef DEBUG_TABLE_REFLOW_TIMING
#ifdef WIN32
#include <windows.h>
@ -331,6 +327,14 @@ public:
// the surrounding margin space
nsMargin GetBCMargin(nsIPresContext* aPresContext) const;
/** Get width of table + colgroup + col collapse: elements that
* continue along the length of the whole left side.
* see nsTablePainter about continuous borders
* @param aPixelsToTwips - conversion factor
* @param aGetInner - get only inner half of border width
*/
nscoord GetContinuousLeftBCBorderWidth(float aPixelsToTwips) const;
void SetBCDamageArea(nsIPresContext& aPresContext,
const nsRect& aValue);
@ -643,7 +647,7 @@ protected:
nsTableReflowState& aReflowState,
nsReflowStatus& aStatus);
/** process a style chnaged notification.
/** process a style changed notification.
* @see nsIFrameReflow::Reflow
* TODO: needs to be optimized for which attribute was actually changed.
*/
@ -797,11 +801,10 @@ public:
nsVoidArray& GetColCache();
/**
* Return aFrame's child if aFrame is an nsScrollFrame, otherwise return aFrame
*/
nsTableRowGroupFrame* GetRowGroupFrame(nsIFrame* aFrame,
nsIAtom* aFrameTypeIn = nsnull) const;
/** Return aFrame's child if aFrame is an nsScrollFrame, otherwise return aFrame
*/
static nsTableRowGroupFrame* GetRowGroupFrame(nsIFrame* aFrame,
nsIAtom* aFrameTypeIn = nsnull);
protected:
@ -908,20 +911,21 @@ protected:
// DATA MEMBERS
struct TableBits {
unsigned mHadInitialReflow:1; // has intial reflow happened
unsigned mHaveReflowedColGroups:1; // have the col groups gotten their initial reflow
unsigned mNeedStrategyBalance:1; // does the strategy needs to balance the table
unsigned mNeedStrategyInit:1; // does the strategy needs to be initialized and then balance the table
unsigned mHasPctCol:1; // does any cell or col have a pct width
unsigned mCellSpansPctCol:1; // does any cell span a col with a pct width (or containing a cell with a pct width)
unsigned mDidResizeReflow:1; // did a resize reflow happen (indicating pass 2)
unsigned mIsBorderCollapse:1; // border collapsing model vs. separate model
unsigned mRowInserted:1;
unsigned mNeedSpecialReflow:1;
unsigned mNeedToInitiateSpecialReflow:1;
unsigned mInitiatedSpecialReflow:1;
unsigned mNeedToCalcBCBorders:1;
unsigned : 19; // unused
PRUint32 mHadInitialReflow:1; // has intial reflow happened
PRUint32 mHaveReflowedColGroups:1; // have the col groups gotten their initial reflow
PRUint32 mNeedStrategyBalance:1; // does the strategy needs to balance the table
PRUint32 mNeedStrategyInit:1; // does the strategy needs to be initialized and then balance the table
PRUint32 mHasPctCol:1; // does any cell or col have a pct width
PRUint32 mCellSpansPctCol:1; // does any cell span a col with a pct width (or containing a cell with a pct width)
PRUint32 mDidResizeReflow:1; // did a resize reflow happen (indicating pass 2)
PRUint32 mIsBorderCollapse:1; // border collapsing model vs. separate model
PRUint32 mRowInserted:1;
PRUint32 mNeedSpecialReflow:1;
PRUint32 mNeedToInitiateSpecialReflow:1;
PRUint32 mInitiatedSpecialReflow:1;
PRUint32 mNeedToCalcBCBorders:1;
PRUint32 mLeftContBCBorder:8;
PRUint32 : 11; // unused
} mBits;
nsTableCellMap* mCellMap; // maintains the relationships between rows, cols, and cells
@ -1041,7 +1045,7 @@ inline void nsTableFrame::SetRowInserted(PRBool aValue)
inline nsFrameList& nsTableFrame::GetColGroups()
{
return mColGroups;
return NS_STATIC_CAST(nsTableFrame*, GetFirstInFlow())->mColGroups;
}
inline nsVoidArray& nsTableFrame::GetColCache()
@ -1084,6 +1088,12 @@ inline void nsTableFrame::SetNeedToCalcBCBorders(PRBool aValue)
mBits.mNeedToCalcBCBorders = (unsigned)aValue;
}
inline nscoord
nsTableFrame::GetContinuousLeftBCBorderWidth(float aPixelsToTwips) const
{
return BC_BORDER_RIGHT_HALF_COORD(aPixelsToTwips, mBits.mLeftContBCBorder);
}
enum nsTableIteration {
eTableLTR = 0,
eTableRTL = 1,

View File

@ -0,0 +1,685 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is TableBackgroundPainter implementation.
*
* The Initial Developer of the Original Code is
* Elika J. Etemad ("fantasai") <fantasai@inkedblade.net>.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsTableFrame.h"
#include "nsTableRowGroupFrame.h"
#include "nsTableRowFrame.h"
#include "nsTableColGroupFrame.h"
#include "nsTableColFrame.h"
#include "nsTableCellFrame.h"
#include "nsTablePainter.h"
#include "nsCSSRendering.h"
/* ~*~ Standards Mode Painting ~*~
Background painting in Standards mode follows CSS2.1:17.5.1
That section does not, however, describe the effect of
borders on background image positioning. What we do is:
- in separate borders, the borders are passed in so that
their width figures in image positioning, even for rows/cols, which
don't have visible borders. This is done to allow authors
to position row backgrounds by, for example, aligning the
top left corner with the top left padding corner of the
top left table cell in the row in cases where all cells
have consistent border widths. If we didn't honor these
invisible borders, there would be no way to align
backgrounds with the padding edges, and designs would be
lost underneath the border.
- in collapsing borders, because the borders collapse, we
use the -continuous border- width to synthesize a border
style and pass that in instead of using the element's
assigned style directly.
The continuous border on a given edge of an element is
the collapse of all borders guaranteed to be continuous
along that edge. Cell borders are ignored (because, for
example, setting a thick border on the leftmost cell
should not shift the row background over; this way a
striped background set on <tr> will line up across rows
even if the cells are assigned arbitrary border widths.
For example, the continous border on the top edge of a
row group is the collapse of any row group, row, and
table borders involved. (The first row group's top would
be [table-top + row group top + first row top]. It's bottom
would be [row group bottom + last row bottom + next row
top + next row group top].)
The top edge of a column group likewise includes the
table top, row group top, and first row top borders. However,
it *also* includes its own top border, since that is guaranteed
to be continuous. It does not include column borders because
those are not guaranteed to be continuous: there may be two
columns with different borders in a single column group.
An alternative would be to define the continuous border as
[table? + row group + row] for horizontal
[table? + col group + col] for vertical
This makes it easier to line up backgrounds across elements
despite varying border widths, but it does not give much
flexibility in aligning /to/ those border widths.
*/
/* ~*~ Quirks Table Background Painting ~*~
Quirks inherits all backgrounds below the table level into the
cells; we don't paint intermediate backgrounds.
*/
/* ~*~ TableBackgroundPainter ~*~
The TableBackgroundPainter is created and destroyed in one painting call.
Its principal function is PaintTable, which paints all table element
backgrounds. The initial code in that method sets up an array of column
data that caches the background styles and the border sizes for the
columns and colgroups in TableBackgroundData structs in mCols. Data for
BC borders are calculated and stashed in a synthesized border style struct
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 exception to this pattern is when a table element has a view.
Elements with views are <dfn>passed through</dfn>, which means their data
(and their descendants' data) are not cached. The full loop is still
executed, however, so that underlying layers can get painted at the cell
level.
The TableBackgroundPainter is then destroyed.
Elements with views set up their own painter to finish the painting
process, since they were skipped. They call the appropriate sub-part
of the loop (e.g. PaintRow) which will paint the frame and descendants.
*/
TableBackgroundPainter::TableBackgroundData::TableBackgroundData()
: mFrame(nsnull),
mBackground(nsnull),
mBorder(nsnull),
mSynthBorder(nsnull)
{
MOZ_COUNT_CTOR(TableBackgroundData);
}
TableBackgroundPainter::TableBackgroundData::~TableBackgroundData()
{
NS_ASSERTION(!mSynthBorder, "must call Destroy before dtor");
MOZ_COUNT_DTOR(TableBackgroundData);
}
void
TableBackgroundPainter::TableBackgroundData::Destroy(nsIPresContext* aPresContext)
{
NS_PRECONDITION(aPresContext, "null prescontext");
if (mSynthBorder) {
mSynthBorder->Destroy(aPresContext);
mSynthBorder = nsnull;
}
}
void
TableBackgroundPainter::TableBackgroundData::Clear()
{
mRect.Empty();
mFrame = nsnull;
mBorder = nsnull;
mBackground = nsnull;
}
void
TableBackgroundPainter::TableBackgroundData::SetFrame(nsIFrame* aFrame)
{
NS_PRECONDITION(aFrame, "null frame");
mFrame = aFrame;
mRect = aFrame->GetRect();
}
void
TableBackgroundPainter::TableBackgroundData::SetFull(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
nsIFrame* aFrame)
{
NS_PRECONDITION(aFrame, "null frame");
mFrame = aFrame;
mRect = aFrame->GetRect();
/* IsVisibleForPainting doesn't use aRenderingContext except in nsTextFrames,
so we're not going to bother translating.*/
PRBool isVisible;
nsresult rv = aFrame->IsVisibleForPainting(aPresContext, aRenderingContext,
PR_TRUE, &isVisible);
if (NS_SUCCEEDED(rv) && isVisible &&
aFrame->GetStyleVisibility()->IsVisible()) {
mBackground = aFrame->GetStyleBackground();
mBorder = aFrame->GetStyleBorder();
}
}
inline PRBool
TableBackgroundPainter::TableBackgroundData::ShouldSetBCBorder()
{
/* we only need accurate border data when positioning background images*/
return mBackground && !(mBackground->mBackgroundFlags & NS_STYLE_BG_IMAGE_NONE);
}
nsresult
TableBackgroundPainter::TableBackgroundData::SetBCBorder(nsMargin& aBorder,
TableBackgroundPainter* aPainter)
{
NS_PRECONDITION(aPainter, "null painter");
if (!mSynthBorder) {
mSynthBorder = new (aPainter->mPresContext)
nsStyleBorder(aPainter->mZeroBorder);
if (!mSynthBorder) return NS_ERROR_OUT_OF_MEMORY;
}
nsStyleCoord coord(aBorder.top);
mSynthBorder->mBorder.SetTop(coord);
coord.SetCoordValue(aBorder.right);
mSynthBorder->mBorder.SetRight(coord);
coord.SetCoordValue(aBorder.bottom);
mSynthBorder->mBorder.SetBottom(coord);
coord.SetCoordValue(aBorder.left);
mSynthBorder->mBorder.SetLeft(coord);
mSynthBorder->RecalcData();
mBorder = mSynthBorder;
return NS_OK;
}
TableBackgroundPainter::TableBackgroundPainter(nsTableFrame* aTableFrame,
Origin aOrigin,
nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect)
: mPresContext(aPresContext),
mRenderingContext(aRenderingContext),
mDirtyRect(aDirtyRect),
mOrigin(aOrigin),
mCols(nsnull),
mZeroBorder(aPresContext)
{
MOZ_COUNT_CTOR(TableBackgroundPainter);
mZeroBorder.SetBorderStyle(NS_SIDE_TOP, NS_STYLE_BORDER_STYLE_SOLID);
mZeroBorder.SetBorderStyle(NS_SIDE_RIGHT, NS_STYLE_BORDER_STYLE_SOLID);
mZeroBorder.SetBorderStyle(NS_SIDE_BOTTOM, NS_STYLE_BORDER_STYLE_SOLID);
mZeroBorder.SetBorderStyle(NS_SIDE_LEFT, NS_STYLE_BORDER_STYLE_SOLID);
nsStyleCoord coord(0);
mZeroBorder.mBorder.SetTop(coord);
mZeroBorder.mBorder.SetRight(coord);
mZeroBorder.mBorder.SetBottom(coord);
mZeroBorder.mBorder.SetLeft(coord);
mZeroBorder.RecalcData();
mZeroPadding.RecalcData();
mPresContext->GetScaledPixelsToTwips(&mP2t);
mIsBorderCollapse = aTableFrame->IsBorderCollapse();
#ifdef DEBUG
mCompatMode = mPresContext->CompatibilityMode();
#endif
mNumCols = aTableFrame->GetColCount();
}
TableBackgroundPainter::~TableBackgroundPainter()
{
if (mCols) {
TableBackgroundData* lastColGroup = nsnull;
for (PRUint32 i = 0; i < mNumCols; i++) {
if (mCols[i].mColGroup != lastColGroup) {
lastColGroup = mCols[i].mColGroup;
lastColGroup->Destroy(mPresContext);
delete lastColGroup;
}
mCols[i].mColGroup = nsnull;
mCols[i].mCol.Destroy(mPresContext);
}
delete [] mCols;
}
mRowGroup.Destroy(mPresContext);
mRow.Destroy(mPresContext);
MOZ_COUNT_DTOR(TableBackgroundPainter);
}
nsresult
TableBackgroundPainter::PaintTableFrame(nsTableFrame* aTableFrame,
nsTableRowGroupFrame* aFirstRowGroup,
nsTableRowGroupFrame* aLastRowGroup,
nsMargin* aDeflate)
{
NS_PRECONDITION(aTableFrame, "null frame");
TableBackgroundData tableData;
tableData.SetFull(mPresContext, mRenderingContext, aTableFrame);
tableData.mRect.MoveTo(0,0); //using table's coords
if (aDeflate) {
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(mP2t, tempBorder);
}
border.right = tempBorder.right;
aLastRowGroup->GetContinuousBCBorderWidth(mP2t, tempBorder);
border.bottom = tempBorder.bottom;
nsTableRowFrame* rowFrame = aFirstRowGroup->GetFirstRow();
if (rowFrame) {
rowFrame->GetContinuousBCBorderWidth(mP2t, tempBorder);
border.top = tempBorder.top;
}
border.left = aTableFrame->GetContinuousLeftBCBorderWidth(mP2t);
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,
*tableData.mBackground,
*tableData.mBorder,
mZeroPadding, PR_TRUE);
}
tableData.Destroy(mPresContext);
return NS_OK;
}
void
TableBackgroundPainter::TranslateContext(nscoord aDX,
nscoord aDY)
{
mRenderingContext.Translate(aDX, aDY);
mDirtyRect.MoveBy(-aDX, -aDY);
if (mCols) {
TableBackgroundData* lastColGroup = nsnull;
for (PRUint32 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");
mCols[i].mColGroup->mRect.MoveBy(-aDX, -aDY);
lastColGroup = mCols[i].mColGroup;
}
}
}
}
nsresult
TableBackgroundPainter::QuirksPaintTable(nsTableFrame* aTableFrame,
nsMargin& aDeflate)
{
NS_PRECONDITION(aTableFrame, "null table frame");
NS_PRECONDITION(eCompatibility_NavQuirks == mCompatMode,
"QuirksPaintTable called for non-Quirks");
nsVoidArray rowGroups;
PRUint32 numRowGroups;
aTableFrame->OrderRowGroups(rowGroups, numRowGroups);
if (numRowGroups < 1) { //degenerate case
PaintTableFrame(aTableFrame,nsnull, nsnull, &aDeflate);
/* No cells; nothing else to paint */
return NS_OK;
}
PaintTableFrame(aTableFrame,
aTableFrame->GetRowGroupFrame(NS_STATIC_CAST(nsIFrame*, rowGroups.ElementAt(0))),
aTableFrame->GetRowGroupFrame(NS_STATIC_CAST(nsIFrame*, rowGroups.ElementAt(numRowGroups - 1))),
&aDeflate);
if (mIsBorderCollapse) {
/* This is a simple pass, so we'll just keep with the table coord system. */
for (PRUint32 i = 0; i < numRowGroups; i++) {
nsTableRowGroupFrame* rg = aTableFrame->GetRowGroupFrame(NS_STATIC_CAST(nsIFrame*, rowGroups.ElementAt(i)));
nsRect rgRect = rg->GetRect();
if (rgRect.Intersects(mDirtyRect) && !rg->HasView()) {
for (nsTableRowFrame* row = rg->GetFirstRow(); row; row = row->GetNextRow()) {
nsRect rowRect = row->GetRect();
rowRect.MoveBy(rgRect.x, rgRect.y);
if (mDirtyRect.YMost() > rowRect.y && //Intersect won't handle rowspans
!row->HasView()) {
for (nsTableCellFrame* cell = row->GetFirstCell(); cell; cell = cell->GetNextCell()) {
mCellRect = cell->GetRect();
mCellRect.MoveBy(rowRect.x, rowRect.y);
if (mCellRect.Intersects(mDirtyRect) && !cell->HasView()) {
nsresult rv = PaintCell(cell, PR_FALSE);
if (NS_FAILED(rv)) return rv;
}
}
}
}
}
}
}
return NS_OK;
}
nsresult
TableBackgroundPainter::PaintTable(nsTableFrame* aTableFrame)
{
NS_PRECONDITION(aTableFrame, "null table frame");
NS_PRECONDITION(eCompatibility_NavQuirks != mCompatMode,
"must call QuirksPaintTable in Quirks mode, not PaintTable");
nsVoidArray rowGroups;
PRUint32 numRowGroups;
aTableFrame->OrderRowGroups(rowGroups, numRowGroups);
if (numRowGroups < 1) { //degenerate case
PaintTableFrame(aTableFrame,nsnull, nsnull, nsnull);
/* No cells; nothing else to paint */
return NS_OK;
}
PaintTableFrame(aTableFrame,
aTableFrame->GetRowGroupFrame(NS_STATIC_CAST(nsIFrame*, rowGroups.ElementAt(0))),
aTableFrame->GetRowGroupFrame(NS_STATIC_CAST(nsIFrame*, rowGroups.ElementAt(numRowGroups - 1))),
nsnull);
/*Set up column background/border data*/
if (mNumCols > 0) {
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 = nsnull;
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(mP2t);
for (nsTableColGroupFrame* cgFrame = NS_STATIC_CAST(nsTableColGroupFrame*, colGroupList.FirstChild());
cgFrame; cgFrame = NS_STATIC_CAST(nsTableColGroupFrame*, cgFrame->GetNextSibling())) {
if (cgFrame->GetColCount() < 1) {
//No columns, no cells, so no need for data
continue;
}
/*Create data struct for column group*/
cgData = new TableBackgroundData;
if (!cgData) return NS_ERROR_OUT_OF_MEMORY;
cgData->SetFull(mPresContext, mRenderingContext, cgFrame);
if (mIsBorderCollapse && cgData->ShouldSetBCBorder()) {
border.left = lastLeftBorder;
cgFrame->GetContinuousBCBorderWidth(mP2t, border);
nsresult rv = cgData->SetBCBorder(border, this);
if (NS_FAILED(rv)) {
cgData->Destroy(mPresContext);
delete cgData;
return rv;
}
}
/*Loop over columns in this colgroup*/
if (cgData->IsVisible()) {
for (nsTableColFrame* col = cgFrame->GetFirstColumn(); col;
col = NS_STATIC_CAST(nsTableColFrame*, col->GetNextSibling())) {
/*Create data struct for column*/
PRUint32 colIndex = col->GetColIndex();
mCols[colIndex].mCol.SetFull(mPresContext, mRenderingContext, col);
//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;
if (mIsBorderCollapse) {
border.left = lastLeftBorder;
lastLeftBorder = col->GetContinuousBCBorderWidth(mP2t, border);
if (mCols[colIndex].mCol.ShouldSetBCBorder()) {
nsresult rv = mCols[colIndex].mCol.SetBCBorder(border, this);
if (NS_FAILED(rv)) return rv;
}
mCols[colIndex].mCol.mBorder->GetBorder(border);
}
}
}
}
}
for (PRUint32 i = 0; i < numRowGroups; i++) {
nsTableRowGroupFrame* rg = nsTableFrame::GetRowGroupFrame(NS_STATIC_CAST(nsIFrame*, rowGroups.ElementAt(i)));
nsRect rgRect = rg->GetRect();
if (rgRect.Intersects(mDirtyRect)) {
nsresult rv = PaintRowGroup(rg, rg->HasView());
if (NS_FAILED(rv)) return rv;
}
}
return NS_OK;
}
nsresult
TableBackgroundPainter::PaintRowGroup(nsTableRowGroupFrame* aFrame,
PRBool aPassThrough)
{
NS_PRECONDITION(aFrame, "null frame");
NS_PRECONDITION(eCompatibility_NavQuirks != mCompatMode,
"must not call PaintRowGroup in Quirks mode");
nsTableRowFrame* firstRow = aFrame->GetFirstRow();
/* Load row group data */
if (!aPassThrough) {
mRowGroup.SetFull(mPresContext, mRenderingContext, aFrame);
if (mIsBorderCollapse && mRowGroup.ShouldSetBCBorder()) {
nsMargin border;
if (firstRow) {
//pick up first row's top border (= rg top border)
firstRow->GetContinuousBCBorderWidth(mP2t, border);
/* (row group doesn't store its top border) */
}
//overwrite sides+bottom borders with rg's own
aFrame->GetContinuousBCBorderWidth(mP2t, border);
nsresult res = mRowGroup.SetBCBorder(border, this);
if (!NS_SUCCEEDED(res)) {
return res;
}
}
aPassThrough = !mRowGroup.IsVisible();
}
else {
mRowGroup.SetFrame(aFrame);
}
/* translate everything into row group coord system*/
if (eOrigin_TableRowGroup != mOrigin) {
TranslateContext(mRowGroup.mRect.x, mRowGroup.mRect.y);
}
nsRect rgRect = mRowGroup.mRect;
mRowGroup.mRect.MoveTo(0, 0);
/* paint */
for (nsTableRowFrame* row = firstRow; row; row = row->GetNextRow()) {
nsRect rect = row->GetRect();
if (mDirtyRect.YMost() >= rect.y) { //Intersect wouldn't handle rowspans
nsresult rv = PaintRow(row, aPassThrough || row->HasView());
if (NS_FAILED(rv)) return rv;
}
}
/* translate back into table coord system */
if (eOrigin_TableRowGroup != mOrigin) {
TranslateContext(-rgRect.x, -rgRect.y);
}
/* unload rg data */
mRowGroup.Clear();
return NS_OK;
}
nsresult
TableBackgroundPainter::PaintRow(nsTableRowFrame* aFrame,
PRBool aPassThrough)
{
NS_PRECONDITION(aFrame, "null frame");
NS_PRECONDITION(eCompatibility_NavQuirks != mCompatMode,
"must not call PaintRow in Quirks mode");
/* Load row data */
if (!aPassThrough) {
mRow.SetFull(mPresContext, mRenderingContext, aFrame);
if (mIsBorderCollapse && mRow.ShouldSetBCBorder()) {
nsMargin border;
nsTableRowFrame* nextRow = aFrame->GetNextRow();
if (nextRow) { //outer top below us is inner bottom for us
border.bottom = nextRow->GetOuterTopContBCBorderWidth(mP2t);
}
else { //acquire rg's bottom border
nsTableRowGroupFrame* rowGroup = NS_STATIC_CAST(nsTableRowGroupFrame*, aFrame->GetParent());
rowGroup->GetContinuousBCBorderWidth(mP2t, border);
}
//get the rest of the borders; will overwrite all but bottom
aFrame->GetContinuousBCBorderWidth(mP2t, border);
nsresult res = mRow.SetBCBorder(border, this);
if (!NS_SUCCEEDED(res)) {
return res;
}
}
aPassThrough = !mRow.IsVisible();
}
else {
mRow.SetFrame(aFrame);
}
/* Translate */
if (eOrigin_TableRow == mOrigin) {
/* If we originate from the row, then make the row the origin. */
mRow.mRect.MoveTo(0, 0);
}
//else: Use row group's coord system -> no translation necessary
for (nsTableCellFrame* cell = aFrame->GetFirstCell(); cell; cell = cell->GetNextCell()) {
mCellRect = cell->GetRect();
//Translate to use the same coord system as mRow.
mCellRect.MoveBy(mRow.mRect.x, mRow.mRect.y);
if (mCellRect.Intersects(mDirtyRect)) {
nsresult rv = PaintCell(cell, aPassThrough || cell->HasView());
if (NS_FAILED(rv)) return rv;
}
}
/* Unload row data */
mRow.Clear();
return NS_OK;
}
nsresult
TableBackgroundPainter::PaintCell(nsTableCellFrame* aCell,
PRBool aPassSelf)
{
NS_PRECONDITION(aCell, "null frame");
const nsStyleTableBorder* cellTableStyle;
cellTableStyle = aCell->GetStyleTableBorder();
if (!(NS_STYLE_TABLE_EMPTY_CELLS_SHOW == cellTableStyle->mEmptyCells ||
NS_STYLE_TABLE_EMPTY_CELLS_SHOW_BACKGROUND == cellTableStyle->mEmptyCells)
&& aCell->GetContentEmpty()) {
return NS_OK;
}
PRInt32 colIndex;
aCell->GetColIndex(colIndex);
//Paint column group background
if (mCols && mCols[colIndex].mColGroup && mCols[colIndex].mColGroup->IsVisible()) {
nsCSSRendering::PaintBackgroundWithSC(mPresContext, mRenderingContext,
mCols[colIndex].mColGroup->mFrame, mDirtyRect,
mCols[colIndex].mColGroup->mRect,
*mCols[colIndex].mColGroup->mBackground,
*mCols[colIndex].mColGroup->mBorder,
mZeroPadding, PR_TRUE, &mCellRect);
}
//Paint column background
if (mCols && mCols[colIndex].mCol.IsVisible()) {
nsCSSRendering::PaintBackgroundWithSC(mPresContext, mRenderingContext,
mCols[colIndex].mCol.mFrame, mDirtyRect,
mCols[colIndex].mCol.mRect,
*mCols[colIndex].mCol.mBackground,
*mCols[colIndex].mCol.mBorder,
mZeroPadding, PR_TRUE, &mCellRect);
}
//Paint row group background
if (mRowGroup.IsVisible()) {
nsCSSRendering::PaintBackgroundWithSC(mPresContext, mRenderingContext,
mRowGroup.mFrame, mDirtyRect, mRowGroup.mRect,
*mRowGroup.mBackground, *mRowGroup.mBorder,
mZeroPadding, PR_TRUE, &mCellRect);
}
//Paint row background
if (mRow.IsVisible()) {
nsCSSRendering::PaintBackgroundWithSC(mPresContext, mRenderingContext,
mRow.mFrame, mDirtyRect, mRow.mRect,
*mRow.mBackground, *mRow.mBorder,
mZeroPadding, PR_TRUE, &mCellRect);
}
//Paint cell background in border-collapse unless we're just passing
if (mIsBorderCollapse && !aPassSelf) {
mRenderingContext.PushState();
mRenderingContext.Translate(mCellRect.x, mCellRect.y);
mDirtyRect.MoveBy(-mCellRect.x, -mCellRect.y);
aCell->Paint(mPresContext, mRenderingContext, mDirtyRect,
NS_FRAME_PAINT_LAYER_BACKGROUND,
NS_PAINT_FLAG_TABLE_BG_PAINT | NS_PAINT_FLAG_TABLE_CELL_BG_PASS);
mDirtyRect.MoveBy(mCellRect.x, mCellRect.y);
PRBool clipEmpty;
mRenderingContext.PopState(clipEmpty);
}
return NS_OK;
}

View File

@ -0,0 +1,271 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is TableBackgroundPainter interface.
*
* The Initial Developer of the Original Code is
* Elika J. Etemad ("fantasai") <fantasai@inkedblade.net>.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsTablePainter_h__
#define nsTablePainter_h__
typedef PRUint8 BCPixelSize;
#define BC_BORDER_TOP_HALF_COORD(p2t,px) NSToCoordRound(((px) - (px) / 2) * (p2t) )
#define BC_BORDER_RIGHT_HALF_COORD(p2t,px) NSToCoordRound(( (px) / 2) * (p2t) )
#define BC_BORDER_BOTTOM_HALF_COORD(p2t,px) NSToCoordRound(( (px) / 2) * (p2t) )
#define BC_BORDER_LEFT_HALF_COORD(p2t,px) NSToCoordRound(((px) - (px) / 2) * (p2t) )
#define BC_BORDER_TOP_HALF(px) ((px) - (px) / 2)
#define BC_BORDER_RIGHT_HALF(px) ((px) / 2)
#define BC_BORDER_BOTTOM_HALF(px) ((px) / 2)
#define BC_BORDER_LEFT_HALF(px) ((px) - (px) / 2)
// flags for Paint, PaintChild, PaintChildren are currently only used by tables.
//Table-based paint call; not a direct call as with views
#define NS_PAINT_FLAG_TABLE_BG_PAINT 0x00000001
//Cells should paint their backgrounds only, no children
#define NS_PAINT_FLAG_TABLE_CELL_BG_PASS 0x00000002
#include "nsIFrame.h"
class nsTableFrame;
class nsTableRowGroupFrame;
class nsTableRowFrame;
class nsTableCellFrame;
class TableBackgroundPainter
{
/*
* Helper class for painting table backgrounds
*
*/
public:
enum Origin { eOrigin_Table, eOrigin_TableRowGroup, eOrigin_TableRow };
/** Public constructor
* @param aTableFrame - the table's table frame
* @param aOrigin - what type of table frame is creating this instance
* @param aPresContext - the presentation context
* @param aRenderingContext - the rendering context
* @param aDirtyRect - the area that needs to be painted
*/
TableBackgroundPainter(nsTableFrame* aTableFrame,
Origin aOrigin,
nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect);
/** Destructor */
~TableBackgroundPainter();
/* ~*~ The Border Collapse Painting Issue ~*~
In border-collapse, the *table* paints the cells' borders,
so we need to make sure the backgrounds get painted first
(underneath) by doing a cell-background-only painting pass.
This happens in both Standards and Quirks mode PaintTable
calls.
The table must then do a no-cell-background pass that
continues as a normal background paint call in the cell
descendants.) This method doesn't handle views very well, but
then, nothing about BC table painting really does.
*/
/* ~*~ Using Standards Mode Painting ~*~
A call to PaintTable will normally paint all of the table's
elements (except the cells in non-BC). Elements with views
however, will be skipped and must create their own painter
to call the appropriate paint function in their ::Paint
method (e.g. painter.PaintRow in nsTableRow::Paint)
*/
/** Paint background for the table frame and its children down through cells
* (Cells themselves will only be painted in border collapse)
* Standards mode only
* Table must do a flagged TABLE_BG_PAINT ::Paint call on its
* children afterwards
* @param aTableFrame - the table frame
*/
nsresult PaintTable(nsTableFrame* aTableFrame);
/** Paint background for the row group and its children down through cells
* (Cells themselves will only be painted in border collapse)
* Standards mode only
* Table Row Group must do a flagged TABLE_BG_PAINT ::Paint call on its
* children afterwards
* @param aFrame - the table row group frame
*/
nsresult PaintRowGroup(nsTableRowGroupFrame* aFrame)
{ return PaintRowGroup(aFrame, PR_FALSE); }
/** Paint background for the row and its children down through cells
* (Cells themselves will only be painted in border collapse)
* Standards mode only
* Table Row must do a flagged TABLE_BG_PAINT ::Paint call on its
* children afterwards
* @param aFrame - the table row frame
*/
nsresult PaintRow(nsTableRowFrame* aFrame)
{ return PaintRow(aFrame, PR_FALSE); }
/** Paint table's background, Quirks mode only
* Cell backgrounds will also be painted in border collapse:
* Table must do a flagged TABLE_BG_PAINT on its children
* afterwards.
* @param aTableFrame - the table frame
* @param aDeflate - deflation needed to bring table's mRect
* to the outer grid lines in border-collapse
*/
nsresult QuirksPaintTable(nsTableFrame* aTableFrame,
nsMargin& aDeflate);
private:
/** Paint table frame's background
* @param aTableFrame - the table frame
* @param aFirstRowGroup - the first (in layout order) row group
* may be null
* @param aLastRowGroup - the last (in layout order) row group
* may be null
* @param aDeflate - adjustment to frame's rect (used for quirks BC)
* may be null
*/
nsresult PaintTableFrame(nsTableFrame* aTableFrame,
nsTableRowGroupFrame* aFirstRowGroup,
nsTableRowGroupFrame* aLastRowGroup,
nsMargin* aDeflate = nsnull);
/* aPassThrough params indicate whether to paint the element or to just
* pass through and paint underlying layers only
* See Public versions for function descriptions
*/
nsresult PaintRowGroup(nsTableRowGroupFrame* aFrame,
PRBool aPassThrough);
nsresult PaintRow(nsTableRowFrame* aFrame,
PRBool aPassThrough);
/** Paint table background layers for this cell space
* Also paints cell's own background in border-collapse mode
* @param aFrame - the cell
* @param aPassSelf - pass this cell; i.e. paint only underlying layers
*/
nsresult PaintCell(nsTableCellFrame* aFrame,
PRBool aPassSelf);
/** Translate mRenderingContext, mDirtyRect, and mCols' column and
* colgroup coords
* @param aDX - origin's x-coord change
* @param aDY - origin's y-coord change
*/
void TranslateContext(nscoord aDX,
nscoord aDY);
struct TableBackgroundData;
friend struct TableBackgroundData;
MOZ_DECL_CTOR_COUNTER(TableBackgroundData)
struct TableBackgroundData {
nsIFrame* mFrame;
nsRect mRect;
const nsStyleBackground* mBackground;
const nsStyleBorder* mBorder;
/** Data is valid & frame is visible */
PRBool IsVisible() const { return mBackground != nsnull; }
/** Constructor */
TableBackgroundData();
/** Destructor */
~TableBackgroundData();
/** Destroys synthesized data. MUST be called before destructor
* @param aPresContext - the pres context
*/
void Destroy(nsIPresContext* aPresContext);
/** Clear background data */
void Clear();
/** Calculate and set all data values to represent aFrame */
void SetFull(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
nsIFrame* aFrame);
/** Set frame data (mFrame, mRect) but leave style data empty */
void SetFrame(nsIFrame* aFrame);
/** True if need to set border-collapse border; must call SetFull beforehand */
PRBool ShouldSetBCBorder();
/** Set border-collapse border with aBorderWidth as widths */
nsresult SetBCBorder(nsMargin& aBorderWidth,
TableBackgroundPainter* aPainter);
private:
nsStyleBorder* mSynthBorder;
};
struct ColData {
TableBackgroundData mCol;
TableBackgroundData* mColGroup; //link to col's parent colgroup's data (owned by painter)
ColData() {
mColGroup = nsnull;
}
};
nsIPresContext* mPresContext;
nsIRenderingContext& mRenderingContext;
nsRect mDirtyRect;
#ifdef DEBUG
nsCompatibility mCompatMode;
#endif
PRBool mIsBorderCollapse;
Origin mOrigin; //user's table frame type
ColData* mCols; //array of columns' ColData
PRUint32 mNumCols;
TableBackgroundData mRowGroup; //current row group
TableBackgroundData mRow; //current row
nsRect mCellRect; //current cell's rect
nsStyleBorder mZeroBorder; //cached zero-width border
nsStylePadding mZeroPadding; //cached zero-width padding
float mP2t; //pixels to twips
};
MOZ_DECL_CTOR_COUNTER(TableBackgroundPainter)
#endif

View File

@ -538,7 +538,25 @@ NS_METHOD nsTableRowFrame::Paint(nsIPresContext* aPresContext,
aRenderingContext.DrawRect(0, 0, mRect.width, mRect.height);
}
#endif
// Standards mode background painting removed. See bug 4510
if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer &&
//direct (not table-called) background paint
!(aFlags & (NS_PAINT_FLAG_TABLE_BG_PAINT | NS_PAINT_FLAG_TABLE_CELL_BG_PASS))) {
//Quirks inherits bg into cells & paints them there
if (eCompatibility_NavQuirks != aPresContext->CompatibilityMode()) {
nsTableFrame* tableFrame;
nsTableFrame::GetTableFrame(this, tableFrame);
NS_ASSERTION(tableFrame, "null table frame");
TableBackgroundPainter painter(tableFrame,
TableBackgroundPainter::eOrigin_TableRow,
aPresContext, aRenderingContext,
aDirtyRect);
nsresult rv = painter.PaintRow(this);
if (NS_FAILED(rv)) return rv;
aFlags |= NS_PAINT_FLAG_TABLE_BG_PAINT;
}
}
PRUint8 overflow = GetStyleDisplay()->mOverflow;
PRBool clip = overflow == NS_STYLE_OVERFLOW_HIDDEN ||
@ -547,7 +565,8 @@ NS_METHOD nsTableRowFrame::Paint(nsIPresContext* aPresContext,
aRenderingContext.PushState();
SetOverflowClipRect(aRenderingContext);
}
PaintChildren(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer, aFlags);
PaintChildren(aPresContext, aRenderingContext, aDirtyRect,
aWhichLayer, aFlags);
if (clip) {
PRBool clipState;
aRenderingContext.PopState(clipState);
@ -862,8 +881,7 @@ nsTableRowFrame::ReflowChildren(nsIPresContext* aPresContext,
PRInt32 cellColIndex;
cellFrame->GetColIndex(cellColIndex);
cellColSpan = aTableFrame.GetEffectiveColSpan(*cellFrame);
x += cellSpacingX;
// If the adjacent cell is in a prior row (because of a rowspan) add in the space
if ((iter.IsLeftToRight() && (prevColIndex != (cellColIndex - 1))) ||
(!iter.IsLeftToRight() && (prevColIndex != cellColIndex + cellColSpan))) {
@ -1034,10 +1052,7 @@ nsTableRowFrame::ReflowChildren(nsIPresContext* aPresContext,
}
ConsiderChildOverflow(aPresContext, aDesiredSize.mOverflowArea, kidFrame);
kidFrame = iter.Next(); // Get the next child
// if this was the last child, and it had a colspan>1, add in the cellSpacing for the colspan
// if the last kid wasn't a colspan, then we still have the colspan of the last real cell
if (!kidFrame && (cellColSpan > 1))
x += cellSpacingX;
x += cellSpacingX;
}
// just set our width to what was available. The table will calculate the width and not use our value.
@ -1524,6 +1539,24 @@ nsTableRowFrame::GetUnpaginatedHeight(nsIPresContext* aPresContext)
return 0;
}
void nsTableRowFrame::SetContinuousBCBorderWidth(PRUint8 aForSide,
BCPixelSize aPixelValue)
{
switch (aForSide) {
case NS_SIDE_RIGHT:
mRightContBorderWidth = aPixelValue;
return;
case NS_SIDE_TOP:
mTopContBorderWidth = aPixelValue;
return;
case NS_SIDE_LEFT:
mLeftContBorderWidth = aPixelValue;
return;
default:
NS_ERROR("invalid NS_SIDE arg");
}
}
/* ----- global methods ----- */
nsresult

View File

@ -39,6 +39,7 @@
#include "nscore.h"
#include "nsHTMLContainerFrame.h"
#include "nsTablePainter.h"
class nsTableFrame;
class nsTableCellFrame;
@ -226,11 +227,31 @@ public:
void SetUnpaginatedHeight(nsIPresContext* aPresContext, nscoord aValue);
nscoord GetTopBCBorderWidth(float* aPixelsToTwips = nsnull);
void SetTopBCBorderWidth(nscoord aWidth);
void SetTopBCBorderWidth(BCPixelSize aWidth);
nscoord GetBottomBCBorderWidth(float* aPixelsToTwips = nsnull);
void SetBottomBCBorderWidth(nscoord aWidth);
void SetBottomBCBorderWidth(BCPixelSize aWidth);
nsMargin* GetBCBorderWidth(float aPixelsToTwips,
nsMargin& aBorder);
/**
* Gets inner border widths before collapsing with cell borders
* Caller must get bottom border from next row or from table
* GetContinuousBCBorderWidth will not overwrite aBorder.bottom
* see nsTablePainter about continuous borders
*/
void GetContinuousBCBorderWidth(float aPixelsToTwips,
nsMargin& aBorder);
/**
* @returns outer top bc border == prev row's bottom inner
*/
nscoord GetOuterTopContBCBorderWidth(float aPixelsToTwips);
/**
* Sets full border widths before collapsing with cell borders
* @param aForSide - side to set; only accepts right, left, and top
*/
void SetContinuousBCBorderWidth(PRUint8 aForSide,
BCPixelSize aPixelValue);
protected:
/** protected constructor.
@ -238,7 +259,7 @@ protected:
*/
nsTableRowFrame();
void InitChildReflowState(nsIPresContext& aPresContext,
void InitChildReflowState(nsIPresContext& aPresContext,
const nsSize& aAvailSize,
PRBool aBorderCollapse,
float aPixelsToTwips,
@ -318,8 +339,11 @@ private:
nscoord mMaxCellDescent; // does *not* include cells with rowspan > 1
// border widths in pixels in the collapsing border model
unsigned mTopBorderWidth:8;
unsigned mBottomBorderWidth:8;
BCPixelSize mTopBorderWidth;
BCPixelSize mBottomBorderWidth;
BCPixelSize mRightContBorderWidth;
BCPixelSize mTopContBorderWidth;
BCPixelSize mLeftContBorderWidth;
#ifdef DEBUG_TABLE_REFLOW_TIMING
public:
@ -433,7 +457,7 @@ inline nscoord nsTableRowFrame::GetTopBCBorderWidth(float* aPixelsToTwips)
return width;
}
inline void nsTableRowFrame::SetTopBCBorderWidth(nscoord aWidth)
inline void nsTableRowFrame::SetTopBCBorderWidth(BCPixelSize aWidth)
{
mTopBorderWidth = aWidth;
}
@ -444,7 +468,7 @@ inline nscoord nsTableRowFrame::GetBottomBCBorderWidth(float* aPixelsToTwips)
return width;
}
inline void nsTableRowFrame::SetBottomBCBorderWidth(nscoord aWidth)
inline void nsTableRowFrame::SetBottomBCBorderWidth(BCPixelSize aWidth)
{
mBottomBorderWidth = aWidth;
}
@ -460,4 +484,21 @@ inline nsMargin* nsTableRowFrame::GetBCBorderWidth(float aPixelsToTwips,
return &aBorder;
}
inline void
nsTableRowFrame::GetContinuousBCBorderWidth(float aPixelsToTwips,
nsMargin& aBorder)
{
aBorder.right = BC_BORDER_LEFT_HALF_COORD(aPixelsToTwips,
mLeftContBorderWidth);
aBorder.top = BC_BORDER_BOTTOM_HALF_COORD(aPixelsToTwips,
mTopContBorderWidth);
aBorder.left = BC_BORDER_RIGHT_HALF_COORD(aPixelsToTwips,
mRightContBorderWidth);
}
inline nscoord nsTableRowFrame::GetOuterTopContBCBorderWidth(float aPixelsToTwips)
{
return BC_BORDER_TOP_HALF_COORD(aPixelsToTwips, mTopContBorderWidth);
}
#endif

View File

@ -94,7 +94,7 @@ nsTableRowGroupFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr)
*aInstancePtr = (void*)this;
return NS_OK;
}
else if (aIID.Equals(NS_GET_IID(nsILineIteratorNavigator)))
else if (aIID.Equals(NS_GET_IID(nsILineIteratorNavigator)))
{ // note there is no addref here, frames are not addref'd
*aInstancePtr = (void*)(nsILineIteratorNavigator*)this;
return NS_OK;
@ -204,7 +204,25 @@ NS_METHOD nsTableRowGroupFrame::Paint(nsIPresContext* aPresContext,
aRenderingContext.DrawRect(0, 0, mRect.width, mRect.height);
}
#endif
// Standards mode background painting removed. See bug 4510
if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer &&
//direct (not table-called) background paint
!(aFlags & (NS_PAINT_FLAG_TABLE_BG_PAINT | NS_PAINT_FLAG_TABLE_CELL_BG_PASS))) {
//Quirks inherits bg into cells & paints them there
if (eCompatibility_NavQuirks != aPresContext->CompatibilityMode()) {
nsTableFrame* tableFrame;
nsTableFrame::GetTableFrame(this, tableFrame);
NS_ASSERTION(tableFrame, "null table frame");
TableBackgroundPainter painter(tableFrame,
TableBackgroundPainter::eOrigin_TableRowGroup,
aPresContext, aRenderingContext,
aDirtyRect);
nsresult rv = painter.PaintRowGroup(this);
if (NS_FAILED(rv)) return rv;
aFlags |= NS_PAINT_FLAG_TABLE_BG_PAINT;
}
}
PRUint8 overflow = GetStyleDisplay()->mOverflow;
PRBool clip = overflow == NS_STYLE_OVERFLOW_HIDDEN ||
@ -213,7 +231,8 @@ NS_METHOD nsTableRowGroupFrame::Paint(nsIPresContext* aPresContext,
aRenderingContext.PushState();
SetOverflowClipRect(aRenderingContext);
}
PaintChildren(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer, aFlags);
PaintChildren(aPresContext, aRenderingContext, aDirtyRect,
aWhichLayer, aFlags);
if (clip) {
PRBool clipState;
aRenderingContext.PopState(clipState);
@ -286,9 +305,9 @@ nsTableRowGroupFrame::GetFrameForPoint(nsIPresContext* aPresContext,
// aKidRect is relative to the upper-left origin of our frame
void
nsTableRowGroupFrame::PlaceChild(nsIPresContext* aPresContext,
nsRowGroupReflowState& aReflowState,
nsIFrame* aKidFrame,
nsHTMLReflowMetrics& aDesiredSize)
nsRowGroupReflowState& aReflowState,
nsIFrame* aKidFrame,
nsHTMLReflowMetrics& aDesiredSize)
{
// Place and size the child
FinishReflowChild(aKidFrame, aPresContext, nsnull, aDesiredSize, 0, aReflowState.y, 0);
@ -1854,6 +1873,24 @@ nsTableRowGroupFrame::GetBCBorderWidth(float aPixelsToTwips,
return &aBorder;
}
void nsTableRowGroupFrame::SetContinuousBCBorderWidth(PRUint8 aForSide,
BCPixelSize aPixelValue)
{
switch (aForSide) {
case NS_SIDE_RIGHT:
mRightContBorderWidth = aPixelValue;
return;
case NS_SIDE_BOTTOM:
mBottomContBorderWidth = aPixelValue;
return;
case NS_SIDE_LEFT:
mLeftContBorderWidth = aPixelValue;
return;
default:
NS_ERROR("invalid NS_SIDE argument");
}
}
//nsILineIterator methods for nsTableFrame
NS_IMETHODIMP
nsTableRowGroupFrame::GetNumLines(PRInt32* aResult)

View File

@ -41,6 +41,7 @@
#include "nsHTMLContainerFrame.h"
#include "nsIAtom.h"
#include "nsILineIterator.h"
#include "nsTablePainter.h"
class nsTableFrame;
class nsTableRowFrame;
@ -220,6 +221,22 @@ public:
nsMargin* GetBCBorderWidth(float aPixelsToTwips,
nsMargin& aBorder);
/**
* Gets inner border widths before collapsing with cell borders
* Caller must get top border from previous row group or from table
* GetContinuousBCBorderWidth will not overwrite aBorder.top
* see nsTablePainter about continuous borders
*/
void GetContinuousBCBorderWidth(float aPixelsToTwips,
nsMargin& aBorder);
/**
* Sets full border widths before collapsing with cell borders
* @param aForSide - side to set; only right, left, and bottom valid
*/
void SetContinuousBCBorderWidth(PRUint8 aForSide,
BCPixelSize aPixelValue);
// nsILineIterator methods
public:
NS_IMETHOD GetNumLines(PRInt32* aResult);
@ -359,6 +376,13 @@ protected:
void UndoContinuedRow(nsIPresContext* aPresContext,
nsTableRowFrame* aRow);
private:
// border widths in pixels in the collapsing border model
BCPixelSize mRightContBorderWidth;
BCPixelSize mBottomContBorderWidth;
BCPixelSize mLeftContBorderWidth;
public:
virtual nsIFrame* GetFirstFrame() { return mFrames.FirstChild(); };
virtual nsIFrame* GetLastFrame() { return mFrames.LastChild(); };
@ -419,4 +443,17 @@ inline void nsTableRowGroupFrame::SetHasStyleHeight(PRBool aValue)
mState &= ~NS_ROWGROUP_HAS_STYLE_HEIGHT;
}
}
inline void
nsTableRowGroupFrame::GetContinuousBCBorderWidth(float aPixelsToTwips,
nsMargin& aBorder)
{
aBorder.right = BC_BORDER_LEFT_HALF_COORD(aPixelsToTwips,
mRightContBorderWidth);
aBorder.bottom = BC_BORDER_TOP_HALF_COORD(aPixelsToTwips,
mBottomContBorderWidth);
aBorder.left = BC_BORDER_RIGHT_HALF_COORD(aPixelsToTwips,
mLeftContBorderWidth);
return;
}
#endif

View File

@ -150,7 +150,7 @@ plaintext, xmp, pre {
table {
display: table;
border-spacing: 2px;
border-spacing: 2px;
border-collapse: separate;
margin-top: 0;
margin-bottom: 0;
@ -170,11 +170,6 @@ table[align="right"] {
table[rules] {
border-collapse: collapse;
}
/* make sure backgrounds are inherited in tables -- see bug 4510 */
td, th, tr {
background: inherit;
}
/* caption inherits from table not table-outer */
caption {

View File

@ -538,16 +538,24 @@ void nsStyleBorder::RecalcData()
}
if ((mBorderStyle[NS_SIDE_TOP] & BORDER_COLOR_DEFINED) == 0) {
mBorderStyle[NS_SIDE_TOP] = BORDER_COLOR_DEFINED | BORDER_COLOR_FOREGROUND;
NS_ASSERTION(!(mBorderStyle[NS_SIDE_TOP] & BORDER_COLOR_SPECIAL),
"Clearing special border because BORDER_COLOR_DEFINED is not set");
SetBorderToForeground(NS_SIDE_TOP);
}
if ((mBorderStyle[NS_SIDE_BOTTOM] & BORDER_COLOR_DEFINED) == 0) {
mBorderStyle[NS_SIDE_BOTTOM] = BORDER_COLOR_DEFINED | BORDER_COLOR_FOREGROUND;
NS_ASSERTION(!(mBorderStyle[NS_SIDE_BOTTOM] & BORDER_COLOR_SPECIAL),
"Clearing special border because BORDER_COLOR_DEFINED is not set");
SetBorderToForeground(NS_SIDE_BOTTOM);
}
if ((mBorderStyle[NS_SIDE_LEFT]& BORDER_COLOR_DEFINED) == 0) {
mBorderStyle[NS_SIDE_LEFT] = BORDER_COLOR_DEFINED | BORDER_COLOR_FOREGROUND;
if ((mBorderStyle[NS_SIDE_LEFT] & BORDER_COLOR_DEFINED) == 0) {
NS_ASSERTION(!(mBorderStyle[NS_SIDE_LEFT] & BORDER_COLOR_SPECIAL),
"Clearing special border because BORDER_COLOR_DEFINED is not set");
SetBorderToForeground(NS_SIDE_LEFT);
}
if ((mBorderStyle[NS_SIDE_RIGHT] & BORDER_COLOR_DEFINED) == 0) {
mBorderStyle[NS_SIDE_RIGHT] = BORDER_COLOR_DEFINED | BORDER_COLOR_FOREGROUND;
NS_ASSERTION(!(mBorderStyle[NS_SIDE_RIGHT] & BORDER_COLOR_SPECIAL),
"Clearing special border because BORDER_COLOR_DEFINED is not set");
SetBorderToForeground(NS_SIDE_RIGHT);
}
}

View File

@ -110,6 +110,10 @@ table {
font-variant: -moz-initial;
}
/* make sure backgrounds are inherited in tables -- see bug 4510*/
td, th, tr {
background: inherit;
}
/* Quirk: collapse top margin of BODY and TD and bottom margin of TD */

View File

@ -88,11 +88,11 @@ nsTableCellMap::nsTableCellMap(nsTableFrame& aTableFrame,
NS_ASSERTION(orderedRowGroups.Count() == (PRInt32) numRowGroups,"problem in OrderRowGroups");
for (PRUint32 rgX = 0; rgX < numRowGroups; rgX++) {
nsTableRowGroupFrame* rgFrame =
aTableFrame.GetRowGroupFrame((nsIFrame*)orderedRowGroups.ElementAt(rgX));
nsTableRowGroupFrame* rgFrame =
nsTableFrame::GetRowGroupFrame((nsIFrame*)orderedRowGroups.ElementAt(rgX));
if (rgFrame) {
nsTableRowGroupFrame* prior = (0 == rgX)
? nsnull : aTableFrame.GetRowGroupFrame((nsIFrame*)orderedRowGroups.ElementAt(rgX - 1));
nsTableRowGroupFrame* prior = (0 == rgX)
? nsnull : nsTableFrame::GetRowGroupFrame((nsIFrame*)orderedRowGroups.ElementAt(rgX - 1));
InsertGroupCellMap(*rgFrame, prior);
}
}

View File

@ -40,6 +40,7 @@
#include "nsTableCellFrame.h"
#include "nsTableFrame.h"
#include "nsTableRowGroupFrame.h"
#include "nsTablePainter.h"
#include "nsReflowPath.h"
#include "nsStyleContext.h"
#include "nsStyleConsts.h"
@ -376,30 +377,23 @@ nsTableCellFrame::PaintUnderlay(nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
PRUint32& aFlags,
const nsStyleTableBorder& aCellTableStyle,
const nsStyleBorder& aStyleBorder,
const nsStylePadding& aStylePadding,
PRBool aVisibleBackground,
PRBool& aPaintChildren)
const nsStyleTableBorder& aCellTableStyle)
{
if (aVisibleBackground) {
nsRect rect(0, 0, mRect.width, mRect.height);
nsCSSRendering::PaintBackground(&aPresContext, aRenderingContext, this,
aDirtyRect, rect, aStyleBorder, aStylePadding,
PR_TRUE);
// draw the border only when there is content or showing empty cells
if (!GetContentEmpty() || NS_STYLE_TABLE_EMPTY_CELLS_SHOW == aCellTableStyle.mEmptyCells) {
PRIntn skipSides = GetSkipSides();
nsCSSRendering::PaintBorder(&aPresContext, aRenderingContext, this,
aDirtyRect, rect, aStyleBorder, mStyleContext, skipSides);
}
nsRect rect(0, 0, mRect.width, mRect.height);
nsCSSRendering::PaintBackground(&aPresContext, aRenderingContext, this,
aDirtyRect, rect, aStyleBorder, aStylePadding,
PR_TRUE);
PRIntn skipSides = GetSkipSides();
if (NS_STYLE_TABLE_EMPTY_CELLS_SHOW == aCellTableStyle.mEmptyCells ||
!GetContentEmpty()) {
nsCSSRendering::PaintBorder(&aPresContext, aRenderingContext, this,
aDirtyRect, rect, aStyleBorder, mStyleContext, skipSides);
}
// tell Paint to paint the children
aPaintChildren = PR_TRUE;
}
NS_METHOD
NS_IMETHODIMP
nsTableCellFrame::Paint(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
@ -412,10 +406,9 @@ nsTableCellFrame::Paint(nsIPresContext* aPresContext,
return NS_OK;
}
PRBool paintChildren = PR_TRUE;
PRBool paintChildren = PR_TRUE;
if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) {
PRBool paintBackground = PR_FALSE;
const nsStyleBorder* myBorder = nsnull;
const nsStylePadding* myPadding = nsnull;
const nsStyleTableBorder* cellTableStyle = nsnull;
@ -425,19 +418,20 @@ nsTableCellFrame::Paint(nsIPresContext* aPresContext,
myPadding = GetStylePadding();
cellTableStyle = GetStyleTableBorder();
// paint the background when the cell is not empty or when showing empty cells or background
paintBackground = (!GetContentEmpty() ||
NS_STYLE_TABLE_EMPTY_CELLS_SHOW == cellTableStyle->mEmptyCells ||
NS_STYLE_TABLE_EMPTY_CELLS_SHOW_BACKGROUND == cellTableStyle->mEmptyCells);
}
PaintUnderlay(*aPresContext, aRenderingContext, aDirtyRect, aFlags, *cellTableStyle,
*myBorder, *myPadding, paintBackground, paintChildren);
// draw the border & background only when there is content or showing empty cells
if (NS_STYLE_TABLE_EMPTY_CELLS_HIDE != cellTableStyle->mEmptyCells ||
!GetContentEmpty()) {
PaintUnderlay(*aPresContext, aRenderingContext, aDirtyRect, aFlags,
*myBorder, *myPadding, *cellTableStyle);
}
if (vis->IsVisible()) {
const nsStyleBackground* myColor = GetStyleBackground();
DecorateForSelection(aPresContext, aRenderingContext,myColor); //ignore return value
}
paintChildren = !(aFlags & NS_PAINT_FLAG_TABLE_CELL_BG_PASS);
//flags were for us; remove them for our children
aFlags &= ~ (NS_PAINT_FLAG_TABLE_CELL_BG_PASS | NS_PAINT_FLAG_TABLE_BG_PAINT);
}
#ifdef DEBUG
@ -931,7 +925,7 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext,
const nsStylePosition* pos = GetStylePosition();
// calculate the min cell width
nscoord onePixel = NSIntPixelsToTwips(1, p2t);
nscoord onePixel = NSIntPixelsToTwips(1, p2t);
nscoord smallestMinWidth = 0;
if (eCompatibility_NavQuirks == compatMode) {
if ((pos->mWidth.GetUnit() != eStyleUnit_Coord) &&
@ -1332,14 +1326,14 @@ nsBCTableCellFrame::PaintUnderlay(nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
PRUint32& aFlags,
const nsStyleTableBorder& aCellTableStyle,
const nsStyleBorder& aStyleBorder,
const nsStylePadding& aStylePadding,
PRBool aVisibleBackground,
PRBool& aPaintChildren)
const nsStyleTableBorder& aCellTableStyle)
{
// Draw the background only during pass1.
if (aVisibleBackground && !(aFlags & BORDER_COLLAPSE_BACKGROUNDS)) {
if (!(aFlags & NS_PAINT_FLAG_TABLE_BG_PAINT)
/*direct call; not table-based paint*/ ||
(aFlags & NS_PAINT_FLAG_TABLE_CELL_BG_PASS)
/*table cell background only pass*/) {
// make border-width reflect border-collapse assigned border
GET_PIXELS_TO_TWIPS(&aPresContext, p2t);
nsMargin borderWidth;
@ -1363,7 +1357,4 @@ nsBCTableCellFrame::PaintUnderlay(nsIPresContext& aPresContext,
PR_TRUE);
// borders are painted by nsTableFrame
}
// don't paint the children if it's pass1
aPaintChildren = (aFlags & BORDER_COLLAPSE_BACKGROUNDS);
}

View File

@ -289,16 +289,13 @@ protected:
friend class nsTableRowFrame;
// paint backgrounds and borders (in separate border model) if aVisibleBackground, always set aPaintChildren
virtual void PaintUnderlay(nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
PRUint32& aFlags,
const nsStyleTableBorder& aCellTableStyle,
const nsStyleBorder& aStyleBorder,
const nsStylePadding& aStylePadding,
PRBool aVisibleBackground,
PRBool& aPaintChildren);
const nsStyleTableBorder& aCellTableStyle);
nsresult DecorateForSelection(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
@ -471,11 +468,9 @@ protected:
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
PRUint32& aFlags,
const nsStyleTableBorder& aCellTableStyle,
const nsStyleBorder& aStyleBorder,
const nsStylePadding& aStylePadding,
PRBool aVisibleBackground,
PRBool& aPaintChildren);
const nsStyleTableBorder& aCellTableStyle);
private:

View File

@ -118,6 +118,24 @@ nsStyleCoord nsTableColFrame::GetStyleWidth() const
return returnWidth;
}
void nsTableColFrame::SetContinuousBCBorderWidth(PRUint8 aForSide,
BCPixelSize aPixelValue)
{
switch (aForSide) {
case NS_SIDE_TOP:
mTopContBorderWidth = aPixelValue;
return;
case NS_SIDE_RIGHT:
mRightContBorderWidth = aPixelValue;
return;
case NS_SIDE_BOTTOM:
mBottomContBorderWidth = aPixelValue;
return;
default:
NS_ERROR("invalid side arg");
}
}
void nsTableColFrame::ResetSizingInfo()
{
memset(mWidths, WIDTH_NOT_SET, NUM_WIDTHS * sizeof(PRInt32));
@ -135,8 +153,6 @@ nsTableColFrame::Paint(nsIPresContext* aPresContext,
if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_FALSE, &isVisible)) && !isVisible) {
return NS_OK;
}
// Standards mode background painting removed. See bug 4510
return NS_OK;
}

View File

@ -39,6 +39,7 @@
#include "nscore.h"
#include "nsContainerFrame.h"
#include "nsTablePainter.h"
class nsVoidArray;
class nsTableCellFrame;
@ -169,9 +170,26 @@ public:
void ResetSizingInfo();
nscoord GetLeftBorderWidth(float* aPixelsToTwips = nsnull);
void SetLeftBorderWidth(nscoord aWidth);
void SetLeftBorderWidth(BCPixelSize aWidth);
nscoord GetRightBorderWidth(float* aPixelsToTwips = nsnull);
void SetRightBorderWidth(nscoord aWidth);
void SetRightBorderWidth(BCPixelSize aWidth);
/**
* Gets inner border widths before collapsing with cell borders
* Caller must get left border from previous column or from table
* GetContinuousBCBorderWidth will not overwrite aBorder.left
* see nsTablePainter about continuous borders
*
* @return outer right border width (left inner for next column)
*/
nscoord GetContinuousBCBorderWidth(float aPixelsToTwips,
nsMargin& aBorder);
/**
* Set full border widths before collapsing with cell borders
* @param aForSide - side to set; only valid for top, right, and bottom
*/
void SetContinuousBCBorderWidth(PRUint8 aForSide,
BCPixelSize aPixelValue);
void Dump(PRInt32 aIndent);
@ -182,8 +200,13 @@ protected:
// the starting index of the column (starting at 0) that this col object represents //
PRUint32 mColIndex: 16;
PRUint32 mLeftBorderWidth: 8; // stored as pixels
PRUint32 mRightBorderWidth: 8; // stored as pixels
// border width in pixels
BCPixelSize mLeftBorderWidth;
BCPixelSize mRightBorderWidth;
BCPixelSize mTopContBorderWidth;
BCPixelSize mRightContBorderWidth;
BCPixelSize mBottomContBorderWidth;
// Widths including MIN_CON, DES_CON, FIX_CON, MIN_ADJ, DES_ADJ, FIX_ADJ, PCT, PCT_ADJ, MIN_PRO, FINAL
// Widths including MIN_CON, DES_CON, FIX_CON, MIN_ADJ, DES_ADJ, FIX_ADJ, PCT, PCT_ADJ, MIN_PRO, FINAL
// XXX these could be stored as pixels and converted to twips for a savings of 10 x 2 bytes.
@ -191,7 +214,7 @@ protected:
};
inline PRInt32 nsTableColFrame::GetColIndex() const
{
{
return mColIndex;
}
@ -206,7 +229,7 @@ inline nscoord nsTableColFrame::GetLeftBorderWidth(float* aPixelsToTwips)
return width;
}
inline void nsTableColFrame::SetLeftBorderWidth(nscoord aWidth)
inline void nsTableColFrame::SetLeftBorderWidth(BCPixelSize aWidth)
{
mLeftBorderWidth = aWidth;
}
@ -217,10 +240,23 @@ inline nscoord nsTableColFrame::GetRightBorderWidth(float* aPixelsToTwips)
return width;
}
inline void nsTableColFrame::SetRightBorderWidth(nscoord aWidth)
inline void nsTableColFrame::SetRightBorderWidth(BCPixelSize aWidth)
{
mRightBorderWidth = aWidth;
}
inline nscoord
nsTableColFrame::GetContinuousBCBorderWidth(float aPixelsToTwips,
nsMargin& aBorder)
{
aBorder.top = BC_BORDER_BOTTOM_HALF_COORD(aPixelsToTwips,
mTopContBorderWidth);
aBorder.right = BC_BORDER_LEFT_HALF_COORD(aPixelsToTwips,
mRightContBorderWidth);
aBorder.bottom = BC_BORDER_TOP_HALF_COORD(aPixelsToTwips,
mBottomContBorderWidth);
return BC_BORDER_RIGHT_HALF_COORD(aPixelsToTwips, mRightContBorderWidth);
}
#endif

View File

@ -391,8 +391,6 @@ nsTableColGroupFrame::Paint(nsIPresContext* aPresContext,
return NS_OK;
}
// Standards mode background painting removed. See bug 4510
PaintChildren(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer);
return NS_OK;
}
@ -646,6 +644,36 @@ void nsTableColGroupFrame::DeleteColFrame(nsIPresContext* aPresContext, nsTableC
mFrames.DestroyFrame(aPresContext, aColFrame);
}
void nsTableColGroupFrame::SetContinuousBCBorderWidth(PRUint8 aForSide,
BCPixelSize aPixelValue)
{
switch (aForSide) {
case NS_SIDE_TOP:
mTopContBorderWidth = aPixelValue;
return;
case NS_SIDE_BOTTOM:
mBottomContBorderWidth = aPixelValue;
return;
default:
NS_ERROR("invalid side arg");
}
}
void nsTableColGroupFrame::GetContinuousBCBorderWidth(float aPixelsToTwips,
nsMargin& aBorder)
{
nsTableFrame* table;
nsTableFrame::GetTableFrame(this, table);
nsTableColFrame* col = table->GetColFrame(mStartColIndex + mColCount - 1);
col->GetContinuousBCBorderWidth(aPixelsToTwips, aBorder);
aBorder.top = BC_BORDER_BOTTOM_HALF_COORD(aPixelsToTwips,
mTopContBorderWidth);
aBorder.bottom = BC_BORDER_TOP_HALF_COORD(aPixelsToTwips,
mBottomContBorderWidth);
return;
}
/* ----- global methods ----- */
nsresult

View File

@ -40,9 +40,9 @@
#include "nscore.h"
#include "nsHTMLContainerFrame.h"
#include "nsTableColFrame.h"
#include "nsTablePainter.h"
class nsTableColFrame;
class nsTableFrame;
enum nsTableColGroupType {
eColGroupContent = 0, // there is real col group content associated
@ -183,6 +183,21 @@ public:
static void ResetColIndices(nsIFrame* aFirstColGroup,
PRInt32 aFirstColIndex,
nsIFrame* aStartColFrame = nsnull);
/**
* Gets inner border widths before collapsing with cell borders
* Caller must get left border from previous column
* GetContinuousBCBorderWidth will not overwrite aBorder.left
* see nsTablePainter about continuous borders
*/
void GetContinuousBCBorderWidth(float aPixelsToTwips,
nsMargin& aBorder);
/**
* Set full border widths before collapsing with cell borders
* @param aForSide - side to set; only accepts top and bottom
*/
void SetContinuousBCBorderWidth(PRUint8 aForSide,
BCPixelSize aPixelValue);
protected:
nsTableColGroupFrame();
@ -221,6 +236,10 @@ protected:
PRInt32 mColCount;
// the starting column index this col group represents. Must be >= 0.
PRInt32 mStartColIndex;
// border width in pixels
BCPixelSize mTopContBorderWidth;
BCPixelSize mBottomContBorderWidth;
};
inline nsTableColGroupFrame::nsTableColGroupFrame()

View File

@ -50,6 +50,7 @@
#include "nsTableRowFrame.h"
#include "nsTableRowGroupFrame.h"
#include "nsTableOuterFrame.h"
#include "nsTablePainter.h"
#include "nsHTMLValue.h"
#include "BasicTableLayoutStrategy.h"
@ -126,18 +127,21 @@ struct nsTableReflowState {
nsTableFrame* table = (nsTableFrame*)aTableFrame.GetFirstInFlow();
nsMargin borderPadding = table->GetChildAreaOffset(&reflowState);
nscoord cellSpacingX = table->GetCellSpacingX();
x = borderPadding.left;
y = borderPadding.top;
x = borderPadding.left + cellSpacingX;
y = borderPadding.top; //cellspacing added during reflow
availSize.width = aAvailWidth;
if (NS_UNCONSTRAINEDSIZE != availSize.width) {
availSize.width -= borderPadding.left + borderPadding.right;
availSize.width -= borderPadding.left + borderPadding.right
+ (2 * cellSpacingX);
}
availSize.height = aAvailHeight;
if (NS_UNCONSTRAINEDSIZE != availSize.height) {
availSize.height -= borderPadding.top + borderPadding.bottom + (2 * table->GetCellSpacingY());
availSize.height -= borderPadding.top + borderPadding.bottom
+ (2 * table->GetCellSpacingY());
}
footerFrame = nsnull;
@ -288,7 +292,7 @@ nsTableFrame::~nsTableFrame()
if (nsnull!=mCellMap) {
delete mCellMap;
mCellMap = nsnull;
}
}
if (nsnull!=mTableLayoutStrategy) {
delete mTableLayoutStrategy;
@ -1230,7 +1234,7 @@ void nsTableFrame::AppendRowGroups(nsIPresContext& aPresContext,
nsTableRowGroupFrame*
nsTableFrame::GetRowGroupFrame(nsIFrame* aFrame,
nsIAtom* aFrameTypeIn) const
nsIAtom* aFrameTypeIn)
{
nsIFrame* rgFrame = nsnull;
nsIAtom* frameType = aFrameTypeIn;
@ -1386,43 +1390,54 @@ nsTableFrame::Paint(nsIPresContext* aPresContext,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags)
{
PRBool visibleBCBorders = PR_FALSE;
if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) {
TableBackgroundPainter painter(this, TableBackgroundPainter::eOrigin_Table,
aPresContext, aRenderingContext, aDirtyRect);
nsresult rv;
if (eCompatibility_NavQuirks == aPresContext->CompatibilityMode()) {
nsMargin deflate(0,0,0,0);
if (IsBorderCollapse()) {
GET_PIXELS_TO_TWIPS(aPresContext, p2t);
BCPropertyData* propData =
(BCPropertyData*)nsTableFrame::GetProperty(aPresContext,
(nsIFrame*)this,
nsLayoutAtoms::tableBCProperty,
PR_FALSE);
if (propData) {
deflate.top = BC_BORDER_TOP_HALF_COORD(p2t, propData->mTopBorderWidth);
deflate.right = BC_BORDER_RIGHT_HALF_COORD(p2t, propData->mRightBorderWidth);
deflate.bottom = BC_BORDER_BOTTOM_HALF_COORD(p2t, propData->mBottomBorderWidth);
deflate.left = BC_BORDER_LEFT_HALF_COORD(p2t, propData->mLeftBorderWidth);
}
}
rv = painter.QuirksPaintTable(this, deflate);
if (NS_FAILED(rv)) return rv;
}
else {
rv = painter.PaintTable(this);
if (NS_FAILED(rv)) return rv;
}
if (GetStyleVisibility()->IsVisible()) {
const nsStyleBorder* border = GetStyleBorder();
const nsStylePadding* padding = GetStylePadding();
nsRect rect(0, 0, mRect.width, mRect.height);
nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, this,
aDirtyRect, rect, *border, *padding,
PR_TRUE);
// paint the border here only for separate borders
if (!IsBorderCollapse()) {
PRIntn skipSides = GetSkipSides();
nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this,
aDirtyRect, rect, *border, mStyleContext, skipSides);
aDirtyRect, rect, *border, mStyleContext,
skipSides);
}
else {
visibleBCBorders = PR_TRUE;
PaintBCBorders(aPresContext, aRenderingContext, aDirtyRect);
}
}
aFlags |= NS_PAINT_FLAG_TABLE_BG_PAINT;
aFlags &= ~NS_PAINT_FLAG_TABLE_CELL_BG_PASS;
}
// for collapsed borders paint the backgrounds of cells, but not their contents (that happens below)
PRUint32 flags = aFlags;
if (visibleBCBorders) {
flags &= ~BORDER_COLLAPSE_BACKGROUNDS; // set bit to 0
}
PaintChildren(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer, flags);
if (visibleBCBorders) {
// for collapsed borders, paint the borders and then the backgrounds of cell
// contents but not the backgrounds of the cells
PaintBCBorders(aPresContext, aRenderingContext, aDirtyRect);
flags |= BORDER_COLLAPSE_BACKGROUNDS; // set bit to 1
PaintChildren(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer, flags);
}
PaintChildren(aPresContext, aRenderingContext, aDirtyRect,
aWhichLayer, aFlags);
#ifdef DEBUG
// for debug...
@ -1583,16 +1598,19 @@ nsTableFrame::AdjustSiblingsAfterReflow(nsIPresContext* aPresContext,
return NS_OK;
}
void
void
nsTableFrame::SetColumnDimensions(nscoord aHeight,
const nsMargin& aBorderPadding)
{
nscoord colHeight = aHeight -= aBorderPadding.top + aBorderPadding.bottom;
nscoord cellSpacingX = GetCellSpacingX();
nscoord cellSpacingY = GetCellSpacingY();
nscoord colHeight = aHeight -= aBorderPadding.top + aBorderPadding.bottom +
2* cellSpacingY;
nsIFrame* colGroupFrame = mColGroups.FirstChild();
PRInt32 colX = 0;
nsPoint colGroupOrigin(aBorderPadding.left + cellSpacingX, aBorderPadding.top);
nsPoint colGroupOrigin(aBorderPadding.left + cellSpacingX,
aBorderPadding.top + cellSpacingY);
PRInt32 numCols = GetColCount();
while (nsnull != colGroupFrame) {
nscoord colGroupWidth = 0;
@ -1606,19 +1624,19 @@ nsTableFrame::SetColumnDimensions(nscoord aHeight,
nsRect colRect(colOrigin.x, colOrigin.y, colWidth, colHeight);
colFrame->SetRect(colRect);
colOrigin.x += colWidth + cellSpacingX;
colGroupWidth += colWidth;
if (numCols - 1 != colX) {
colGroupWidth += cellSpacingX;
}
colGroupWidth += colWidth + cellSpacingX;
colX++;
}
colFrame = colFrame->GetNextSibling();
}
if (colGroupWidth) {
colGroupWidth -= cellSpacingX;
}
nsRect colGroupRect(colGroupOrigin.x, colGroupOrigin.y, colGroupWidth, colHeight);
colGroupFrame->SetRect(colGroupRect);
colGroupFrame = colGroupFrame->GetNextSibling();
colGroupOrigin.x += colGroupWidth;
colGroupOrigin.x += colGroupWidth + cellSpacingX;
}
}
@ -2881,7 +2899,7 @@ nsTableFrame::RecoverState(nsTableReflowState& aReflowState,
if ((NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP == display->mDisplay) &&
!aReflowState.footerFrame) {
aReflowState.footerFrame = childFrame;
}
}
else {
if ((NS_STYLE_DISPLAY_TABLE_ROW_GROUP == display->mDisplay) &&
!aReflowState.firstBodySection) {
@ -3647,7 +3665,7 @@ nsTableFrame::DistributeHeightToRows(const nsHTMLReflowState& aReflowState,
}
yOriginRow += rowRect.height + cellSpacingY;
yEndRG += rowRect.height + cellSpacingY;
}
}
rowFrame = rowFrame->GetNextRow();
}
if (amountUsed > 0) {
@ -5658,7 +5676,7 @@ nsTableFrame::CalcBCBorders(nsIPresContext& aPresContext)
BCCellBorder lastTopBorder, lastBottomBorder;
// horizontal borders indexed in x-direction (cols)
BCCellBorders lastBottomBorders(damageArea.width + 1, damageArea.x); if (!lastBottomBorders.borders) ABORT0();
PRBool startSeg;
PRBool startSeg, gotRowBorder;
BCMapCellInfo info, ajaInfo;
BCBorderOwner owner, ajaOwner;
@ -5680,6 +5698,7 @@ nsTableFrame::CalcBCBorders(nsIPresContext& aPresContext)
PRBool bottomRowSpan = PR_FALSE;
// see if lastTopBorder, lastBottomBorder need to be reset
if (iter.IsNewRow()) {
gotRowBorder = PR_FALSE;
lastTopBorder.Reset(info.rowIndex, info.rowSpan);
lastBottomBorder.Reset(cellEndRowIndex + 1, info.rowSpan);
}
@ -5722,7 +5741,7 @@ nsTableFrame::CalcBCBorders(nsIPresContext& aPresContext)
// update lastTopBorder and see if a new segment starts
startSeg = SetHorBorder(ownerBStyle, ownerWidth, ownerColor, tlCorner, lastTopBorder);
// store the border segment in the cell map
tableCellMap->SetBCBorderEdge(NS_SIDE_TOP, *info.cellMap, 0, 0, colX,
tableCellMap->SetBCBorderEdge(NS_SIDE_TOP, *info.cellMap, 0, 0, colX,
1, owner, ownerWidth, startSeg);
// update the affected borders of the cell, row, and table
DivideBCBorderSize(ownerWidth, smallHalf, largeHalf);
@ -5733,6 +5752,44 @@ nsTableFrame::CalcBCBorders(nsIPresContext& aPresContext)
info.topRow->SetTopBCBorderWidth(PR_MAX(smallHalf, info.topRow->GetTopBCBorderWidth()));
}
propData->mTopBorderWidth = LimitBorderWidth(PR_MAX(propData->mTopBorderWidth, (PRUint8)ownerWidth));
//calculate column continuous borders
//we only need to do this once, so we'll do it only on the first row
CalcDominantBorder(this, cgFrame, colFrame, info.rg, info.topRow,
nsnull, PR_TRUE, NS_SIDE_TOP, PR_FALSE, t2p,
owner, ownerBStyle, ownerWidth, ownerColor);
((nsTableColFrame*)colFrame)->SetContinuousBCBorderWidth(NS_SIDE_TOP,
ownerWidth);
if (numCols == cellEndColIndex + 1) {
CalcDominantBorder(this, cgFrame, colFrame, nsnull, nsnull,
nsnull, PR_TRUE, NS_SIDE_RIGHT, PR_FALSE, t2p,
owner, ownerBStyle, ownerWidth, ownerColor);
}
else {
CalcDominantBorder(nsnull, cgFrame, colFrame, nsnull, nsnull,
nsnull, PR_FALSE, NS_SIDE_RIGHT, PR_FALSE, t2p,
owner, ownerBStyle, ownerWidth, ownerColor);
}
((nsTableColFrame*)colFrame)->SetContinuousBCBorderWidth(NS_SIDE_RIGHT,
ownerWidth);
}
//calculate continuous top first row & rowgroup border: special case
//because it must include the table in the collapse
CalcDominantBorder(this, nsnull, nsnull, info.rg, info.topRow,
nsnull, PR_TRUE, NS_SIDE_TOP, PR_FALSE, t2p,
owner, ownerBStyle, ownerWidth, ownerColor);
info.topRow->SetContinuousBCBorderWidth(NS_SIDE_TOP, ownerWidth);
if (info.cgRight) {
//calculate continuous top colgroup border once per colgroup
CalcDominantBorder(this, info.cg, nsnull, info.rg, info.topRow,
nsnull, PR_TRUE, NS_SIDE_TOP, PR_FALSE, t2p,
owner, ownerBStyle, ownerWidth, ownerColor);
info.cg->SetContinuousBCBorderWidth(NS_SIDE_TOP, ownerWidth);
}
if (0 == info.colIndex) {
CalcDominantBorder(this, info.cg, info.leftCol, nsnull, nsnull,
nsnull, PR_TRUE, NS_SIDE_LEFT, PR_FALSE, t2p,
owner, ownerBStyle, ownerWidth, ownerColor);
mBits.mLeftContBCBorder = ownerWidth;
}
}
else {
@ -5760,10 +5817,10 @@ nsTableFrame::CalcBCBorders(nsIPresContext& aPresContext)
nsTableRowFrame* rowFrame = nsnull;
for (PRInt32 rowX = info.rowIndex; rowX <= cellEndRowIndex; rowX++) {
rowFrame = (rowX == info.rowIndex) ? info.topRow : rowFrame->GetNextRow();
CalcDominantBorder(this, info.cg, info.leftCol, info.rg, rowFrame, info.cell, PR_TRUE, NS_SIDE_LEFT,
CalcDominantBorder(this, info.cg, info.leftCol, info.rg, rowFrame, info.cell, PR_TRUE, NS_SIDE_LEFT,
PR_FALSE, t2p, owner, ownerBStyle, ownerWidth, ownerColor);
BCCornerInfo& tlCorner = (0 == rowX) ? topCorners[0] : bottomCorners[0]; // top left
tlCorner.Update(NS_SIDE_BOTTOM, owner, ownerBStyle, ownerWidth, ownerColor);
tlCorner.Update(NS_SIDE_BOTTOM, owner, ownerBStyle, ownerWidth, ownerColor);
tableCellMap->SetBCBorderCorner(eTopLeft, *info.cellMap, iter.mRowGroupStart, rowX,
0, tlCorner.ownerSide, tlCorner.subWidth, tlCorner.bevel);
bottomCorners[0].Set(NS_SIDE_TOP, owner, ownerBStyle, ownerWidth, ownerColor); // bottom left
@ -5781,6 +5838,17 @@ nsTableFrame::CalcBCBorders(nsIPresContext& aPresContext)
info.leftCol->SetLeftBorderWidth(PR_MAX(smallHalf, info.leftCol->GetLeftBorderWidth()));
}
propData->mLeftBorderWidth = LimitBorderWidth(PR_MAX(propData->mLeftBorderWidth, ownerWidth));
//get row continuous borders
CalcDominantBorder(this, info.cg, info.leftCol, info.rg, rowFrame, nsnull, PR_TRUE, NS_SIDE_LEFT,
PR_FALSE, t2p, owner, ownerBStyle, ownerWidth, ownerColor);
rowFrame->SetContinuousBCBorderWidth(NS_SIDE_LEFT, ownerWidth);
}
//get row group continuous borders
if (info.rgBottom) { //once per row group, so check for bottom
CalcDominantBorder(this, info.cg, info.leftCol, info.rg, nsnull,
nsnull, PR_TRUE, NS_SIDE_LEFT, PR_FALSE, t2p,
owner, ownerBStyle, ownerWidth, ownerColor);
info.rg->SetContinuousBCBorderWidth(NS_SIDE_LEFT, ownerWidth);
}
}
@ -5818,6 +5886,18 @@ nsTableFrame::CalcBCBorders(nsIPresContext& aPresContext)
info.rightCol->SetRightBorderWidth(PR_MAX(largeHalf, info.rightCol->GetRightBorderWidth()));
}
propData->mRightBorderWidth = LimitBorderWidth(PR_MAX(propData->mRightBorderWidth, ownerWidth));
//get row continuous borders
CalcDominantBorder(this, info.cg, info.rightCol, info.rg, rowFrame,
nsnull, PR_TRUE, NS_SIDE_RIGHT, PR_TRUE, t2p,
owner, ownerBStyle, ownerWidth, ownerColor);
rowFrame->SetContinuousBCBorderWidth(NS_SIDE_RIGHT, ownerWidth);
}
//get row group continuous borders
if (info.rgBottom) { //once per rg, so check for bottom
CalcDominantBorder(this, info.cg, info.rightCol, info.rg, nsnull,
nsnull, PR_TRUE, NS_SIDE_RIGHT, PR_TRUE, t2p,
owner, ownerBStyle, ownerWidth, ownerColor);
info.rg->SetContinuousBCBorderWidth(NS_SIDE_RIGHT, ownerWidth);
}
}
else {
@ -5944,17 +6024,32 @@ nsTableFrame::CalcBCBorders(nsIPresContext& aPresContext)
lastBottomBorder.index = cellEndRowIndex + 1;
lastBottomBorder.span = info.rowSpan;
lastBottomBorders[colX] = lastBottomBorder;
//get col continuous border
CalcDominantBorder(this, cgFrame, colFrame, info.rg, info.bottomRow,
nsnull, PR_TRUE, NS_SIDE_BOTTOM, PR_TRUE, t2p,
owner, ownerBStyle, ownerWidth, ownerColor);
((nsTableColFrame*)colFrame)->SetContinuousBCBorderWidth(NS_SIDE_BOTTOM,
ownerWidth);
}
//get row group/col group continuous border
CalcDominantBorder(this, nsnull, nsnull, info.rg, info.bottomRow,
nsnull, PR_TRUE, NS_SIDE_BOTTOM, PR_TRUE, t2p,
owner, ownerBStyle, ownerWidth, ownerColor);
info.rg->SetContinuousBCBorderWidth(NS_SIDE_BOTTOM, ownerWidth);
CalcDominantBorder(this, info.cg, nsnull, info.rg, info.bottomRow,
nsnull, PR_TRUE, NS_SIDE_BOTTOM, PR_TRUE, t2p,
owner, ownerBStyle, ownerWidth, ownerColor);
info.cg->SetContinuousBCBorderWidth(NS_SIDE_BOTTOM, ownerWidth);
}
else {
PRInt32 segLength = 0;
for (PRInt32 colX = info.colIndex; colX <= cellEndColIndex; colX += segLength) {
iter.PeekBottom(info, colX, ajaInfo);
const nsIFrame* rg = (info.rgBottom) ? info.rg : nsnull;
CalcDominantBorder(nsnull, nsnull, nsnull, rg, info.bottomRow, info.cell, PR_FALSE, NS_SIDE_BOTTOM,
CalcDominantBorder(nsnull, nsnull, nsnull, rg, info.bottomRow, info.cell, PR_FALSE, NS_SIDE_BOTTOM,
PR_TRUE, t2p, owner, ownerBStyle, ownerWidth, ownerColor);
rg = (ajaInfo.rgTop) ? ajaInfo.rg : nsnull;
CalcDominantBorder(nsnull, nsnull, nsnull, rg, ajaInfo.topRow, ajaInfo.cell, PR_FALSE, NS_SIDE_TOP,
CalcDominantBorder(nsnull, nsnull, nsnull, rg, ajaInfo.topRow, ajaInfo.cell, PR_FALSE, NS_SIDE_TOP,
PR_FALSE, t2p, ajaOwner, ajaBStyle, ajaWidth, ajaColor);
CalcDominantBorder(PR_FALSE, owner, ownerBStyle, ownerWidth, ownerColor, ajaOwner, ajaBStyle, ajaWidth,
ajaColor, owner, ownerBStyle, ownerWidth, ownerColor, PR_TRUE);
@ -5972,23 +6067,23 @@ nsTableFrame::CalcBCBorders(nsIPresContext& aPresContext)
}
else if (prevRowIndex < cellEndRowIndex + 1) { // spans below the cell to the left
topCorners[colX] = blCorner;
blCorner.Set(NS_SIDE_RIGHT, owner, ownerBStyle, ownerWidth, ownerColor);
blCorner.Set(NS_SIDE_RIGHT, owner, ownerBStyle, ownerWidth, ownerColor);
update = PR_FALSE;
}
}
if (update) {
blCorner.Update(NS_SIDE_RIGHT, owner, ownerBStyle, ownerWidth, ownerColor);
blCorner.Update(NS_SIDE_RIGHT, owner, ownerBStyle, ownerWidth, ownerColor);
}
if (BOTTOM_DAMAGED(cellEndRowIndex) && LEFT_DAMAGED(colX)) {
if (hitsSpanBelow) {
tableCellMap->SetBCBorderCorner(eBottomLeft, *info.cellMap, iter.mRowGroupStart, cellEndRowIndex, colX,
tableCellMap->SetBCBorderCorner(eBottomLeft, *info.cellMap, iter.mRowGroupStart, cellEndRowIndex, colX,
blCorner.ownerSide, blCorner.subWidth, blCorner.bevel);
}
// store any corners this cell spans together with the aja cell
for (PRInt32 cX = colX + 1; cX < colX + segLength; cX++) {
BCCornerInfo& corner = bottomCorners[cX];
BCCornerInfo& corner = bottomCorners[cX];
corner.Set(NS_SIDE_RIGHT, owner, ownerBStyle, ownerWidth, ownerColor);
tableCellMap->SetBCBorderCorner(eBottomLeft, *info.cellMap, iter.mRowGroupStart, cellEndRowIndex,
tableCellMap->SetBCBorderCorner(eBottomLeft, *info.cellMap, iter.mRowGroupStart, cellEndRowIndex,
cX, corner.ownerSide, corner.subWidth, PR_FALSE);
}
}
@ -6008,7 +6103,7 @@ nsTableFrame::CalcBCBorders(nsIPresContext& aPresContext)
// store the border segment the cell map and update cellBorders
if (BOTTOM_DAMAGED(cellEndRowIndex) && LEFT_DAMAGED(colX) && RIGHT_DAMAGED(colX)) {
tableCellMap->SetBCBorderEdge(NS_SIDE_BOTTOM, *info.cellMap, iter.mRowGroupStart, cellEndRowIndex,
tableCellMap->SetBCBorderEdge(NS_SIDE_BOTTOM, *info.cellMap, iter.mRowGroupStart, cellEndRowIndex,
colX, segLength, owner, ownerWidth, startSeg);
// update the borders of the affected cells and rows
DivideBCBorderSize(ownerWidth, smallHalf, largeHalf);
@ -6027,16 +6122,39 @@ nsTableFrame::CalcBCBorders(nsIPresContext& aPresContext)
}
// update bottom right corner
BCCornerInfo& brCorner = bottomCorners[colX + segLength];
brCorner.Update(NS_SIDE_LEFT, owner, ownerBStyle, ownerWidth, ownerColor);
brCorner.Update(NS_SIDE_LEFT, owner, ownerBStyle, ownerWidth, ownerColor);
}
if (!gotRowBorder && 1 == info.rowSpan) {
//get continuous row/row group border
//we need to check the row group's bottom border if this is
//the last row in the row group, but only a cell with rowspan=1
//will know whether *this* row is at the bottom
const nsIFrame* rg = (info.rgBottom) ? info.rg : nsnull;
CalcDominantBorder(nsnull, nsnull, nsnull, rg, info.bottomRow,
nsnull, PR_FALSE, NS_SIDE_BOTTOM, PR_TRUE, t2p,
owner, ownerBStyle, ownerWidth, ownerColor);
rg = (ajaInfo.rgTop) ? ajaInfo.rg : nsnull;
CalcDominantBorder(nsnull, nsnull, nsnull, rg, ajaInfo.topRow,
nsnull, PR_FALSE, NS_SIDE_TOP, PR_FALSE, t2p,
ajaOwner, ajaBStyle, ajaWidth, ajaColor);
CalcDominantBorder(PR_FALSE, owner, ownerBStyle, ownerWidth,
ownerColor, ajaOwner, ajaBStyle, ajaWidth,
ajaColor, owner, ownerBStyle, ownerWidth,
ownerColor, PR_TRUE);
ajaInfo.topRow->SetContinuousBCBorderWidth(NS_SIDE_TOP, ownerWidth);
if (info.rgBottom) {
info.rg->SetContinuousBCBorderWidth(NS_SIDE_BOTTOM, ownerWidth);
}
gotRowBorder = PR_TRUE;
}
}
// see if the cell to the right had a rowspan and its lower left border needs be joined with this one's bottom
if ((numCols != cellEndColIndex + 1) && // there is a cell to the right
if ((numCols != cellEndColIndex + 1) && // there is a cell to the right
(lastBottomBorders[cellEndColIndex + 1].span > 1)) { // cell to right was a rowspan
BCCornerInfo& corner = bottomCorners[cellEndColIndex + 1];
if ((NS_SIDE_TOP != corner.ownerSide) && (NS_SIDE_BOTTOM != corner.ownerSide)) { // not a vertical owner
BCCellBorder& thisBorder = lastBottomBorder;
BCCellBorder& thisBorder = lastBottomBorder;
BCCellBorder& nextBorder = lastBottomBorders[info.colIndex + 1];
if ((thisBorder.color == nextBorder.color) && (thisBorder.width == nextBorder.width) &&
(thisBorder.style == nextBorder.style)) {
@ -7206,7 +7324,7 @@ PRBool nsTableFrame::RowHasSpanningCells(PRInt32 aRowIndex)
nsTableCellMap* cellMap = GetCellMap();
NS_PRECONDITION (cellMap, "bad call, cellMap not yet allocated.");
if (cellMap) {
result = cellMap->RowHasSpanningCells(aRowIndex);
result = cellMap->RowHasSpanningCells(aRowIndex);
}
return result;
}
@ -7217,7 +7335,7 @@ PRBool nsTableFrame::RowIsSpannedInto(PRInt32 aRowIndex)
nsTableCellMap* cellMap = GetCellMap();
NS_PRECONDITION (cellMap, "bad call, cellMap not yet allocated.");
if (cellMap) {
result = cellMap->RowIsSpannedInto(aRowIndex);
result = cellMap->RowIsSpannedInto(aRowIndex);
}
return result;
}

View File

@ -62,10 +62,6 @@ struct nsStylePosition;
enum nsPixelRound {eAlwaysRoundUp=0, eAlwaysRoundDown, eRoundUpIfHalfOrMore};
// flags for Paint, PaintChild, PaintChildren are currently only used by tables.
// use low order bit of flags to distinguish between pass1(0) and pass2(1) border collapse backgrounds
#define BORDER_COLLAPSE_BACKGROUNDS 0x00000001
#ifdef DEBUG_TABLE_REFLOW_TIMING
#ifdef WIN32
#include <windows.h>
@ -331,6 +327,14 @@ public:
// the surrounding margin space
nsMargin GetBCMargin(nsIPresContext* aPresContext) const;
/** Get width of table + colgroup + col collapse: elements that
* continue along the length of the whole left side.
* see nsTablePainter about continuous borders
* @param aPixelsToTwips - conversion factor
* @param aGetInner - get only inner half of border width
*/
nscoord GetContinuousLeftBCBorderWidth(float aPixelsToTwips) const;
void SetBCDamageArea(nsIPresContext& aPresContext,
const nsRect& aValue);
@ -643,7 +647,7 @@ protected:
nsTableReflowState& aReflowState,
nsReflowStatus& aStatus);
/** process a style chnaged notification.
/** process a style changed notification.
* @see nsIFrameReflow::Reflow
* TODO: needs to be optimized for which attribute was actually changed.
*/
@ -797,11 +801,10 @@ public:
nsVoidArray& GetColCache();
/**
* Return aFrame's child if aFrame is an nsScrollFrame, otherwise return aFrame
*/
nsTableRowGroupFrame* GetRowGroupFrame(nsIFrame* aFrame,
nsIAtom* aFrameTypeIn = nsnull) const;
/** Return aFrame's child if aFrame is an nsScrollFrame, otherwise return aFrame
*/
static nsTableRowGroupFrame* GetRowGroupFrame(nsIFrame* aFrame,
nsIAtom* aFrameTypeIn = nsnull);
protected:
@ -908,20 +911,21 @@ protected:
// DATA MEMBERS
struct TableBits {
unsigned mHadInitialReflow:1; // has intial reflow happened
unsigned mHaveReflowedColGroups:1; // have the col groups gotten their initial reflow
unsigned mNeedStrategyBalance:1; // does the strategy needs to balance the table
unsigned mNeedStrategyInit:1; // does the strategy needs to be initialized and then balance the table
unsigned mHasPctCol:1; // does any cell or col have a pct width
unsigned mCellSpansPctCol:1; // does any cell span a col with a pct width (or containing a cell with a pct width)
unsigned mDidResizeReflow:1; // did a resize reflow happen (indicating pass 2)
unsigned mIsBorderCollapse:1; // border collapsing model vs. separate model
unsigned mRowInserted:1;
unsigned mNeedSpecialReflow:1;
unsigned mNeedToInitiateSpecialReflow:1;
unsigned mInitiatedSpecialReflow:1;
unsigned mNeedToCalcBCBorders:1;
unsigned : 19; // unused
PRUint32 mHadInitialReflow:1; // has intial reflow happened
PRUint32 mHaveReflowedColGroups:1; // have the col groups gotten their initial reflow
PRUint32 mNeedStrategyBalance:1; // does the strategy needs to balance the table
PRUint32 mNeedStrategyInit:1; // does the strategy needs to be initialized and then balance the table
PRUint32 mHasPctCol:1; // does any cell or col have a pct width
PRUint32 mCellSpansPctCol:1; // does any cell span a col with a pct width (or containing a cell with a pct width)
PRUint32 mDidResizeReflow:1; // did a resize reflow happen (indicating pass 2)
PRUint32 mIsBorderCollapse:1; // border collapsing model vs. separate model
PRUint32 mRowInserted:1;
PRUint32 mNeedSpecialReflow:1;
PRUint32 mNeedToInitiateSpecialReflow:1;
PRUint32 mInitiatedSpecialReflow:1;
PRUint32 mNeedToCalcBCBorders:1;
PRUint32 mLeftContBCBorder:8;
PRUint32 : 11; // unused
} mBits;
nsTableCellMap* mCellMap; // maintains the relationships between rows, cols, and cells
@ -1041,7 +1045,7 @@ inline void nsTableFrame::SetRowInserted(PRBool aValue)
inline nsFrameList& nsTableFrame::GetColGroups()
{
return mColGroups;
return NS_STATIC_CAST(nsTableFrame*, GetFirstInFlow())->mColGroups;
}
inline nsVoidArray& nsTableFrame::GetColCache()
@ -1084,6 +1088,12 @@ inline void nsTableFrame::SetNeedToCalcBCBorders(PRBool aValue)
mBits.mNeedToCalcBCBorders = (unsigned)aValue;
}
inline nscoord
nsTableFrame::GetContinuousLeftBCBorderWidth(float aPixelsToTwips) const
{
return BC_BORDER_RIGHT_HALF_COORD(aPixelsToTwips, mBits.mLeftContBCBorder);
}
enum nsTableIteration {
eTableLTR = 0,
eTableRTL = 1,

View File

@ -0,0 +1,685 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is TableBackgroundPainter implementation.
*
* The Initial Developer of the Original Code is
* Elika J. Etemad ("fantasai") <fantasai@inkedblade.net>.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsTableFrame.h"
#include "nsTableRowGroupFrame.h"
#include "nsTableRowFrame.h"
#include "nsTableColGroupFrame.h"
#include "nsTableColFrame.h"
#include "nsTableCellFrame.h"
#include "nsTablePainter.h"
#include "nsCSSRendering.h"
/* ~*~ Standards Mode Painting ~*~
Background painting in Standards mode follows CSS2.1:17.5.1
That section does not, however, describe the effect of
borders on background image positioning. What we do is:
- in separate borders, the borders are passed in so that
their width figures in image positioning, even for rows/cols, which
don't have visible borders. This is done to allow authors
to position row backgrounds by, for example, aligning the
top left corner with the top left padding corner of the
top left table cell in the row in cases where all cells
have consistent border widths. If we didn't honor these
invisible borders, there would be no way to align
backgrounds with the padding edges, and designs would be
lost underneath the border.
- in collapsing borders, because the borders collapse, we
use the -continuous border- width to synthesize a border
style and pass that in instead of using the element's
assigned style directly.
The continuous border on a given edge of an element is
the collapse of all borders guaranteed to be continuous
along that edge. Cell borders are ignored (because, for
example, setting a thick border on the leftmost cell
should not shift the row background over; this way a
striped background set on <tr> will line up across rows
even if the cells are assigned arbitrary border widths.
For example, the continous border on the top edge of a
row group is the collapse of any row group, row, and
table borders involved. (The first row group's top would
be [table-top + row group top + first row top]. It's bottom
would be [row group bottom + last row bottom + next row
top + next row group top].)
The top edge of a column group likewise includes the
table top, row group top, and first row top borders. However,
it *also* includes its own top border, since that is guaranteed
to be continuous. It does not include column borders because
those are not guaranteed to be continuous: there may be two
columns with different borders in a single column group.
An alternative would be to define the continuous border as
[table? + row group + row] for horizontal
[table? + col group + col] for vertical
This makes it easier to line up backgrounds across elements
despite varying border widths, but it does not give much
flexibility in aligning /to/ those border widths.
*/
/* ~*~ Quirks Table Background Painting ~*~
Quirks inherits all backgrounds below the table level into the
cells; we don't paint intermediate backgrounds.
*/
/* ~*~ TableBackgroundPainter ~*~
The TableBackgroundPainter is created and destroyed in one painting call.
Its principal function is PaintTable, which paints all table element
backgrounds. The initial code in that method sets up an array of column
data that caches the background styles and the border sizes for the
columns and colgroups in TableBackgroundData structs in mCols. Data for
BC borders are calculated and stashed in a synthesized border style struct
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 exception to this pattern is when a table element has a view.
Elements with views are <dfn>passed through</dfn>, which means their data
(and their descendants' data) are not cached. The full loop is still
executed, however, so that underlying layers can get painted at the cell
level.
The TableBackgroundPainter is then destroyed.
Elements with views set up their own painter to finish the painting
process, since they were skipped. They call the appropriate sub-part
of the loop (e.g. PaintRow) which will paint the frame and descendants.
*/
TableBackgroundPainter::TableBackgroundData::TableBackgroundData()
: mFrame(nsnull),
mBackground(nsnull),
mBorder(nsnull),
mSynthBorder(nsnull)
{
MOZ_COUNT_CTOR(TableBackgroundData);
}
TableBackgroundPainter::TableBackgroundData::~TableBackgroundData()
{
NS_ASSERTION(!mSynthBorder, "must call Destroy before dtor");
MOZ_COUNT_DTOR(TableBackgroundData);
}
void
TableBackgroundPainter::TableBackgroundData::Destroy(nsIPresContext* aPresContext)
{
NS_PRECONDITION(aPresContext, "null prescontext");
if (mSynthBorder) {
mSynthBorder->Destroy(aPresContext);
mSynthBorder = nsnull;
}
}
void
TableBackgroundPainter::TableBackgroundData::Clear()
{
mRect.Empty();
mFrame = nsnull;
mBorder = nsnull;
mBackground = nsnull;
}
void
TableBackgroundPainter::TableBackgroundData::SetFrame(nsIFrame* aFrame)
{
NS_PRECONDITION(aFrame, "null frame");
mFrame = aFrame;
mRect = aFrame->GetRect();
}
void
TableBackgroundPainter::TableBackgroundData::SetFull(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
nsIFrame* aFrame)
{
NS_PRECONDITION(aFrame, "null frame");
mFrame = aFrame;
mRect = aFrame->GetRect();
/* IsVisibleForPainting doesn't use aRenderingContext except in nsTextFrames,
so we're not going to bother translating.*/
PRBool isVisible;
nsresult rv = aFrame->IsVisibleForPainting(aPresContext, aRenderingContext,
PR_TRUE, &isVisible);
if (NS_SUCCEEDED(rv) && isVisible &&
aFrame->GetStyleVisibility()->IsVisible()) {
mBackground = aFrame->GetStyleBackground();
mBorder = aFrame->GetStyleBorder();
}
}
inline PRBool
TableBackgroundPainter::TableBackgroundData::ShouldSetBCBorder()
{
/* we only need accurate border data when positioning background images*/
return mBackground && !(mBackground->mBackgroundFlags & NS_STYLE_BG_IMAGE_NONE);
}
nsresult
TableBackgroundPainter::TableBackgroundData::SetBCBorder(nsMargin& aBorder,
TableBackgroundPainter* aPainter)
{
NS_PRECONDITION(aPainter, "null painter");
if (!mSynthBorder) {
mSynthBorder = new (aPainter->mPresContext)
nsStyleBorder(aPainter->mZeroBorder);
if (!mSynthBorder) return NS_ERROR_OUT_OF_MEMORY;
}
nsStyleCoord coord(aBorder.top);
mSynthBorder->mBorder.SetTop(coord);
coord.SetCoordValue(aBorder.right);
mSynthBorder->mBorder.SetRight(coord);
coord.SetCoordValue(aBorder.bottom);
mSynthBorder->mBorder.SetBottom(coord);
coord.SetCoordValue(aBorder.left);
mSynthBorder->mBorder.SetLeft(coord);
mSynthBorder->RecalcData();
mBorder = mSynthBorder;
return NS_OK;
}
TableBackgroundPainter::TableBackgroundPainter(nsTableFrame* aTableFrame,
Origin aOrigin,
nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect)
: mPresContext(aPresContext),
mRenderingContext(aRenderingContext),
mDirtyRect(aDirtyRect),
mOrigin(aOrigin),
mCols(nsnull),
mZeroBorder(aPresContext)
{
MOZ_COUNT_CTOR(TableBackgroundPainter);
mZeroBorder.SetBorderStyle(NS_SIDE_TOP, NS_STYLE_BORDER_STYLE_SOLID);
mZeroBorder.SetBorderStyle(NS_SIDE_RIGHT, NS_STYLE_BORDER_STYLE_SOLID);
mZeroBorder.SetBorderStyle(NS_SIDE_BOTTOM, NS_STYLE_BORDER_STYLE_SOLID);
mZeroBorder.SetBorderStyle(NS_SIDE_LEFT, NS_STYLE_BORDER_STYLE_SOLID);
nsStyleCoord coord(0);
mZeroBorder.mBorder.SetTop(coord);
mZeroBorder.mBorder.SetRight(coord);
mZeroBorder.mBorder.SetBottom(coord);
mZeroBorder.mBorder.SetLeft(coord);
mZeroBorder.RecalcData();
mZeroPadding.RecalcData();
mPresContext->GetScaledPixelsToTwips(&mP2t);
mIsBorderCollapse = aTableFrame->IsBorderCollapse();
#ifdef DEBUG
mCompatMode = mPresContext->CompatibilityMode();
#endif
mNumCols = aTableFrame->GetColCount();
}
TableBackgroundPainter::~TableBackgroundPainter()
{
if (mCols) {
TableBackgroundData* lastColGroup = nsnull;
for (PRUint32 i = 0; i < mNumCols; i++) {
if (mCols[i].mColGroup != lastColGroup) {
lastColGroup = mCols[i].mColGroup;
lastColGroup->Destroy(mPresContext);
delete lastColGroup;
}
mCols[i].mColGroup = nsnull;
mCols[i].mCol.Destroy(mPresContext);
}
delete [] mCols;
}
mRowGroup.Destroy(mPresContext);
mRow.Destroy(mPresContext);
MOZ_COUNT_DTOR(TableBackgroundPainter);
}
nsresult
TableBackgroundPainter::PaintTableFrame(nsTableFrame* aTableFrame,
nsTableRowGroupFrame* aFirstRowGroup,
nsTableRowGroupFrame* aLastRowGroup,
nsMargin* aDeflate)
{
NS_PRECONDITION(aTableFrame, "null frame");
TableBackgroundData tableData;
tableData.SetFull(mPresContext, mRenderingContext, aTableFrame);
tableData.mRect.MoveTo(0,0); //using table's coords
if (aDeflate) {
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(mP2t, tempBorder);
}
border.right = tempBorder.right;
aLastRowGroup->GetContinuousBCBorderWidth(mP2t, tempBorder);
border.bottom = tempBorder.bottom;
nsTableRowFrame* rowFrame = aFirstRowGroup->GetFirstRow();
if (rowFrame) {
rowFrame->GetContinuousBCBorderWidth(mP2t, tempBorder);
border.top = tempBorder.top;
}
border.left = aTableFrame->GetContinuousLeftBCBorderWidth(mP2t);
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,
*tableData.mBackground,
*tableData.mBorder,
mZeroPadding, PR_TRUE);
}
tableData.Destroy(mPresContext);
return NS_OK;
}
void
TableBackgroundPainter::TranslateContext(nscoord aDX,
nscoord aDY)
{
mRenderingContext.Translate(aDX, aDY);
mDirtyRect.MoveBy(-aDX, -aDY);
if (mCols) {
TableBackgroundData* lastColGroup = nsnull;
for (PRUint32 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");
mCols[i].mColGroup->mRect.MoveBy(-aDX, -aDY);
lastColGroup = mCols[i].mColGroup;
}
}
}
}
nsresult
TableBackgroundPainter::QuirksPaintTable(nsTableFrame* aTableFrame,
nsMargin& aDeflate)
{
NS_PRECONDITION(aTableFrame, "null table frame");
NS_PRECONDITION(eCompatibility_NavQuirks == mCompatMode,
"QuirksPaintTable called for non-Quirks");
nsVoidArray rowGroups;
PRUint32 numRowGroups;
aTableFrame->OrderRowGroups(rowGroups, numRowGroups);
if (numRowGroups < 1) { //degenerate case
PaintTableFrame(aTableFrame,nsnull, nsnull, &aDeflate);
/* No cells; nothing else to paint */
return NS_OK;
}
PaintTableFrame(aTableFrame,
aTableFrame->GetRowGroupFrame(NS_STATIC_CAST(nsIFrame*, rowGroups.ElementAt(0))),
aTableFrame->GetRowGroupFrame(NS_STATIC_CAST(nsIFrame*, rowGroups.ElementAt(numRowGroups - 1))),
&aDeflate);
if (mIsBorderCollapse) {
/* This is a simple pass, so we'll just keep with the table coord system. */
for (PRUint32 i = 0; i < numRowGroups; i++) {
nsTableRowGroupFrame* rg = aTableFrame->GetRowGroupFrame(NS_STATIC_CAST(nsIFrame*, rowGroups.ElementAt(i)));
nsRect rgRect = rg->GetRect();
if (rgRect.Intersects(mDirtyRect) && !rg->HasView()) {
for (nsTableRowFrame* row = rg->GetFirstRow(); row; row = row->GetNextRow()) {
nsRect rowRect = row->GetRect();
rowRect.MoveBy(rgRect.x, rgRect.y);
if (mDirtyRect.YMost() > rowRect.y && //Intersect won't handle rowspans
!row->HasView()) {
for (nsTableCellFrame* cell = row->GetFirstCell(); cell; cell = cell->GetNextCell()) {
mCellRect = cell->GetRect();
mCellRect.MoveBy(rowRect.x, rowRect.y);
if (mCellRect.Intersects(mDirtyRect) && !cell->HasView()) {
nsresult rv = PaintCell(cell, PR_FALSE);
if (NS_FAILED(rv)) return rv;
}
}
}
}
}
}
}
return NS_OK;
}
nsresult
TableBackgroundPainter::PaintTable(nsTableFrame* aTableFrame)
{
NS_PRECONDITION(aTableFrame, "null table frame");
NS_PRECONDITION(eCompatibility_NavQuirks != mCompatMode,
"must call QuirksPaintTable in Quirks mode, not PaintTable");
nsVoidArray rowGroups;
PRUint32 numRowGroups;
aTableFrame->OrderRowGroups(rowGroups, numRowGroups);
if (numRowGroups < 1) { //degenerate case
PaintTableFrame(aTableFrame,nsnull, nsnull, nsnull);
/* No cells; nothing else to paint */
return NS_OK;
}
PaintTableFrame(aTableFrame,
aTableFrame->GetRowGroupFrame(NS_STATIC_CAST(nsIFrame*, rowGroups.ElementAt(0))),
aTableFrame->GetRowGroupFrame(NS_STATIC_CAST(nsIFrame*, rowGroups.ElementAt(numRowGroups - 1))),
nsnull);
/*Set up column background/border data*/
if (mNumCols > 0) {
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 = nsnull;
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(mP2t);
for (nsTableColGroupFrame* cgFrame = NS_STATIC_CAST(nsTableColGroupFrame*, colGroupList.FirstChild());
cgFrame; cgFrame = NS_STATIC_CAST(nsTableColGroupFrame*, cgFrame->GetNextSibling())) {
if (cgFrame->GetColCount() < 1) {
//No columns, no cells, so no need for data
continue;
}
/*Create data struct for column group*/
cgData = new TableBackgroundData;
if (!cgData) return NS_ERROR_OUT_OF_MEMORY;
cgData->SetFull(mPresContext, mRenderingContext, cgFrame);
if (mIsBorderCollapse && cgData->ShouldSetBCBorder()) {
border.left = lastLeftBorder;
cgFrame->GetContinuousBCBorderWidth(mP2t, border);
nsresult rv = cgData->SetBCBorder(border, this);
if (NS_FAILED(rv)) {
cgData->Destroy(mPresContext);
delete cgData;
return rv;
}
}
/*Loop over columns in this colgroup*/
if (cgData->IsVisible()) {
for (nsTableColFrame* col = cgFrame->GetFirstColumn(); col;
col = NS_STATIC_CAST(nsTableColFrame*, col->GetNextSibling())) {
/*Create data struct for column*/
PRUint32 colIndex = col->GetColIndex();
mCols[colIndex].mCol.SetFull(mPresContext, mRenderingContext, col);
//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;
if (mIsBorderCollapse) {
border.left = lastLeftBorder;
lastLeftBorder = col->GetContinuousBCBorderWidth(mP2t, border);
if (mCols[colIndex].mCol.ShouldSetBCBorder()) {
nsresult rv = mCols[colIndex].mCol.SetBCBorder(border, this);
if (NS_FAILED(rv)) return rv;
}
mCols[colIndex].mCol.mBorder->GetBorder(border);
}
}
}
}
}
for (PRUint32 i = 0; i < numRowGroups; i++) {
nsTableRowGroupFrame* rg = nsTableFrame::GetRowGroupFrame(NS_STATIC_CAST(nsIFrame*, rowGroups.ElementAt(i)));
nsRect rgRect = rg->GetRect();
if (rgRect.Intersects(mDirtyRect)) {
nsresult rv = PaintRowGroup(rg, rg->HasView());
if (NS_FAILED(rv)) return rv;
}
}
return NS_OK;
}
nsresult
TableBackgroundPainter::PaintRowGroup(nsTableRowGroupFrame* aFrame,
PRBool aPassThrough)
{
NS_PRECONDITION(aFrame, "null frame");
NS_PRECONDITION(eCompatibility_NavQuirks != mCompatMode,
"must not call PaintRowGroup in Quirks mode");
nsTableRowFrame* firstRow = aFrame->GetFirstRow();
/* Load row group data */
if (!aPassThrough) {
mRowGroup.SetFull(mPresContext, mRenderingContext, aFrame);
if (mIsBorderCollapse && mRowGroup.ShouldSetBCBorder()) {
nsMargin border;
if (firstRow) {
//pick up first row's top border (= rg top border)
firstRow->GetContinuousBCBorderWidth(mP2t, border);
/* (row group doesn't store its top border) */
}
//overwrite sides+bottom borders with rg's own
aFrame->GetContinuousBCBorderWidth(mP2t, border);
nsresult res = mRowGroup.SetBCBorder(border, this);
if (!NS_SUCCEEDED(res)) {
return res;
}
}
aPassThrough = !mRowGroup.IsVisible();
}
else {
mRowGroup.SetFrame(aFrame);
}
/* translate everything into row group coord system*/
if (eOrigin_TableRowGroup != mOrigin) {
TranslateContext(mRowGroup.mRect.x, mRowGroup.mRect.y);
}
nsRect rgRect = mRowGroup.mRect;
mRowGroup.mRect.MoveTo(0, 0);
/* paint */
for (nsTableRowFrame* row = firstRow; row; row = row->GetNextRow()) {
nsRect rect = row->GetRect();
if (mDirtyRect.YMost() >= rect.y) { //Intersect wouldn't handle rowspans
nsresult rv = PaintRow(row, aPassThrough || row->HasView());
if (NS_FAILED(rv)) return rv;
}
}
/* translate back into table coord system */
if (eOrigin_TableRowGroup != mOrigin) {
TranslateContext(-rgRect.x, -rgRect.y);
}
/* unload rg data */
mRowGroup.Clear();
return NS_OK;
}
nsresult
TableBackgroundPainter::PaintRow(nsTableRowFrame* aFrame,
PRBool aPassThrough)
{
NS_PRECONDITION(aFrame, "null frame");
NS_PRECONDITION(eCompatibility_NavQuirks != mCompatMode,
"must not call PaintRow in Quirks mode");
/* Load row data */
if (!aPassThrough) {
mRow.SetFull(mPresContext, mRenderingContext, aFrame);
if (mIsBorderCollapse && mRow.ShouldSetBCBorder()) {
nsMargin border;
nsTableRowFrame* nextRow = aFrame->GetNextRow();
if (nextRow) { //outer top below us is inner bottom for us
border.bottom = nextRow->GetOuterTopContBCBorderWidth(mP2t);
}
else { //acquire rg's bottom border
nsTableRowGroupFrame* rowGroup = NS_STATIC_CAST(nsTableRowGroupFrame*, aFrame->GetParent());
rowGroup->GetContinuousBCBorderWidth(mP2t, border);
}
//get the rest of the borders; will overwrite all but bottom
aFrame->GetContinuousBCBorderWidth(mP2t, border);
nsresult res = mRow.SetBCBorder(border, this);
if (!NS_SUCCEEDED(res)) {
return res;
}
}
aPassThrough = !mRow.IsVisible();
}
else {
mRow.SetFrame(aFrame);
}
/* Translate */
if (eOrigin_TableRow == mOrigin) {
/* If we originate from the row, then make the row the origin. */
mRow.mRect.MoveTo(0, 0);
}
//else: Use row group's coord system -> no translation necessary
for (nsTableCellFrame* cell = aFrame->GetFirstCell(); cell; cell = cell->GetNextCell()) {
mCellRect = cell->GetRect();
//Translate to use the same coord system as mRow.
mCellRect.MoveBy(mRow.mRect.x, mRow.mRect.y);
if (mCellRect.Intersects(mDirtyRect)) {
nsresult rv = PaintCell(cell, aPassThrough || cell->HasView());
if (NS_FAILED(rv)) return rv;
}
}
/* Unload row data */
mRow.Clear();
return NS_OK;
}
nsresult
TableBackgroundPainter::PaintCell(nsTableCellFrame* aCell,
PRBool aPassSelf)
{
NS_PRECONDITION(aCell, "null frame");
const nsStyleTableBorder* cellTableStyle;
cellTableStyle = aCell->GetStyleTableBorder();
if (!(NS_STYLE_TABLE_EMPTY_CELLS_SHOW == cellTableStyle->mEmptyCells ||
NS_STYLE_TABLE_EMPTY_CELLS_SHOW_BACKGROUND == cellTableStyle->mEmptyCells)
&& aCell->GetContentEmpty()) {
return NS_OK;
}
PRInt32 colIndex;
aCell->GetColIndex(colIndex);
//Paint column group background
if (mCols && mCols[colIndex].mColGroup && mCols[colIndex].mColGroup->IsVisible()) {
nsCSSRendering::PaintBackgroundWithSC(mPresContext, mRenderingContext,
mCols[colIndex].mColGroup->mFrame, mDirtyRect,
mCols[colIndex].mColGroup->mRect,
*mCols[colIndex].mColGroup->mBackground,
*mCols[colIndex].mColGroup->mBorder,
mZeroPadding, PR_TRUE, &mCellRect);
}
//Paint column background
if (mCols && mCols[colIndex].mCol.IsVisible()) {
nsCSSRendering::PaintBackgroundWithSC(mPresContext, mRenderingContext,
mCols[colIndex].mCol.mFrame, mDirtyRect,
mCols[colIndex].mCol.mRect,
*mCols[colIndex].mCol.mBackground,
*mCols[colIndex].mCol.mBorder,
mZeroPadding, PR_TRUE, &mCellRect);
}
//Paint row group background
if (mRowGroup.IsVisible()) {
nsCSSRendering::PaintBackgroundWithSC(mPresContext, mRenderingContext,
mRowGroup.mFrame, mDirtyRect, mRowGroup.mRect,
*mRowGroup.mBackground, *mRowGroup.mBorder,
mZeroPadding, PR_TRUE, &mCellRect);
}
//Paint row background
if (mRow.IsVisible()) {
nsCSSRendering::PaintBackgroundWithSC(mPresContext, mRenderingContext,
mRow.mFrame, mDirtyRect, mRow.mRect,
*mRow.mBackground, *mRow.mBorder,
mZeroPadding, PR_TRUE, &mCellRect);
}
//Paint cell background in border-collapse unless we're just passing
if (mIsBorderCollapse && !aPassSelf) {
mRenderingContext.PushState();
mRenderingContext.Translate(mCellRect.x, mCellRect.y);
mDirtyRect.MoveBy(-mCellRect.x, -mCellRect.y);
aCell->Paint(mPresContext, mRenderingContext, mDirtyRect,
NS_FRAME_PAINT_LAYER_BACKGROUND,
NS_PAINT_FLAG_TABLE_BG_PAINT | NS_PAINT_FLAG_TABLE_CELL_BG_PASS);
mDirtyRect.MoveBy(mCellRect.x, mCellRect.y);
PRBool clipEmpty;
mRenderingContext.PopState(clipEmpty);
}
return NS_OK;
}

View File

@ -0,0 +1,271 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is TableBackgroundPainter interface.
*
* The Initial Developer of the Original Code is
* Elika J. Etemad ("fantasai") <fantasai@inkedblade.net>.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsTablePainter_h__
#define nsTablePainter_h__
typedef PRUint8 BCPixelSize;
#define BC_BORDER_TOP_HALF_COORD(p2t,px) NSToCoordRound(((px) - (px) / 2) * (p2t) )
#define BC_BORDER_RIGHT_HALF_COORD(p2t,px) NSToCoordRound(( (px) / 2) * (p2t) )
#define BC_BORDER_BOTTOM_HALF_COORD(p2t,px) NSToCoordRound(( (px) / 2) * (p2t) )
#define BC_BORDER_LEFT_HALF_COORD(p2t,px) NSToCoordRound(((px) - (px) / 2) * (p2t) )
#define BC_BORDER_TOP_HALF(px) ((px) - (px) / 2)
#define BC_BORDER_RIGHT_HALF(px) ((px) / 2)
#define BC_BORDER_BOTTOM_HALF(px) ((px) / 2)
#define BC_BORDER_LEFT_HALF(px) ((px) - (px) / 2)
// flags for Paint, PaintChild, PaintChildren are currently only used by tables.
//Table-based paint call; not a direct call as with views
#define NS_PAINT_FLAG_TABLE_BG_PAINT 0x00000001
//Cells should paint their backgrounds only, no children
#define NS_PAINT_FLAG_TABLE_CELL_BG_PASS 0x00000002
#include "nsIFrame.h"
class nsTableFrame;
class nsTableRowGroupFrame;
class nsTableRowFrame;
class nsTableCellFrame;
class TableBackgroundPainter
{
/*
* Helper class for painting table backgrounds
*
*/
public:
enum Origin { eOrigin_Table, eOrigin_TableRowGroup, eOrigin_TableRow };
/** Public constructor
* @param aTableFrame - the table's table frame
* @param aOrigin - what type of table frame is creating this instance
* @param aPresContext - the presentation context
* @param aRenderingContext - the rendering context
* @param aDirtyRect - the area that needs to be painted
*/
TableBackgroundPainter(nsTableFrame* aTableFrame,
Origin aOrigin,
nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect);
/** Destructor */
~TableBackgroundPainter();
/* ~*~ The Border Collapse Painting Issue ~*~
In border-collapse, the *table* paints the cells' borders,
so we need to make sure the backgrounds get painted first
(underneath) by doing a cell-background-only painting pass.
This happens in both Standards and Quirks mode PaintTable
calls.
The table must then do a no-cell-background pass that
continues as a normal background paint call in the cell
descendants.) This method doesn't handle views very well, but
then, nothing about BC table painting really does.
*/
/* ~*~ Using Standards Mode Painting ~*~
A call to PaintTable will normally paint all of the table's
elements (except the cells in non-BC). Elements with views
however, will be skipped and must create their own painter
to call the appropriate paint function in their ::Paint
method (e.g. painter.PaintRow in nsTableRow::Paint)
*/
/** Paint background for the table frame and its children down through cells
* (Cells themselves will only be painted in border collapse)
* Standards mode only
* Table must do a flagged TABLE_BG_PAINT ::Paint call on its
* children afterwards
* @param aTableFrame - the table frame
*/
nsresult PaintTable(nsTableFrame* aTableFrame);
/** Paint background for the row group and its children down through cells
* (Cells themselves will only be painted in border collapse)
* Standards mode only
* Table Row Group must do a flagged TABLE_BG_PAINT ::Paint call on its
* children afterwards
* @param aFrame - the table row group frame
*/
nsresult PaintRowGroup(nsTableRowGroupFrame* aFrame)
{ return PaintRowGroup(aFrame, PR_FALSE); }
/** Paint background for the row and its children down through cells
* (Cells themselves will only be painted in border collapse)
* Standards mode only
* Table Row must do a flagged TABLE_BG_PAINT ::Paint call on its
* children afterwards
* @param aFrame - the table row frame
*/
nsresult PaintRow(nsTableRowFrame* aFrame)
{ return PaintRow(aFrame, PR_FALSE); }
/** Paint table's background, Quirks mode only
* Cell backgrounds will also be painted in border collapse:
* Table must do a flagged TABLE_BG_PAINT on its children
* afterwards.
* @param aTableFrame - the table frame
* @param aDeflate - deflation needed to bring table's mRect
* to the outer grid lines in border-collapse
*/
nsresult QuirksPaintTable(nsTableFrame* aTableFrame,
nsMargin& aDeflate);
private:
/** Paint table frame's background
* @param aTableFrame - the table frame
* @param aFirstRowGroup - the first (in layout order) row group
* may be null
* @param aLastRowGroup - the last (in layout order) row group
* may be null
* @param aDeflate - adjustment to frame's rect (used for quirks BC)
* may be null
*/
nsresult PaintTableFrame(nsTableFrame* aTableFrame,
nsTableRowGroupFrame* aFirstRowGroup,
nsTableRowGroupFrame* aLastRowGroup,
nsMargin* aDeflate = nsnull);
/* aPassThrough params indicate whether to paint the element or to just
* pass through and paint underlying layers only
* See Public versions for function descriptions
*/
nsresult PaintRowGroup(nsTableRowGroupFrame* aFrame,
PRBool aPassThrough);
nsresult PaintRow(nsTableRowFrame* aFrame,
PRBool aPassThrough);
/** Paint table background layers for this cell space
* Also paints cell's own background in border-collapse mode
* @param aFrame - the cell
* @param aPassSelf - pass this cell; i.e. paint only underlying layers
*/
nsresult PaintCell(nsTableCellFrame* aFrame,
PRBool aPassSelf);
/** Translate mRenderingContext, mDirtyRect, and mCols' column and
* colgroup coords
* @param aDX - origin's x-coord change
* @param aDY - origin's y-coord change
*/
void TranslateContext(nscoord aDX,
nscoord aDY);
struct TableBackgroundData;
friend struct TableBackgroundData;
MOZ_DECL_CTOR_COUNTER(TableBackgroundData)
struct TableBackgroundData {
nsIFrame* mFrame;
nsRect mRect;
const nsStyleBackground* mBackground;
const nsStyleBorder* mBorder;
/** Data is valid & frame is visible */
PRBool IsVisible() const { return mBackground != nsnull; }
/** Constructor */
TableBackgroundData();
/** Destructor */
~TableBackgroundData();
/** Destroys synthesized data. MUST be called before destructor
* @param aPresContext - the pres context
*/
void Destroy(nsIPresContext* aPresContext);
/** Clear background data */
void Clear();
/** Calculate and set all data values to represent aFrame */
void SetFull(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
nsIFrame* aFrame);
/** Set frame data (mFrame, mRect) but leave style data empty */
void SetFrame(nsIFrame* aFrame);
/** True if need to set border-collapse border; must call SetFull beforehand */
PRBool ShouldSetBCBorder();
/** Set border-collapse border with aBorderWidth as widths */
nsresult SetBCBorder(nsMargin& aBorderWidth,
TableBackgroundPainter* aPainter);
private:
nsStyleBorder* mSynthBorder;
};
struct ColData {
TableBackgroundData mCol;
TableBackgroundData* mColGroup; //link to col's parent colgroup's data (owned by painter)
ColData() {
mColGroup = nsnull;
}
};
nsIPresContext* mPresContext;
nsIRenderingContext& mRenderingContext;
nsRect mDirtyRect;
#ifdef DEBUG
nsCompatibility mCompatMode;
#endif
PRBool mIsBorderCollapse;
Origin mOrigin; //user's table frame type
ColData* mCols; //array of columns' ColData
PRUint32 mNumCols;
TableBackgroundData mRowGroup; //current row group
TableBackgroundData mRow; //current row
nsRect mCellRect; //current cell's rect
nsStyleBorder mZeroBorder; //cached zero-width border
nsStylePadding mZeroPadding; //cached zero-width padding
float mP2t; //pixels to twips
};
MOZ_DECL_CTOR_COUNTER(TableBackgroundPainter)
#endif

View File

@ -538,7 +538,25 @@ NS_METHOD nsTableRowFrame::Paint(nsIPresContext* aPresContext,
aRenderingContext.DrawRect(0, 0, mRect.width, mRect.height);
}
#endif
// Standards mode background painting removed. See bug 4510
if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer &&
//direct (not table-called) background paint
!(aFlags & (NS_PAINT_FLAG_TABLE_BG_PAINT | NS_PAINT_FLAG_TABLE_CELL_BG_PASS))) {
//Quirks inherits bg into cells & paints them there
if (eCompatibility_NavQuirks != aPresContext->CompatibilityMode()) {
nsTableFrame* tableFrame;
nsTableFrame::GetTableFrame(this, tableFrame);
NS_ASSERTION(tableFrame, "null table frame");
TableBackgroundPainter painter(tableFrame,
TableBackgroundPainter::eOrigin_TableRow,
aPresContext, aRenderingContext,
aDirtyRect);
nsresult rv = painter.PaintRow(this);
if (NS_FAILED(rv)) return rv;
aFlags |= NS_PAINT_FLAG_TABLE_BG_PAINT;
}
}
PRUint8 overflow = GetStyleDisplay()->mOverflow;
PRBool clip = overflow == NS_STYLE_OVERFLOW_HIDDEN ||
@ -547,7 +565,8 @@ NS_METHOD nsTableRowFrame::Paint(nsIPresContext* aPresContext,
aRenderingContext.PushState();
SetOverflowClipRect(aRenderingContext);
}
PaintChildren(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer, aFlags);
PaintChildren(aPresContext, aRenderingContext, aDirtyRect,
aWhichLayer, aFlags);
if (clip) {
PRBool clipState;
aRenderingContext.PopState(clipState);
@ -862,8 +881,7 @@ nsTableRowFrame::ReflowChildren(nsIPresContext* aPresContext,
PRInt32 cellColIndex;
cellFrame->GetColIndex(cellColIndex);
cellColSpan = aTableFrame.GetEffectiveColSpan(*cellFrame);
x += cellSpacingX;
// If the adjacent cell is in a prior row (because of a rowspan) add in the space
if ((iter.IsLeftToRight() && (prevColIndex != (cellColIndex - 1))) ||
(!iter.IsLeftToRight() && (prevColIndex != cellColIndex + cellColSpan))) {
@ -1034,10 +1052,7 @@ nsTableRowFrame::ReflowChildren(nsIPresContext* aPresContext,
}
ConsiderChildOverflow(aPresContext, aDesiredSize.mOverflowArea, kidFrame);
kidFrame = iter.Next(); // Get the next child
// if this was the last child, and it had a colspan>1, add in the cellSpacing for the colspan
// if the last kid wasn't a colspan, then we still have the colspan of the last real cell
if (!kidFrame && (cellColSpan > 1))
x += cellSpacingX;
x += cellSpacingX;
}
// just set our width to what was available. The table will calculate the width and not use our value.
@ -1524,6 +1539,24 @@ nsTableRowFrame::GetUnpaginatedHeight(nsIPresContext* aPresContext)
return 0;
}
void nsTableRowFrame::SetContinuousBCBorderWidth(PRUint8 aForSide,
BCPixelSize aPixelValue)
{
switch (aForSide) {
case NS_SIDE_RIGHT:
mRightContBorderWidth = aPixelValue;
return;
case NS_SIDE_TOP:
mTopContBorderWidth = aPixelValue;
return;
case NS_SIDE_LEFT:
mLeftContBorderWidth = aPixelValue;
return;
default:
NS_ERROR("invalid NS_SIDE arg");
}
}
/* ----- global methods ----- */
nsresult

View File

@ -39,6 +39,7 @@
#include "nscore.h"
#include "nsHTMLContainerFrame.h"
#include "nsTablePainter.h"
class nsTableFrame;
class nsTableCellFrame;
@ -226,11 +227,31 @@ public:
void SetUnpaginatedHeight(nsIPresContext* aPresContext, nscoord aValue);
nscoord GetTopBCBorderWidth(float* aPixelsToTwips = nsnull);
void SetTopBCBorderWidth(nscoord aWidth);
void SetTopBCBorderWidth(BCPixelSize aWidth);
nscoord GetBottomBCBorderWidth(float* aPixelsToTwips = nsnull);
void SetBottomBCBorderWidth(nscoord aWidth);
void SetBottomBCBorderWidth(BCPixelSize aWidth);
nsMargin* GetBCBorderWidth(float aPixelsToTwips,
nsMargin& aBorder);
/**
* Gets inner border widths before collapsing with cell borders
* Caller must get bottom border from next row or from table
* GetContinuousBCBorderWidth will not overwrite aBorder.bottom
* see nsTablePainter about continuous borders
*/
void GetContinuousBCBorderWidth(float aPixelsToTwips,
nsMargin& aBorder);
/**
* @returns outer top bc border == prev row's bottom inner
*/
nscoord GetOuterTopContBCBorderWidth(float aPixelsToTwips);
/**
* Sets full border widths before collapsing with cell borders
* @param aForSide - side to set; only accepts right, left, and top
*/
void SetContinuousBCBorderWidth(PRUint8 aForSide,
BCPixelSize aPixelValue);
protected:
/** protected constructor.
@ -238,7 +259,7 @@ protected:
*/
nsTableRowFrame();
void InitChildReflowState(nsIPresContext& aPresContext,
void InitChildReflowState(nsIPresContext& aPresContext,
const nsSize& aAvailSize,
PRBool aBorderCollapse,
float aPixelsToTwips,
@ -318,8 +339,11 @@ private:
nscoord mMaxCellDescent; // does *not* include cells with rowspan > 1
// border widths in pixels in the collapsing border model
unsigned mTopBorderWidth:8;
unsigned mBottomBorderWidth:8;
BCPixelSize mTopBorderWidth;
BCPixelSize mBottomBorderWidth;
BCPixelSize mRightContBorderWidth;
BCPixelSize mTopContBorderWidth;
BCPixelSize mLeftContBorderWidth;
#ifdef DEBUG_TABLE_REFLOW_TIMING
public:
@ -433,7 +457,7 @@ inline nscoord nsTableRowFrame::GetTopBCBorderWidth(float* aPixelsToTwips)
return width;
}
inline void nsTableRowFrame::SetTopBCBorderWidth(nscoord aWidth)
inline void nsTableRowFrame::SetTopBCBorderWidth(BCPixelSize aWidth)
{
mTopBorderWidth = aWidth;
}
@ -444,7 +468,7 @@ inline nscoord nsTableRowFrame::GetBottomBCBorderWidth(float* aPixelsToTwips)
return width;
}
inline void nsTableRowFrame::SetBottomBCBorderWidth(nscoord aWidth)
inline void nsTableRowFrame::SetBottomBCBorderWidth(BCPixelSize aWidth)
{
mBottomBorderWidth = aWidth;
}
@ -460,4 +484,21 @@ inline nsMargin* nsTableRowFrame::GetBCBorderWidth(float aPixelsToTwips,
return &aBorder;
}
inline void
nsTableRowFrame::GetContinuousBCBorderWidth(float aPixelsToTwips,
nsMargin& aBorder)
{
aBorder.right = BC_BORDER_LEFT_HALF_COORD(aPixelsToTwips,
mLeftContBorderWidth);
aBorder.top = BC_BORDER_BOTTOM_HALF_COORD(aPixelsToTwips,
mTopContBorderWidth);
aBorder.left = BC_BORDER_RIGHT_HALF_COORD(aPixelsToTwips,
mRightContBorderWidth);
}
inline nscoord nsTableRowFrame::GetOuterTopContBCBorderWidth(float aPixelsToTwips)
{
return BC_BORDER_TOP_HALF_COORD(aPixelsToTwips, mTopContBorderWidth);
}
#endif

View File

@ -94,7 +94,7 @@ nsTableRowGroupFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr)
*aInstancePtr = (void*)this;
return NS_OK;
}
else if (aIID.Equals(NS_GET_IID(nsILineIteratorNavigator)))
else if (aIID.Equals(NS_GET_IID(nsILineIteratorNavigator)))
{ // note there is no addref here, frames are not addref'd
*aInstancePtr = (void*)(nsILineIteratorNavigator*)this;
return NS_OK;
@ -204,7 +204,25 @@ NS_METHOD nsTableRowGroupFrame::Paint(nsIPresContext* aPresContext,
aRenderingContext.DrawRect(0, 0, mRect.width, mRect.height);
}
#endif
// Standards mode background painting removed. See bug 4510
if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer &&
//direct (not table-called) background paint
!(aFlags & (NS_PAINT_FLAG_TABLE_BG_PAINT | NS_PAINT_FLAG_TABLE_CELL_BG_PASS))) {
//Quirks inherits bg into cells & paints them there
if (eCompatibility_NavQuirks != aPresContext->CompatibilityMode()) {
nsTableFrame* tableFrame;
nsTableFrame::GetTableFrame(this, tableFrame);
NS_ASSERTION(tableFrame, "null table frame");
TableBackgroundPainter painter(tableFrame,
TableBackgroundPainter::eOrigin_TableRowGroup,
aPresContext, aRenderingContext,
aDirtyRect);
nsresult rv = painter.PaintRowGroup(this);
if (NS_FAILED(rv)) return rv;
aFlags |= NS_PAINT_FLAG_TABLE_BG_PAINT;
}
}
PRUint8 overflow = GetStyleDisplay()->mOverflow;
PRBool clip = overflow == NS_STYLE_OVERFLOW_HIDDEN ||
@ -213,7 +231,8 @@ NS_METHOD nsTableRowGroupFrame::Paint(nsIPresContext* aPresContext,
aRenderingContext.PushState();
SetOverflowClipRect(aRenderingContext);
}
PaintChildren(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer, aFlags);
PaintChildren(aPresContext, aRenderingContext, aDirtyRect,
aWhichLayer, aFlags);
if (clip) {
PRBool clipState;
aRenderingContext.PopState(clipState);
@ -286,9 +305,9 @@ nsTableRowGroupFrame::GetFrameForPoint(nsIPresContext* aPresContext,
// aKidRect is relative to the upper-left origin of our frame
void
nsTableRowGroupFrame::PlaceChild(nsIPresContext* aPresContext,
nsRowGroupReflowState& aReflowState,
nsIFrame* aKidFrame,
nsHTMLReflowMetrics& aDesiredSize)
nsRowGroupReflowState& aReflowState,
nsIFrame* aKidFrame,
nsHTMLReflowMetrics& aDesiredSize)
{
// Place and size the child
FinishReflowChild(aKidFrame, aPresContext, nsnull, aDesiredSize, 0, aReflowState.y, 0);
@ -1854,6 +1873,24 @@ nsTableRowGroupFrame::GetBCBorderWidth(float aPixelsToTwips,
return &aBorder;
}
void nsTableRowGroupFrame::SetContinuousBCBorderWidth(PRUint8 aForSide,
BCPixelSize aPixelValue)
{
switch (aForSide) {
case NS_SIDE_RIGHT:
mRightContBorderWidth = aPixelValue;
return;
case NS_SIDE_BOTTOM:
mBottomContBorderWidth = aPixelValue;
return;
case NS_SIDE_LEFT:
mLeftContBorderWidth = aPixelValue;
return;
default:
NS_ERROR("invalid NS_SIDE argument");
}
}
//nsILineIterator methods for nsTableFrame
NS_IMETHODIMP
nsTableRowGroupFrame::GetNumLines(PRInt32* aResult)

View File

@ -41,6 +41,7 @@
#include "nsHTMLContainerFrame.h"
#include "nsIAtom.h"
#include "nsILineIterator.h"
#include "nsTablePainter.h"
class nsTableFrame;
class nsTableRowFrame;
@ -220,6 +221,22 @@ public:
nsMargin* GetBCBorderWidth(float aPixelsToTwips,
nsMargin& aBorder);
/**
* Gets inner border widths before collapsing with cell borders
* Caller must get top border from previous row group or from table
* GetContinuousBCBorderWidth will not overwrite aBorder.top
* see nsTablePainter about continuous borders
*/
void GetContinuousBCBorderWidth(float aPixelsToTwips,
nsMargin& aBorder);
/**
* Sets full border widths before collapsing with cell borders
* @param aForSide - side to set; only right, left, and bottom valid
*/
void SetContinuousBCBorderWidth(PRUint8 aForSide,
BCPixelSize aPixelValue);
// nsILineIterator methods
public:
NS_IMETHOD GetNumLines(PRInt32* aResult);
@ -359,6 +376,13 @@ protected:
void UndoContinuedRow(nsIPresContext* aPresContext,
nsTableRowFrame* aRow);
private:
// border widths in pixels in the collapsing border model
BCPixelSize mRightContBorderWidth;
BCPixelSize mBottomContBorderWidth;
BCPixelSize mLeftContBorderWidth;
public:
virtual nsIFrame* GetFirstFrame() { return mFrames.FirstChild(); };
virtual nsIFrame* GetLastFrame() { return mFrames.LastChild(); };
@ -419,4 +443,17 @@ inline void nsTableRowGroupFrame::SetHasStyleHeight(PRBool aValue)
mState &= ~NS_ROWGROUP_HAS_STYLE_HEIGHT;
}
}
inline void
nsTableRowGroupFrame::GetContinuousBCBorderWidth(float aPixelsToTwips,
nsMargin& aBorder)
{
aBorder.right = BC_BORDER_LEFT_HALF_COORD(aPixelsToTwips,
mRightContBorderWidth);
aBorder.bottom = BC_BORDER_TOP_HALF_COORD(aPixelsToTwips,
mBottomContBorderWidth);
aBorder.left = BC_BORDER_RIGHT_HALF_COORD(aPixelsToTwips,
mLeftContBorderWidth);
return;
}
#endif