bug 41262 - new table border collapsing code. sr=attinasi, r=alexsavulov.

This commit is contained in:
karnaze%netscape.com 2002-02-19 15:48:28 +00:00
parent b3d4a89ff5
commit 679c575202
67 changed files with 10162 additions and 1484 deletions

View File

@ -1412,39 +1412,44 @@ MapAttributesIntoRule(const nsIHTMLMappedAttributes* aAttributes,
nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
}
else if (aData->mSID == eStyleStruct_Border && aData->mMarginData) {
const nsStyleDisplay* readDisplay = (nsStyleDisplay*)
aData->mStyleContext->GetStyleData(eStyleStruct_Display);
if (!aData->mStyleContext) return;
const nsStyleTableBorder* tableStyle =
(const nsStyleTableBorder*)aData->mStyleContext->GetStyleData(eStyleStruct_TableBorder);
const nsStyleDisplay* readDisplay =
(nsStyleDisplay*) aData->mStyleContext->GetStyleData(eStyleStruct_Display);
if (readDisplay &&
(readDisplay->mDisplay == NS_STYLE_DISPLAY_TABLE_CELL)) {
// set the cell's border from the table
nsHTMLValue value;
aAttributes->GetAttribute(nsHTMLAtoms::border, value);
if (((value.GetUnit() == eHTMLUnit_Pixel) &&
(value.GetPixelValue() > 0)) ||
(value.GetUnit() == eHTMLUnit_Empty)) {
if (aData->mMarginData->mBorderWidth->mLeft.GetUnit() == eCSSUnit_Null)
aData->mMarginData->mBorderWidth->mLeft.SetFloatValue(1.0f, eCSSUnit_Pixel);
if (aData->mMarginData->mBorderWidth->mRight.GetUnit() == eCSSUnit_Null)
aData->mMarginData->mBorderWidth->mRight.SetFloatValue(1.0f, eCSSUnit_Pixel);
if (aData->mMarginData->mBorderWidth->mTop.GetUnit() == eCSSUnit_Null)
aData->mMarginData->mBorderWidth->mTop.SetFloatValue(1.0f, eCSSUnit_Pixel);
if (aData->mMarginData->mBorderWidth->mBottom.GetUnit() == eCSSUnit_Null)
aData->mMarginData->mBorderWidth->mBottom.SetFloatValue(1.0f, eCSSUnit_Pixel);
if (NS_STYLE_BORDER_SEPARATE == tableStyle->mBorderCollapse) {
// Set the cell's border from the table in the separate border model. If there is a border
// on the table, then the mapping to rules=all will take care of borders in the collapsing model.
nsHTMLValue value;
aAttributes->GetAttribute(nsHTMLAtoms::border, value);
if (((value.GetUnit() == eHTMLUnit_Pixel) &&
(value.GetPixelValue() > 0)) ||
(value.GetUnit() == eHTMLUnit_Empty)) {
if (aData->mMarginData->mBorderWidth->mLeft.GetUnit() == eCSSUnit_Null)
aData->mMarginData->mBorderWidth->mLeft.SetFloatValue(1.0f, eCSSUnit_Pixel);
if (aData->mMarginData->mBorderWidth->mRight.GetUnit() == eCSSUnit_Null)
aData->mMarginData->mBorderWidth->mRight.SetFloatValue(1.0f, eCSSUnit_Pixel);
if (aData->mMarginData->mBorderWidth->mTop.GetUnit() == eCSSUnit_Null)
aData->mMarginData->mBorderWidth->mTop.SetFloatValue(1.0f, eCSSUnit_Pixel);
if (aData->mMarginData->mBorderWidth->mBottom.GetUnit() == eCSSUnit_Null)
aData->mMarginData->mBorderWidth->mBottom.SetFloatValue(1.0f, eCSSUnit_Pixel);
PRUint8 borderStyle = (eCompatibility_NavQuirks == mode)
? NS_STYLE_BORDER_STYLE_BG_INSET : NS_STYLE_BORDER_STYLE_INSET;
PRUint8 borderStyle = (eCompatibility_NavQuirks == mode)
? NS_STYLE_BORDER_STYLE_BG_INSET : NS_STYLE_BORDER_STYLE_INSET;
// BG_INSET results in a border color based on background colors
// used for NavQuirks only...
if (aData->mMarginData->mBorderStyle->mLeft.GetUnit() == eCSSUnit_Null)
aData->mMarginData->mBorderStyle->mLeft.SetIntValue(borderStyle, eCSSUnit_Enumerated);
if (aData->mMarginData->mBorderStyle->mRight.GetUnit() == eCSSUnit_Null)
aData->mMarginData->mBorderStyle->mRight.SetIntValue(borderStyle, eCSSUnit_Enumerated);
if (aData->mMarginData->mBorderStyle->mTop.GetUnit() == eCSSUnit_Null)
aData->mMarginData->mBorderStyle->mTop.SetIntValue(borderStyle, eCSSUnit_Enumerated);
if (aData->mMarginData->mBorderStyle->mBottom.GetUnit() == eCSSUnit_Null)
aData->mMarginData->mBorderStyle->mBottom.SetIntValue(borderStyle, eCSSUnit_Enumerated);
if (aData->mMarginData->mBorderStyle->mLeft.GetUnit() == eCSSUnit_Null)
aData->mMarginData->mBorderStyle->mLeft.SetIntValue(borderStyle, eCSSUnit_Enumerated);
if (aData->mMarginData->mBorderStyle->mRight.GetUnit() == eCSSUnit_Null)
aData->mMarginData->mBorderStyle->mRight.SetIntValue(borderStyle, eCSSUnit_Enumerated);
if (aData->mMarginData->mBorderStyle->mTop.GetUnit() == eCSSUnit_Null)
aData->mMarginData->mBorderStyle->mTop.SetIntValue(borderStyle, eCSSUnit_Enumerated);
if (aData->mMarginData->mBorderStyle->mBottom.GetUnit() == eCSSUnit_Null)
aData->mMarginData->mBorderStyle->mBottom.SetIntValue(borderStyle, eCSSUnit_Enumerated);
}
}
}
else {
@ -1458,7 +1463,6 @@ MapAttributesIntoRule(const nsIHTMLMappedAttributes* aAttributes,
PRUint8 borderStyle = (eCompatibility_NavQuirks == mode)
? NS_STYLE_BORDER_STYLE_BG_OUTSET :
NS_STYLE_BORDER_STYLE_OUTSET;
// bordercolor
nsHTMLValue value;
aAttributes->GetAttribute(nsHTMLAtoms::bordercolor, value);
@ -1476,6 +1480,18 @@ MapAttributesIntoRule(const nsIHTMLMappedAttributes* aAttributes,
borderStyle = NS_STYLE_BORDER_STYLE_OUTSET; // use css outset
}
else if (NS_STYLE_BORDER_COLLAPSE == tableStyle->mBorderCollapse) {
// make the color grey
nscolor color = NS_RGB(80, 80, 80);
if (aData->mMarginData->mBorderColor->mLeft.GetUnit() == eCSSUnit_Null)
aData->mMarginData->mBorderColor->mLeft.SetColorValue(color);
if (aData->mMarginData->mBorderColor->mRight.GetUnit() == eCSSUnit_Null)
aData->mMarginData->mBorderColor->mRight.SetColorValue(color);
if (aData->mMarginData->mBorderColor->mTop.GetUnit() == eCSSUnit_Null)
aData->mMarginData->mBorderColor->mTop.SetColorValue(color);
if (aData->mMarginData->mBorderColor->mBottom.GetUnit() == eCSSUnit_Null)
aData->mMarginData->mBorderColor->mBottom.SetColorValue(color);
}
// border and frame
MapTableBorderInto(aAttributes, aData, borderStyle);
@ -1500,7 +1516,6 @@ nsHTMLTableElement::GetMappedAttributeImpact(const nsIAtom* aAttribute, PRInt32
(aAttribute == nsHTMLAtoms::cellpadding) ||
(aAttribute == nsHTMLAtoms::cellspacing) ||
(aAttribute == nsHTMLAtoms::cols) ||
(aAttribute == nsHTMLAtoms::rules) ||
(aAttribute == nsHTMLAtoms::border) ||
(aAttribute == nsHTMLAtoms::frame) ||
(aAttribute == nsHTMLAtoms::width) ||
@ -1512,7 +1527,10 @@ nsHTMLTableElement::GetMappedAttributeImpact(const nsIAtom* aAttribute, PRInt32
else if (aAttribute == nsHTMLAtoms::bordercolor) {
aHint = NS_STYLE_HINT_VISUAL;
}
else if (aAttribute == nsHTMLAtoms::align) {
else if ((aAttribute == nsHTMLAtoms::align) ||
(aAttribute == nsHTMLAtoms::rules)) {
// Changing to rules will force border-collapse. Unfortunately, if border-collapse was
// already in effect, then a frame change is not necessary.
aHint = NS_STYLE_HINT_FRAMECHANGE;
}
else if (!GetCommonMappedAttributesImpact(aAttribute, aHint)) {

View File

@ -475,6 +475,254 @@ TableTHRule::MapRuleInfoInto(nsRuleData* aRuleData)
return NS_OK;
}
static void
ProcessTableRulesAttribute(nsStyleStruct* aStyleStruct,
nsRuleData* aRuleData,
PRUint8 aSide,
PRBool aGroup,
PRUint8 aRulesArg1,
PRUint8 aRulesArg2,
PRUint8 aRulesArg3)
{
if (!aStyleStruct || !aRuleData || !aRuleData->mPresContext) return;
nsCOMPtr<nsIStyleContext> tableContext = getter_AddRefs(aRuleData->mStyleContext->GetParent()); if (!tableContext) return;
if (!aGroup) {
tableContext = getter_AddRefs(tableContext->GetParent()); if (!tableContext) return;
}
const nsStyleTable* tableData =
(const nsStyleTable*)tableContext->GetStyleData(eStyleStruct_Table);
if (tableData && ((aRulesArg1 == tableData->mRules) ||
(aRulesArg2 == tableData->mRules) ||
(aRulesArg3 == tableData->mRules))) {
const nsStyleBorder* tableBorderData =
(const nsStyleBorder*)tableContext->GetStyleData(eStyleStruct_Border); if (!tableBorderData) return;
PRUint8 tableBorderStyle = tableBorderData->GetBorderStyle(aSide);
nsStyleBorder* borderData = (nsStyleBorder*)aStyleStruct; if (!borderData) return;
PRUint8 borderStyle = borderData->GetBorderStyle(aSide);
// XXX It appears that the style system erronously applies the custom style rule after css style,
// consequently it does not properly fit into the casade. For now, assume that a border style of none
// implies that the style has not been set.
if (NS_STYLE_BORDER_STYLE_NONE == borderStyle) {
// use the table's border style if it is dashed or dotted, otherwise use solid
PRUint8 bStyle = ((NS_STYLE_BORDER_STYLE_NONE != tableBorderStyle) &&
(NS_STYLE_BORDER_STYLE_HIDDEN != tableBorderStyle))
? tableBorderStyle : NS_STYLE_BORDER_STYLE_SOLID;
if ((NS_STYLE_BORDER_STYLE_DASHED != bStyle) &&
(NS_STYLE_BORDER_STYLE_DOTTED != bStyle) &&
(NS_STYLE_BORDER_STYLE_SOLID != bStyle)) {
bStyle = NS_STYLE_BORDER_STYLE_SOLID;
}
bStyle |= NS_STYLE_BORDER_STYLE_RULES_MASK;
borderData->SetBorderStyle(aSide, bStyle);
nscolor borderColor;
PRBool transparent, foreground;
borderData->GetBorderColor(aSide, borderColor, transparent, foreground);
if (transparent || foreground) {
// use the table's border color if it is set, otherwise use black
nscolor tableBorderColor;
tableBorderData->GetBorderColor(aSide, tableBorderColor, transparent, foreground);
borderColor = (transparent || foreground) ? NS_RGB(0,0,0) : tableBorderColor;
borderData->SetBorderColor(aSide, borderColor);
}
// set the border width to be 1 pixel
float p2t;
aRuleData->mPresContext->GetScaledPixelsToTwips(&p2t);
nscoord onePixel = NSToCoordRound(p2t);
nsStyleCoord coord(onePixel);
switch(aSide) {
case NS_SIDE_TOP:
borderData->mBorder.SetTop(coord);
break;
case NS_SIDE_RIGHT:
borderData->mBorder.SetRight(coord);
break;
case NS_SIDE_BOTTOM:
borderData->mBorder.SetBottom(coord);
break;
default: // NS_SIDE_LEFT
borderData->mBorder.SetLeft(coord);
break;
}
}
}
}
// -----------------------------------------------------------
// this rule handles borders on a <thead>, <tbody>, <tfoot> when rules is set on its <table>
// -----------------------------------------------------------
class TableTbodyRule: public GenericTableRule {
public:
TableTbodyRule(nsIHTMLStyleSheet* aSheet);
virtual ~TableTbodyRule();
void Reset()
{
GenericTableRule::Reset();
}
NS_IMETHOD MapRuleInfoInto(nsRuleData* aRuleData);
};
TableTbodyRule::TableTbodyRule(nsIHTMLStyleSheet* aSheet)
: GenericTableRule(aSheet)
{
}
TableTbodyRule::~TableTbodyRule()
{
}
static void TbodyPostResolveCallback(nsStyleStruct* aStyleStruct, nsRuleData* aRuleData)
{
::ProcessTableRulesAttribute(aStyleStruct, aRuleData, NS_SIDE_TOP, PR_TRUE, NS_STYLE_TABLE_RULES_ALL,
NS_STYLE_TABLE_RULES_GROUPS, NS_STYLE_TABLE_RULES_ROWS);
::ProcessTableRulesAttribute(aStyleStruct, aRuleData, NS_SIDE_BOTTOM, PR_TRUE, NS_STYLE_TABLE_RULES_ALL,
NS_STYLE_TABLE_RULES_GROUPS, NS_STYLE_TABLE_RULES_ROWS);
}
NS_IMETHODIMP
TableTbodyRule::MapRuleInfoInto(nsRuleData* aRuleData)
{
if (aRuleData && aRuleData->mSID == eStyleStruct_Border) {
aRuleData->mCanStoreInRuleTree = PR_FALSE;
aRuleData->mPostResolveCallback = &TbodyPostResolveCallback;
}
return NS_OK;
}
// -----------------------------------------------------------
// -----------------------------------------------------------
// this rule handles borders on a <row> when rules is set on its <table>
// -----------------------------------------------------------
class TableRowRule: public GenericTableRule {
public:
TableRowRule(nsIHTMLStyleSheet* aSheet);
virtual ~TableRowRule();
void Reset()
{
GenericTableRule::Reset();
}
NS_IMETHOD MapRuleInfoInto(nsRuleData* aRuleData);
};
TableRowRule::TableRowRule(nsIHTMLStyleSheet* aSheet)
: GenericTableRule(aSheet)
{
}
TableRowRule::~TableRowRule()
{
}
static void RowPostResolveCallback(nsStyleStruct* aStyleStruct, nsRuleData* aRuleData)
{
::ProcessTableRulesAttribute(aStyleStruct, aRuleData, NS_SIDE_TOP, PR_FALSE, NS_STYLE_TABLE_RULES_ALL,
NS_STYLE_TABLE_RULES_ROWS, NS_STYLE_TABLE_RULES_ROWS);
::ProcessTableRulesAttribute(aStyleStruct, aRuleData, NS_SIDE_BOTTOM, PR_FALSE, NS_STYLE_TABLE_RULES_ALL,
NS_STYLE_TABLE_RULES_ROWS, NS_STYLE_TABLE_RULES_ROWS);
}
NS_IMETHODIMP
TableRowRule::MapRuleInfoInto(nsRuleData* aRuleData)
{
if (aRuleData && aRuleData->mSID == eStyleStruct_Border) {
aRuleData->mCanStoreInRuleTree = PR_FALSE;
aRuleData->mPostResolveCallback = &RowPostResolveCallback;
}
return NS_OK;
}
// -----------------------------------------------------------
// this rule handles borders on a <colgroup> when rules is set on its <table>
// -----------------------------------------------------------
class TableColgroupRule: public GenericTableRule {
public:
TableColgroupRule(nsIHTMLStyleSheet* aSheet);
virtual ~TableColgroupRule();
void Reset()
{
GenericTableRule::Reset();
}
NS_IMETHOD MapRuleInfoInto(nsRuleData* aRuleData);
};
TableColgroupRule::TableColgroupRule(nsIHTMLStyleSheet* aSheet)
: GenericTableRule(aSheet)
{
}
TableColgroupRule::~TableColgroupRule()
{
}
static void ColgroupPostResolveCallback(nsStyleStruct* aStyleStruct, nsRuleData* aRuleData)
{
::ProcessTableRulesAttribute(aStyleStruct, aRuleData, NS_SIDE_LEFT, PR_TRUE, NS_STYLE_TABLE_RULES_ALL,
NS_STYLE_TABLE_RULES_GROUPS, NS_STYLE_TABLE_RULES_COLS);
::ProcessTableRulesAttribute(aStyleStruct, aRuleData, NS_SIDE_RIGHT, PR_TRUE, NS_STYLE_TABLE_RULES_ALL,
NS_STYLE_TABLE_RULES_GROUPS, NS_STYLE_TABLE_RULES_COLS);
}
NS_IMETHODIMP
TableColgroupRule::MapRuleInfoInto(nsRuleData* aRuleData)
{
if (aRuleData && aRuleData->mSID == eStyleStruct_Border) {
aRuleData->mCanStoreInRuleTree = PR_FALSE;
aRuleData->mPostResolveCallback = &ColgroupPostResolveCallback;
}
return NS_OK;
}
// -----------------------------------------------------------
// this rule handles borders on a <col> when rules is set on its <table>
// -----------------------------------------------------------
class TableColRule: public GenericTableRule {
public:
TableColRule(nsIHTMLStyleSheet* aSheet);
virtual ~TableColRule();
void Reset()
{
GenericTableRule::Reset();
}
NS_IMETHOD MapRuleInfoInto(nsRuleData* aRuleData);
};
TableColRule::TableColRule(nsIHTMLStyleSheet* aSheet)
: GenericTableRule(aSheet)
{
}
TableColRule::~TableColRule()
{
}
static void ColPostResolveCallback(nsStyleStruct* aStyleStruct, nsRuleData* aRuleData)
{
::ProcessTableRulesAttribute(aStyleStruct, aRuleData, NS_SIDE_LEFT, PR_FALSE, NS_STYLE_TABLE_RULES_ALL,
NS_STYLE_TABLE_RULES_COLS, NS_STYLE_TABLE_RULES_COLS);
::ProcessTableRulesAttribute(aStyleStruct, aRuleData, NS_SIDE_RIGHT, PR_FALSE, NS_STYLE_TABLE_RULES_ALL,
NS_STYLE_TABLE_RULES_COLS, NS_STYLE_TABLE_RULES_COLS);
}
NS_IMETHODIMP
TableColRule::MapRuleInfoInto(nsRuleData* aRuleData)
{
if (aRuleData && aRuleData->mSID == eStyleStruct_Border) {
aRuleData->mCanStoreInRuleTree = PR_FALSE;
aRuleData->mPostResolveCallback = &ColPostResolveCallback;
}
return NS_OK;
}
// -----------------------------------------------------------
class AttributeKey: public nsHashKey
@ -653,6 +901,10 @@ protected:
HTMLColorRule* mVisitedRule;
HTMLColorRule* mActiveRule;
HTMLDocumentColorRule* mDocumentColorRule;
TableTbodyRule* mTableTbodyRule;
TableRowRule* mTableRowRule;
TableColgroupRule* mTableColgroupRule;
TableColRule* mTableColRule;
TableTHRule* mTableTHRule;
// NOTE: if adding more rules, be sure to update
// the SizeOf method to include them
@ -710,6 +962,26 @@ HTMLStyleSheetImpl::HTMLStyleSheetImpl(void)
nsresult
HTMLStyleSheetImpl::Init()
{
mTableTbodyRule = new TableTbodyRule(this);
if (!mTableTbodyRule)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(mTableTbodyRule);
mTableRowRule = new TableRowRule(this);
if (!mTableRowRule)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(mTableRowRule);
mTableColgroupRule = new TableColgroupRule(this);
if (!mTableColgroupRule)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(mTableColgroupRule);
mTableColRule = new TableColRule(this);
if (!mTableColRule)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(mTableColRule);
mTableTHRule = new TableTHRule(this);
if (!mTableTHRule)
return NS_ERROR_OUT_OF_MEMORY;
@ -750,6 +1022,22 @@ HTMLStyleSheetImpl::~HTMLStyleSheetImpl()
mDocumentColorRule->mSheet = nsnull;
NS_RELEASE(mDocumentColorRule);
}
if (nsnull != mTableTbodyRule) {
mTableTbodyRule->mSheet = nsnull;
NS_RELEASE(mTableTbodyRule);
}
if (nsnull != mTableRowRule) {
mTableRowRule->mSheet = nsnull;
NS_RELEASE(mTableRowRule);
}
if (nsnull != mTableColgroupRule) {
mTableColgroupRule->mSheet = nsnull;
NS_RELEASE(mTableColgroupRule);
}
if (nsnull != mTableColRule) {
mTableColRule->mSheet = nsnull;
NS_RELEASE(mTableColRule);
}
if (nsnull != mTableTHRule) {
mTableTHRule->mSheet = nsnull;
NS_RELEASE(mTableTHRule);
@ -848,6 +1136,18 @@ HTMLStyleSheetImpl::RulesMatching(ElementRuleProcessorData* aData,
else if (tag == nsHTMLAtoms::th) {
ruleWalker->Forward(mTableTHRule);
}
else if (tag == nsHTMLAtoms::tr) {
ruleWalker->Forward(mTableRowRule);
}
else if ((tag == nsHTMLAtoms::thead) || (tag == nsHTMLAtoms::tbody) || (tag == nsHTMLAtoms::tfoot)) {
ruleWalker->Forward(mTableTbodyRule);
}
else if (tag == nsHTMLAtoms::col) {
ruleWalker->Forward(mTableColRule);
}
else if (tag == nsHTMLAtoms::colgroup) {
ruleWalker->Forward(mTableColgroupRule);
}
else if (tag == nsHTMLAtoms::table) {
if (aData->mIsQuirkMode)
ruleWalker->Forward(mDocumentColorRule);
@ -888,7 +1188,13 @@ NS_IMETHODIMP
HTMLStyleSheetImpl::RulesMatching(PseudoRuleProcessorData* aData,
nsIAtom* aMedium)
{
// no pseudo frame style
nsIAtom* pseudoTag = aData->mPseudoTag;
if (pseudoTag == nsHTMLAtoms::tableColPseudo) {
nsRuleWalker *ruleWalker = aData->mRuleWalker;
if (ruleWalker) {
ruleWalker->Forward(mTableColRule);
}
}
return NS_OK;
}
@ -1008,6 +1314,11 @@ HTMLStyleSheetImpl::Reset(nsIURI* aURL)
NS_RELEASE(mActiveRule);
}
mDocumentColorRule->Reset();
mTableTbodyRule->Reset();
mTableRowRule->Reset();
mTableColgroupRule->Reset();
mTableColRule->Reset();
mTableTHRule->Reset();
mMappedAttrTable.Enumerate(MappedDropSheet);
@ -1264,6 +1575,10 @@ MappedSizeAttributes(nsHashKey *aKey, void *aData, void* closure)
* - mVisitedRule
* - mActiveRule
* - mDocumentColorRule
* - mTableTbodyRule
* - mTableRowRule
* - mTableColgroupRule
* - mTableColRule
* - mTableTHRule
* - mMappedAttrTable
* 2) Delegates (really) to the MappedAttributes in the mMappedAttrTable
@ -1298,6 +1613,10 @@ HTMLStyleSheetImpl::SizeOf(nsISizeOfHandler *aSizeOfHandler, PRUint32 &aSize)
// - mVisitedRule : sizeof object
// - mActiveRule : sizeof object
// - mDocumentColorRule : sizeof object
// - mTableTbodyRule : sizeof object
// - mTableRowRule : sizeof object
// - mTableColgroupRule : sizeof object
// - mTableColRule : sizeof object
// - mTableTHRule : sizeof object
// - mMappedAttrTable
@ -1321,6 +1640,26 @@ HTMLStyleSheetImpl::SizeOf(nsISizeOfHandler *aSizeOfHandler, PRUint32 &aSize)
tag = getter_AddRefs(NS_NewAtom("DocumentColorRule"));
aSizeOfHandler->AddSize(tag,localSize);
}
if(uniqueItems->AddItem((void*)mTableTbodyRule)){
localSize = sizeof(*mTableTbodyRule);
tag = getter_AddRefs(NS_NewAtom("TableTbodyRule"));
aSizeOfHandler->AddSize(tag,localSize);
}
if(uniqueItems->AddItem((void*)mTableRowRule)){
localSize = sizeof(*mTableRowRule);
tag = getter_AddRefs(NS_NewAtom("TableRowRule"));
aSizeOfHandler->AddSize(tag,localSize);
}
if(uniqueItems->AddItem((void*)mTableColgroupRule)){
localSize = sizeof(*mTableColgroupRule);
tag = getter_AddRefs(NS_NewAtom("TableColgroupRule"));
aSizeOfHandler->AddSize(tag,localSize);
}
if(uniqueItems->AddItem((void*)mTableColRule)){
localSize = sizeof(*mTableColRule);
tag = getter_AddRefs(NS_NewAtom("TableColRule"));
aSizeOfHandler->AddSize(tag,localSize);
}
if(uniqueItems->AddItem((void*)mTableTHRule)){
localSize = sizeof(*mTableTHRule);
tag = getter_AddRefs(NS_NewAtom("TableTHRule"));

View File

@ -103,7 +103,7 @@ CSS_PROP(border-bottom-color, border_bottom_color, VISUAL)
CSS_PROP(-moz-border-bottom-colors, border_bottom_colors, VISUAL)
CSS_PROP(border-bottom-style, border_bottom_style, REFLOW) // on/off will need reflow
CSS_PROP(border-bottom-width, border_bottom_width, REFLOW)
CSS_PROP(border-collapse, border_collapse, REFLOW)
CSS_PROP(border-collapse, border_collapse, FRAMECHANGE)
CSS_PROP(border-color, border_color, VISUAL)
CSS_PROP(border-left, border_left, REFLOW)
CSS_PROP(border-left-color, border_left_color, VISUAL)

View File

@ -100,6 +100,7 @@ LAYOUT_ATOM(selectScrolledContentPseudo, ":-moz-select-scrolled-content")
// Alphabetical list of frame types
LAYOUT_ATOM(areaFrame, "AreaFrame")
LAYOUT_ATOM(bcTableCellFrame, "BCTableCellFrame") // table cell in border collapsing model
LAYOUT_ATOM(blockFrame, "BlockFrame")
LAYOUT_ATOM(boxFrame, "BoxFrame")
LAYOUT_ATOM(brFrame, "BRFrame")
@ -143,7 +144,8 @@ LAYOUT_ATOM(overflowProperty, "OverflowProperty") // list of nsIFra
LAYOUT_ATOM(overflowLinesProperty, "OverflowLinesProperty") // list of nsLineBox*
LAYOUT_ATOM(rowUnpaginatedHeightProperty, "RowUnpaginatedHeightProperty") // nscoord*
LAYOUT_ATOM(spaceManagerProperty, "SpaceManagerProperty") // the space manager for a block
LAYOUT_ATOM(viewProperty, "ViewProperty") // nsView*
LAYOUT_ATOM(tableBCProperty, "TableBCProperty") // table border collapsing info (e.g. damage area, table border widths)
LAYOUT_ATOM(viewProperty, "ViewProperty")
// Alphabetical list of event handler names
LAYOUT_ATOM(onabort, "onabort")

View File

@ -465,7 +465,8 @@ struct nsStyleBorder: public nsStyleStruct {
// XXX these are deprecated methods
void CalcBorderFor(const nsIFrame* aFrame, nsMargin& aBorder) const;
void CalcBorderFor(const nsIFrame* aFrame, PRUint8 aSide, nscoord& aWidth) const;
protected:
PRPackedBool mHasCachedBorder;
nsMargin mCachedBorder;

View File

@ -605,6 +605,28 @@ nsStyleBorder::CalcBorderFor(const nsIFrame* aFrame, nsMargin& aBorder) const
}
}
void
nsStyleBorder::CalcBorderFor(const nsIFrame* aFrame, PRUint8 aSide, nscoord& aWidth) const
{
aWidth = 0;
// using mCachedBorder as above, doesn't work properly
nsStyleCoord coord;
switch(aSide) {
case NS_SIDE_TOP:
coord = mBorder.GetTop(coord);
break;
case NS_SIDE_RIGHT:
coord = mBorder.GetRight(coord);
break;
case NS_SIDE_BOTTOM:
coord = mBorder.GetBottom(coord);
break;
default: // NS_SIDE_LEFT
coord = mBorder.GetLeft(coord);
}
aWidth = CalcSideFor(aFrame, coord, NS_SPACING_BORDER, aSide, mBorderWidths, 3);
}
nsStyleOutline::nsStyleOutline(nsIPresContext* aPresContext)
{
// XXX support mBorderWidths until deprecated methods are removed
@ -862,7 +884,7 @@ nsStyleTable::nsStyleTable()
mLayoutStrategy = NS_STYLE_TABLE_LAYOUT_AUTO;
mCols = NS_STYLE_TABLE_COLS_NONE;
mFrame = NS_STYLE_TABLE_FRAME_NONE;
mRules = NS_STYLE_TABLE_RULES_ALL;
mRules = NS_STYLE_TABLE_RULES_NONE;
mSpan = 1;
}

View File

@ -52,8 +52,11 @@
#include "nsIPresContext.h"
#include "nsILinkHandler.h"
#include "nsIDocument.h"
#include "nsTableFrame.h"
#include "nsTableColGroupFrame.h"
#include "nsTableColFrame.h"
#include "nsIDOMHTMLTableColElement.h"
#include "nsTableCellFrame.h" // to get IS_CELL_FRAME
#include "nsHTMLIIDs.h"
#include "nsIStyleFrameConstruction.h"
#include "nsHTMLParts.h"
@ -859,6 +862,23 @@ nsFrameConstructorSaveState::~nsFrameConstructorSaveState()
}
}
static
PRBool IsBorderCollapse(nsIFrame* aFrame)
{
nsIFrame* frame = aFrame;
while (frame) {
nsCOMPtr<nsIAtom> fType;
frame->GetFrameType(getter_AddRefs(fType));
if (nsLayoutAtoms::tableFrame == fType.get()) {
return ((nsTableFrame*)frame)->IsBorderCollapse();
}
frame->GetParent(&frame);
}
NS_ASSERTION(PR_FALSE, "program error");
return PR_FALSE;
}
// -----------------------------------------------------------
// Structure used when creating table frames.
@ -870,7 +890,7 @@ struct nsTableCreator {
virtual nsresult CreateTableColFrame(nsIFrame** aNewFrame);
virtual nsresult CreateTableColGroupFrame(nsIFrame** aNewFrame);
virtual nsresult CreateTableRowFrame(nsIFrame** aNewFrame);
virtual nsresult CreateTableCellFrame(nsIFrame** aNewFrame);
virtual nsresult CreateTableCellFrame(nsIFrame* aParentFrame, nsIFrame** aNewFrame);
virtual nsresult CreateTableCellInnerFrame(nsIFrame** aNewFrame);
nsTableCreator(nsIPresShell* aPresShell)
@ -919,8 +939,9 @@ nsTableCreator::CreateTableRowFrame(nsIFrame** aNewFrame) {
}
nsresult
nsTableCreator::CreateTableCellFrame(nsIFrame** aNewFrame) {
return NS_NewTableCellFrame(mPresShell, aNewFrame);
nsTableCreator::CreateTableCellFrame(nsIFrame* aParentFrame,
nsIFrame** aNewFrame) {
return NS_NewTableCellFrame(mPresShell, IsBorderCollapse(aParentFrame), aNewFrame);
}
nsresult
@ -1527,7 +1548,7 @@ IsTableRelated(nsIAtom* aParentType,
((nsLayoutAtoms::tableCaptionFrame == aParentType) ||
(nsLayoutAtoms::tableColGroupFrame == aParentType) ||
(nsLayoutAtoms::tableColFrame == aParentType) ||
(nsLayoutAtoms::tableCellFrame == aParentType))) {
IS_TABLE_CELL(aParentType))) {
return PR_TRUE;
}
else return PR_FALSE;
@ -1629,7 +1650,7 @@ ProcessPseudoFrames(nsIPresContext* aPresContext,
if (aPseudoFrames.mCellOuter.mFrame) {
rv = ProcessPseudoCellFrame(aPresContext, aPseudoFrames, aHighestFrame);
if (nsLayoutAtoms::tableCellFrame == aHighestType) return rv;
if (IS_TABLE_CELL(aHighestType)) return rv;
}
if (aPseudoFrames.mRow.mFrame) {
rv = ProcessPseudoFrame(aPresContext, aPseudoFrames.mRow, aHighestFrame);
@ -1650,7 +1671,7 @@ ProcessPseudoFrames(nsIPresContext* aPresContext,
}
if (aPseudoFrames.mCellOuter.mFrame) {
rv = ProcessPseudoCellFrame(aPresContext, aPseudoFrames, aHighestFrame);
if (nsLayoutAtoms::tableCellFrame == aHighestType) return rv;
if (IS_TABLE_CELL(aHighestType)) return rv;
}
if (aPseudoFrames.mRow.mFrame) {
rv = ProcessPseudoFrame(aPresContext, aPseudoFrames.mRow, aHighestFrame);
@ -1671,12 +1692,12 @@ ProcessPseudoFrames(nsIPresContext* aPresContext,
}
if (aPseudoFrames.mCellOuter.mFrame) {
rv = ProcessPseudoCellFrame(aPresContext, aPseudoFrames, aHighestFrame);
if (nsLayoutAtoms::tableCellFrame == aHighestType) return rv;
if (IS_TABLE_CELL(aHighestType)) return rv;
}
}
else if (nsLayoutAtoms::tableCellFrame == aPseudoFrames.mLowestType) {
else if (IS_TABLE_CELL(aPseudoFrames.mLowestType)) {
rv = ProcessPseudoCellFrame(aPresContext, aPseudoFrames, aHighestFrame);
if (nsLayoutAtoms::tableCellFrame == aHighestType) return rv;
if (IS_TABLE_CELL(aHighestType)) return rv;
if (aPseudoFrames.mRow.mFrame) {
rv = ProcessPseudoFrame(aPresContext, aPseudoFrames.mRow, aHighestFrame);
@ -1942,6 +1963,7 @@ nsCSSFrameConstructor::CreatePseudoCellFrame(nsIPresShell* aPresShell
// set pseudo data for the newly created frames
pseudoOuter.mChildList.AddChild(pseudoInner.mFrame);
// give it nsLayoutAtoms::tableCellFrame, if it is really nsLayoutAtoms::bcTableCellFrame, it will match later
aState.mPseudoFrames.mLowestType = nsLayoutAtoms::tableCellFrame;
// set pseudo data for the parent
@ -2021,7 +2043,7 @@ nsCSSFrameConstructor::GetPseudoColGroupFrame(nsIPresShell* aPresShel
rv = CreatePseudoCellFrame(aPresShell, aPresContext, aTableCreator, aState, &aParentFrameIn);
created = PR_TRUE;
}
if (created || (nsLayoutAtoms::tableCellFrame == parentFrameType.get()) || // cell parent
if (created || IS_TABLE_CELL(parentFrameType.get()) || // cell parent
!IsTableRelated(parentFrameType.get(), PR_TRUE)) { // block parent
rv = CreatePseudoTableFrame(aPresShell, aPresContext, aTableCreator, aState, &aParentFrameIn);
}
@ -2065,7 +2087,7 @@ nsCSSFrameConstructor::GetPseudoRowGroupFrame(nsIPresShell* aPresShel
rv = CreatePseudoCellFrame(aPresShell, aPresContext, aTableCreator, aState, &aParentFrameIn);
created = PR_TRUE;
}
if (created || (nsLayoutAtoms::tableCellFrame == parentFrameType.get()) || // cell parent
if (created || IS_TABLE_CELL(parentFrameType.get()) || // cell parent
!IsTableRelated(parentFrameType.get(), PR_TRUE)) { // block parent
rv = CreatePseudoTableFrame(aPresShell, aPresContext, aTableCreator, aState, &aParentFrameIn);
}
@ -2102,7 +2124,7 @@ nsCSSFrameConstructor::GetPseudoRowFrame(nsIPresShell* aPresShell,
if (pseudoFrames.IsEmpty()) {
PRBool created = PR_FALSE;
if ((nsLayoutAtoms::tableCellFrame == parentFrameType.get()) || // cell parent
if (IS_TABLE_CELL(parentFrameType.get()) || // cell parent
!IsTableRelated(parentFrameType.get(), PR_TRUE)) { // block parent
rv = CreatePseudoTableFrame(aPresShell, aPresContext, aTableCreator, aState, &aParentFrameIn);
created = PR_TRUE;
@ -2230,7 +2252,7 @@ nsCSSFrameConstructor::GetParentFrame(nsIPresShell* aPresShell,
pseudoParentFrame = pseudoFrames.mRowGroup.mFrame;
}
}
else if (nsLayoutAtoms::tableCellFrame == aChildFrameType) { // cell child
else if (IS_TABLE_CELL(aChildFrameType)) { // cell child
if (nsLayoutAtoms::tableRowFrame != parentFrameType.get()) { // need pseudo row parent
rv = GetPseudoRowFrame(aPresShell, aPresContext, aTableCreator, aState, aParentFrameIn);
if (NS_FAILED(rv)) return rv;
@ -2572,7 +2594,7 @@ nsCSSFrameConstructor::ConstructTableColFrame(nsIPresShell* aPresShel
PRBool& aIsPseudoParent)
{
nsresult rv = NS_OK;
if (!aPresShell || !aPresContext || !aParentFrameIn) return rv;
if (!aPresShell || !aPresContext || !aParentFrameIn || !aStyleContext) return rv;
nsIFrame* parentFrame = aParentFrameIn;
aIsPseudoParent = PR_FALSE;
@ -2585,16 +2607,42 @@ nsCSSFrameConstructor::ConstructTableColFrame(nsIPresShell* aPresShel
}
}
rv = aTableCreator.CreateTableColFrame(&aNewFrame);
if (NS_FAILED(rv)) return rv;
InitAndRestoreFrame(aPresContext, aState, aContent,
parentFrame, aStyleContext, nsnull, aNewFrame);
rv = aTableCreator.CreateTableColFrame(&aNewFrame); if (NS_FAILED(rv)) return rv;
InitAndRestoreFrame(aPresContext, aState, aContent, parentFrame, aStyleContext, nsnull, aNewFrame);
// if the parent frame was anonymous then reparent the style context
nsCOMPtr<nsIStyleContext> parentStyleContext;
parentFrame->GetStyleContext(getter_AddRefs(parentStyleContext));
if (aIsPseudoParent) {
aPresContext->ReParentStyleContext(aNewFrame, parentStyleContext);
}
// construct additional col frames if the col frame has a span > 1
PRInt32 span = 1;
nsCOMPtr<nsIDOMHTMLTableColElement> cgContent(do_QueryInterface(aContent));
if (cgContent) {
cgContent->GetSpan(&span);
nsIFrame* lastCol = aNewFrame;
for (PRInt32 spanX = 1; spanX < span; spanX++) {
nsCOMPtr<nsIStyleContext> styleContext;
aPresContext->ResolvePseudoStyleContextFor(aContent, nsHTMLAtoms::tableColPseudo, aStyleContext,
PR_FALSE, getter_AddRefs(styleContext));
nsIFrame* newCol;
rv = aTableCreator.CreateTableColFrame(&newCol); if (NS_FAILED(rv)) return rv;
InitAndRestoreFrame(aPresContext, aState, aContent, parentFrame, styleContext, nsnull, newCol);
if (aIsPseudoParent) {
aPresContext->ReParentStyleContext(newCol, aStyleContext);
}
((nsTableColFrame*)newCol)->SetType(eColAnonymousCol);
lastCol->SetNextSibling(newCol);
lastCol = newCol;
}
}
if (!aIsPseudo) {
nsFrameItems childItems;
nsIFrame* captionFrame;
rv = TableProcessChildren(aPresShell, aPresContext, aState, aContent, aNewFrame,
aTableCreator, childItems, captionFrame);
if (NS_FAILED(rv)) return rv;
aTableCreator, childItems, captionFrame); if (NS_FAILED(rv)) return rv;
aNewFrame->SetInitialChildList(aPresContext, nsnull, childItems.childList);
if (aIsPseudoParent) {
aState.mPseudoFrames.mColGroup.mChildList.AddChild(aNewFrame);
@ -2625,6 +2673,7 @@ nsCSSFrameConstructor::ConstructTableCellFrame(nsIPresShell* aPresShe
aIsPseudoParent = PR_FALSE;
if (!aIsPseudo) {
// this frame may have a pseudo parent
// use nsLayoutAtoms::tableCellFrame which will match if it is really nsLayoutAtoms::bcTableCellFrame
GetParentFrame(aPresShell, aPresContext, aTableCreator, *aParentFrameIn,
nsLayoutAtoms::tableCellFrame, aState, parentFrame, aIsPseudoParent);
if (!aIsPseudoParent && !aState.mPseudoFrames.IsEmpty()) {
@ -2635,7 +2684,7 @@ nsCSSFrameConstructor::ConstructTableCellFrame(nsIPresShell* aPresShe
}
}
rv = aTableCreator.CreateTableCellFrame(&aNewCellOuterFrame);
rv = aTableCreator.CreateTableCellFrame(parentFrame, &aNewCellOuterFrame);
if (NS_FAILED(rv)) return rv;
// Initialize the table cell frame
@ -11328,7 +11377,7 @@ nsCSSFrameConstructor::CreateContinuingFrame(nsIPresShell* aPresShell,
// See if it's a table cell frame
cellFrame->GetFrameType(&tableType);
if (nsLayoutAtoms::tableCellFrame == tableType) {
if (IS_TABLE_CELL(tableType)) {
nsIFrame* continuingCellFrame;
CreateContinuingFrame(aPresShell, aPresContext, cellFrame, newFrame, &continuingCellFrame);
@ -11343,8 +11392,8 @@ nsCSSFrameConstructor::CreateContinuingFrame(nsIPresShell* aPresShell,
newFrame->SetInitialChildList(aPresContext, nsnull, newChildList.childList);
}
} else if (nsLayoutAtoms::tableCellFrame == frameType) {
rv = NS_NewTableCellFrame(aPresShell, &newFrame);
} else if (IS_TABLE_CELL(frameType)) {
rv = NS_NewTableCellFrame(aPresShell, IsBorderCollapse(aParentFrame), &newFrame);
if (NS_SUCCEEDED(rv)) {
newFrame->Init(aPresContext, content, aParentFrame, styleContext, aFrame);
nsHTMLContainerFrame::CreateViewForFrame(aPresContext, newFrame,

View File

@ -514,6 +514,7 @@ void nsCSSRendering::DrawSide(nsIRenderingContext& aContext,
}
}
/**
* Draw a dotted/dashed sides of a box
*/
@ -3821,3 +3822,356 @@ void FillOrInvertRect(nsIRenderingContext& aRC, const nsRect& aRect, PRBool aInv
}
}
// Begin table border-collapsing section
// These functions were written to not disrupt the normal ones and yet satisfy some additional requirements
// At some point, all functions should be unified to include the additional functionality that these provide
static nscoord
RoundIntToPixel(nscoord aValue,
nscoord aTwipsPerPixel,
PRBool aRoundDown = PR_FALSE)
{
nscoord halfPixel = NSToCoordRound(aTwipsPerPixel / 2.0f);
nscoord extra = aValue % aTwipsPerPixel;
nscoord finalValue = (!aRoundDown && (extra >= halfPixel)) ? aValue + (aTwipsPerPixel - extra) : aValue - extra;
return finalValue;
}
static nscoord
RoundFloatToPixel(float aValue,
nscoord aTwipsPerPixel,
PRBool aRoundDown = PR_FALSE)
{
return RoundIntToPixel(NSToCoordRound(aValue), aTwipsPerPixel, aRoundDown);
}
static void
SetPoly(const nsRect& aRect,
nsPoint* poly)
{
poly[0].x = aRect.x;
poly[0].y = aRect.y;
poly[1].x = aRect.x + aRect.width;
poly[1].y = aRect.y;
poly[2].x = aRect.x + aRect.width;
poly[2].y = aRect.y + aRect.height;
poly[3].x = aRect.x;
poly[3].y = aRect.y + aRect.height;
poly[4].x = aRect.x;
poly[4].y = aRect.y;
}
static void
DrawSolidBorderSegment(nsIRenderingContext& aContext,
nsRect aRect,
nscoord aTwipsPerPixel,
PRUint8 aStartBevelSide = 0,
nscoord aStartBevelOffset = 0,
PRUint8 aEndBevelSide = 0,
nscoord aEndBevelOffset = 0)
{
if ((aRect.width == aTwipsPerPixel) || (aRect.height == aTwipsPerPixel) ||
((0 == aStartBevelOffset) && (0 == aEndBevelOffset))) {
// simple line or rectangle
if ((NS_SIDE_TOP == aStartBevelSide) || (NS_SIDE_BOTTOM == aStartBevelSide)) {
if (1 == aRect.height)
aContext.DrawLine(aRect.x, aRect.y, aRect.x, aRect.y + aRect.height);
else
aContext.FillRect(aRect);
}
else {
if (1 == aRect.width)
aContext.DrawLine(aRect.x, aRect.y, aRect.x + aRect.width, aRect.y);
else
aContext.FillRect(aRect);
}
}
else {
// polygon with beveling
nsPoint poly[5];
SetPoly(aRect, poly);
switch(aStartBevelSide) {
case NS_SIDE_TOP:
poly[0].x += aStartBevelOffset;
poly[4].x = poly[0].x;
break;
case NS_SIDE_BOTTOM:
poly[3].x += aStartBevelOffset;
break;
case NS_SIDE_RIGHT:
poly[1].y += aStartBevelOffset;
break;
case NS_SIDE_LEFT:
poly[0].y += aStartBevelOffset;
poly[4].y = poly[0].y;
}
switch(aEndBevelSide) {
case NS_SIDE_TOP:
poly[1].x -= aEndBevelOffset;
break;
case NS_SIDE_BOTTOM:
poly[2].x -= aEndBevelOffset;
break;
case NS_SIDE_RIGHT:
poly[2].y -= aEndBevelOffset;
break;
case NS_SIDE_LEFT:
poly[3].y -= aEndBevelOffset;
}
aContext.FillPolygon(poly, 5);
}
}
static void
GetDashInfo(nscoord aBorderLength,
nscoord aDashLength,
nscoord aTwipsPerPixel,
PRInt32& aNumDashSpaces,
nscoord& aStartDashLength,
nscoord& aEndDashLength)
{
aNumDashSpaces = 0;
if (aStartDashLength + aDashLength + aEndDashLength >= aBorderLength) {
aStartDashLength = aBorderLength;
aEndDashLength = 0;
}
else {
aNumDashSpaces = aBorderLength / (2 * aDashLength); // round down
nscoord foo = ((2 * aNumDashSpaces) - 1) * aDashLength;
nscoord extra = aBorderLength - aStartDashLength - aEndDashLength - (((2 * aNumDashSpaces) - 1) * aDashLength);
if (extra > 0) {
nscoord half = RoundIntToPixel(extra / 2, aTwipsPerPixel);
aStartDashLength += half;
aEndDashLength += (extra - half);
}
}
}
void
nsCSSRendering::DrawTableBorderSegment(nsIRenderingContext& aContext,
PRUint8 aBorderStyle,
nscolor aBorderColor,
const nsStyleBackground* aBGColor,
const nsRect& aBorder,
float aPixelsToTwips,
PRUint8 aStartBevelSide,
nscoord aStartBevelOffset,
PRUint8 aEndBevelSide,
nscoord aEndBevelOffset)
{
aContext.SetColor (aBorderColor);
PRBool horizontal = ((NS_SIDE_TOP == aStartBevelSide) || (NS_SIDE_BOTTOM == aStartBevelSide));
nscoord twipsPerPixel = NSIntPixelsToTwips(1, aPixelsToTwips);
PRBool ridgeGroove = NS_STYLE_BORDER_STYLE_RIDGE;
if ((twipsPerPixel >= aBorder.width) || (twipsPerPixel >= aBorder.height) ||
(NS_STYLE_BORDER_STYLE_DASHED == aBorderStyle) || (NS_STYLE_BORDER_STYLE_DOTTED == aBorderStyle)) {
// no beveling for 1 pixel border, dash or dot
aStartBevelOffset = 0;
aEndBevelOffset = 0;
}
switch (aBorderStyle) {
case NS_STYLE_BORDER_STYLE_NONE:
case NS_STYLE_BORDER_STYLE_HIDDEN:
case NS_STYLE_BORDER_STYLE_BLANK:
//NS_ASSERTION(PR_FALSE, "style of none, hidden, or blank");
break;
case NS_STYLE_BORDER_STYLE_DOTTED:
case NS_STYLE_BORDER_STYLE_DASHED:
{
nscoord dashLength = (NS_STYLE_BORDER_STYLE_DASHED == aBorderStyle) ? DASH_LENGTH : DOT_LENGTH;
// make the dash length proportional to the border thickness
dashLength *= (horizontal) ? aBorder.height : aBorder.width;
// make the min dash length for the ends 1/2 the dash length
nscoord minDashLength = (NS_STYLE_BORDER_STYLE_DASHED == aBorderStyle)
? RoundFloatToPixel(((float)dashLength) / 2.0f, twipsPerPixel) : dashLength;
minDashLength = PR_MAX(minDashLength, twipsPerPixel);
nscoord numDashSpaces = 0;
nscoord startDashLength = minDashLength;
nscoord endDashLength = minDashLength;
if (horizontal) {
GetDashInfo(aBorder.width, dashLength, twipsPerPixel, numDashSpaces, startDashLength, endDashLength);
nsRect rect(aBorder.x, aBorder.y, startDashLength, aBorder.height);
DrawSolidBorderSegment(aContext, rect, PR_TRUE);
for (PRInt32 spaceX = 0; spaceX < numDashSpaces; spaceX++) {
rect.x += rect.width + dashLength;
rect.width = (spaceX == (numDashSpaces - 1)) ? endDashLength : dashLength;
DrawSolidBorderSegment(aContext, rect, PR_TRUE);
}
}
else {
GetDashInfo(aBorder.height, dashLength, twipsPerPixel, numDashSpaces, startDashLength, endDashLength);
nsRect rect(aBorder.x, aBorder.y, aBorder.width, startDashLength);
DrawSolidBorderSegment(aContext, rect, PR_FALSE);
for (PRInt32 spaceY = 0; spaceY < numDashSpaces; spaceY++) {
rect.y += rect.height + dashLength;
rect.height = (spaceY == (numDashSpaces - 1)) ? endDashLength : dashLength;
DrawSolidBorderSegment(aContext, rect, PR_FALSE);
}
}
}
break;
case NS_STYLE_BORDER_STYLE_GROOVE:
ridgeGroove = NS_STYLE_BORDER_STYLE_GROOVE; // and fall through to ridge
case NS_STYLE_BORDER_STYLE_RIDGE:
if ((horizontal && (twipsPerPixel >= aBorder.height)) ||
(!horizontal && (twipsPerPixel >= aBorder.width))) {
// a one pixel border
DrawSolidBorderSegment(aContext, aBorder, twipsPerPixel, aStartBevelSide, aStartBevelOffset,
aEndBevelSide, aEndBevelOffset);
}
else {
nscoord startBevel = (aStartBevelOffset > 0)
? RoundFloatToPixel(0.5f * (float)aStartBevelOffset, twipsPerPixel, PR_TRUE) : 0;
nscoord endBevel = (aEndBevelOffset > 0)
? RoundFloatToPixel(0.5f * (float)aEndBevelOffset, twipsPerPixel, PR_TRUE) : 0;
PRUint8 ridgeGrooveSide = (horizontal) ? NS_SIDE_TOP : NS_SIDE_LEFT;
aContext.SetColor (
MakeBevelColor (ridgeGrooveSide, ridgeGroove, aBGColor->mBackgroundColor, aBorderColor, PR_TRUE));
nsRect rect(aBorder);
nscoord half;
if (horizontal) { // top, bottom
half = RoundFloatToPixel(0.5f * (float)aBorder.height, twipsPerPixel);
rect.height = half;
if (NS_SIDE_TOP == aStartBevelSide) {
rect.x += startBevel;
rect.width -= startBevel;
}
if (NS_SIDE_TOP == aEndBevelSide) {
rect.width -= endBevel;
}
DrawSolidBorderSegment(aContext, rect, twipsPerPixel, aStartBevelSide,
startBevel, aEndBevelSide, endBevel);
}
else { // left, right
half = RoundFloatToPixel(0.5f * (float)aBorder.width, twipsPerPixel);
rect.width = half;
if (NS_SIDE_LEFT == aStartBevelSide) {
rect.y += startBevel;
rect.height -= startBevel;
}
if (NS_SIDE_LEFT == aEndBevelSide) {
rect.height -= endBevel;
}
DrawSolidBorderSegment(aContext, rect, twipsPerPixel, aStartBevelSide,
startBevel, aEndBevelSide, endBevel);
}
rect = aBorder;
ridgeGrooveSide = (NS_SIDE_TOP == ridgeGrooveSide) ? NS_SIDE_BOTTOM : NS_SIDE_RIGHT;
aContext.SetColor (
MakeBevelColor (ridgeGrooveSide, ridgeGroove, aBGColor->mBackgroundColor, aBorderColor, PR_TRUE));
if (horizontal) {
rect.y = rect.y + half;
rect.height = aBorder.height - half;
if (NS_SIDE_BOTTOM == aStartBevelSide) {
rect.x += startBevel;
rect.width -= startBevel;
}
if (NS_SIDE_BOTTOM == aEndBevelSide) {
rect.width -= endBevel;
}
DrawSolidBorderSegment(aContext, rect, twipsPerPixel, aStartBevelSide,
startBevel, aEndBevelSide, endBevel);
}
else {
rect.x = rect.x + half;
rect.width = aBorder.width - half;
if (NS_SIDE_RIGHT == aStartBevelSide) {
rect.y += aStartBevelOffset - startBevel;
rect.height -= startBevel;
}
if (NS_SIDE_RIGHT == aEndBevelSide) {
rect.height -= endBevel;
}
DrawSolidBorderSegment(aContext, rect, twipsPerPixel, aStartBevelSide,
startBevel, aEndBevelSide, endBevel);
}
}
break;
case NS_STYLE_BORDER_STYLE_DOUBLE:
if ((aBorder.width > 2) && (aBorder.height > 2)) {
nscoord startBevel = (aStartBevelOffset > 0)
? RoundFloatToPixel(0.333333f * (float)aStartBevelOffset, twipsPerPixel) : 0;
nscoord endBevel = (aEndBevelOffset > 0)
? RoundFloatToPixel(0.333333f * (float)aEndBevelOffset, twipsPerPixel) : 0;
if (horizontal) { // top, bottom
nscoord thirdHeight = RoundFloatToPixel(0.333333f * (float)aBorder.height, twipsPerPixel);
// draw the top line or rect
nsRect topRect(aBorder.x, aBorder.y, aBorder.width, thirdHeight);
if (NS_SIDE_TOP == aStartBevelSide) {
topRect.x += aStartBevelOffset - startBevel;
topRect.width -= aStartBevelOffset - startBevel;
}
if (NS_SIDE_TOP == aEndBevelSide) {
topRect.width -= aEndBevelOffset - endBevel;
}
DrawSolidBorderSegment(aContext, topRect, twipsPerPixel, aStartBevelSide,
startBevel, aEndBevelSide, endBevel);
// draw the botom line or rect
nscoord heightOffset = aBorder.height - thirdHeight;
nsRect bottomRect(aBorder.x, aBorder.y + heightOffset, aBorder.width, aBorder.height - heightOffset);
if (NS_SIDE_BOTTOM == aStartBevelSide) {
bottomRect.x += aStartBevelOffset - startBevel;
bottomRect.width -= aStartBevelOffset - startBevel;
}
if (NS_SIDE_BOTTOM == aEndBevelSide) {
bottomRect.width -= aEndBevelOffset - endBevel;
}
DrawSolidBorderSegment(aContext, bottomRect, twipsPerPixel, aStartBevelSide,
startBevel, aEndBevelSide, endBevel);
}
else { // left, right
nscoord thirdWidth = RoundFloatToPixel(0.333333f * (float)aBorder.width, twipsPerPixel);
nsRect leftRect(aBorder.x, aBorder.y, thirdWidth, aBorder.height);
if (NS_SIDE_LEFT == aStartBevelSide) {
leftRect.y += aStartBevelOffset - startBevel;
leftRect.height -= aStartBevelOffset - startBevel;
}
if (NS_SIDE_LEFT == aEndBevelSide) {
leftRect.height -= aEndBevelOffset - endBevel;
}
DrawSolidBorderSegment(aContext, leftRect, twipsPerPixel, aStartBevelSide,
startBevel, aEndBevelSide, endBevel);
nscoord widthOffset = aBorder.width - thirdWidth;
nsRect rightRect(aBorder.x + widthOffset, aBorder.y, aBorder.width - widthOffset, aBorder.height);
if (NS_SIDE_RIGHT == aStartBevelSide) {
rightRect.y += aStartBevelOffset - startBevel;
rightRect.height -= aStartBevelOffset - startBevel;
}
if (NS_SIDE_RIGHT == aEndBevelSide) {
rightRect.height -= aEndBevelOffset - endBevel;
}
DrawSolidBorderSegment(aContext, rightRect, twipsPerPixel, aStartBevelSide,
startBevel, aEndBevelSide, endBevel);
}
break;
}
// else fall through to solid
case NS_STYLE_BORDER_STYLE_SOLID:
DrawSolidBorderSegment(aContext, aBorder, twipsPerPixel, aStartBevelSide,
aStartBevelOffset, aEndBevelSide, aEndBevelOffset);
break;
case NS_STYLE_BORDER_STYLE_BG_OUTSET:
case NS_STYLE_BORDER_STYLE_BG_INSET:
case NS_STYLE_BORDER_STYLE_OUTSET:
case NS_STYLE_BORDER_STYLE_INSET:
NS_ASSERTION(PR_FALSE, "inset, outset should have been converted to groove, ridge");
break;
}
}
// End table border-collapsing section

View File

@ -180,6 +180,17 @@ public:
PRIntn aSkipSides,
nsRect* aGap);
// Draw a border segment in the table collapsing border model without beveling corners
static void DrawTableBorderSegment(nsIRenderingContext& aContext,
PRUint8 aBorderStyle,
nscolor aBorderColor,
const nsStyleBackground* aBGColor,
const nsRect& aBorderRect,
float aPixelsToTwips,
PRUint8 aStartBevelSide = 0,
nscoord aStartBevelOffset = 0,
PRUint8 aEndBevelSide = 0,
nscoord aEndBevelOffset = 0);
/**
* transform a color to a color that will show up on a printer if needed
* aMapColor - color to evaluate

View File

@ -100,6 +100,7 @@ LAYOUT_ATOM(selectScrolledContentPseudo, ":-moz-select-scrolled-content")
// Alphabetical list of frame types
LAYOUT_ATOM(areaFrame, "AreaFrame")
LAYOUT_ATOM(bcTableCellFrame, "BCTableCellFrame") // table cell in border collapsing model
LAYOUT_ATOM(blockFrame, "BlockFrame")
LAYOUT_ATOM(boxFrame, "BoxFrame")
LAYOUT_ATOM(brFrame, "BRFrame")
@ -143,7 +144,8 @@ LAYOUT_ATOM(overflowProperty, "OverflowProperty") // list of nsIFra
LAYOUT_ATOM(overflowLinesProperty, "OverflowLinesProperty") // list of nsLineBox*
LAYOUT_ATOM(rowUnpaginatedHeightProperty, "RowUnpaginatedHeightProperty") // nscoord*
LAYOUT_ATOM(spaceManagerProperty, "SpaceManagerProperty") // the space manager for a block
LAYOUT_ATOM(viewProperty, "ViewProperty") // nsView*
LAYOUT_ATOM(tableBCProperty, "TableBCProperty") // table border collapsing info (e.g. damage area, table border widths)
LAYOUT_ATOM(viewProperty, "ViewProperty")
// Alphabetical list of event handler names
LAYOUT_ATOM(onabort, "onabort")

View File

@ -249,6 +249,9 @@
#define NS_STYLE_BORDER_STYLE_HIDDEN 10
#define NS_STYLE_BORDER_STYLE_BG_INSET 11
#define NS_STYLE_BORDER_STYLE_BG_OUTSET 12
// a bit ORed onto the style for table border collapsing indicating that the style was
// derived from a table with its rules attribute set
#define NS_STYLE_BORDER_STYLE_RULES_MASK 0x10
// See nsStyleDisplay
#define NS_STYLE_CLEAR_NONE 0

View File

@ -270,12 +270,13 @@ struct nsHTMLReflowState {
// Initialize a reflow state for a child frames reflow. Some state
// is copied from the parent reflow state; the remaining state is
// computed.
// computed.
nsHTMLReflowState(nsIPresContext* aPresContext,
const nsHTMLReflowState& aParentReflowState,
nsIFrame* aFrame,
const nsSize& aAvailableSpace,
nsReflowReason aReason);
nsReflowReason aReason,
PRBool aInit = PR_TRUE);
// Same as the previous except that the reason is taken from the
// parent's reflow state.
@ -293,6 +294,13 @@ struct nsHTMLReflowState {
nscoord aContainingBlockWidth,
nscoord aContainingBlockHeight);
// This method initializes various data members. It is automatically
// called by the various constructors
void Init(nsIPresContext* aPresContext,
nscoord aContainingBlockWidth = -1,
nscoord aContainingBlockHeight = -1,
nsMargin* aBorder = nsnull,
nsMargin* aPadding = nsnull);
/**
* Get the containing block reflow state, starting from a frames
* <B>parent</B> reflow state (the parent reflow state may or may not end
@ -352,15 +360,12 @@ struct nsHTMLReflowState {
protected:
// This method initializes various data members. It is automatically
// called by the various constructors
void Init(nsIPresContext* aPresContext,
nscoord aContainingBlockWidth = -1,
nscoord aContainingBlockHeight = -1);
void InitConstraints(nsIPresContext* aPresContext,
nscoord aContainingBlockWidth,
nscoord aContainingBlockHeight);
nscoord aContainingBlockHeight,
nsMargin* aBorder,
nsMargin* aPadding);
void CalculateHypotheticalBox(nsIPresContext* aPresContext,
nsIFrame* aPlaceholderFrame,

View File

@ -249,6 +249,9 @@
#define NS_STYLE_BORDER_STYLE_HIDDEN 10
#define NS_STYLE_BORDER_STYLE_BG_INSET 11
#define NS_STYLE_BORDER_STYLE_BG_OUTSET 12
// a bit ORed onto the style for table border collapsing indicating that the style was
// derived from a table with its rules attribute set
#define NS_STYLE_BORDER_STYLE_RULES_MASK 0x10
// See nsStyleDisplay
#define NS_STYLE_CLEAR_NONE 0

View File

@ -4646,6 +4646,7 @@ void DR_State::InitFrameTypeTable()
AddFrameTypeInfo(nsLayoutAtoms::scrollFrame, "scroll", "scroll");
AddFrameTypeInfo(nsLayoutAtoms::tableCaptionFrame, "caption", "tableCaption");
AddFrameTypeInfo(nsLayoutAtoms::tableCellFrame, "cell", "tableCell");
AddFrameTypeInfo(nsLayoutAtoms::bcTableCellFrame, "bcCell", "bcTableCell");
AddFrameTypeInfo(nsLayoutAtoms::tableColFrame, "col", "tableCol");
AddFrameTypeInfo(nsLayoutAtoms::tableColGroupFrame, "colG", "tableColGroup");
AddFrameTypeInfo(nsLayoutAtoms::tableFrame, "tbl", "table");

View File

@ -204,7 +204,7 @@ extern nsresult NS_NewTableColFrame(nsIPresShell* aPresShell, nsIFrame** aResult
extern nsresult NS_NewTableColGroupFrame(nsIPresShell* aPresShell, nsIFrame** aResult);
extern nsresult NS_NewTableRowFrame(nsIPresShell* aPresShell, nsIFrame** aResult);
extern nsresult NS_NewTableRowGroupFrame(nsIPresShell* aPresShell, nsIFrame** aResult);
extern nsresult NS_NewTableCellFrame(nsIPresShell* aPresShell, nsIFrame** aResult);
extern nsresult NS_NewTableCellFrame(nsIPresShell* aPresShell, PRBool aIsBorderCollapse, nsIFrame** aResult);
// XXX passing aWebShell into this is wrong
extern nsresult NS_NewHTMLContentSink(nsIHTMLContentSink** aInstancePtrResult,

View File

@ -51,6 +51,9 @@
#include "nsIPref.h"
#include "nsIServiceManager.h"
#define IS_TABLE_CELL(frameType)\
((nsLayoutAtoms::tableCellFrame == frameType) || (nsLayoutAtoms::bcTableCellFrame == frameType))
#ifdef NS_DEBUG
#undef NOISY_VERTICAL_ALIGN
#else
@ -140,7 +143,8 @@ nsHTMLReflowState::nsHTMLReflowState(nsIPresContext* aPresContext,
const nsHTMLReflowState& aParentReflowState,
nsIFrame* aFrame,
const nsSize& aAvailableSpace,
nsReflowReason aReason)
nsReflowReason aReason,
PRBool aInit)
: mReflowDepth(aParentReflowState.mReflowDepth + 1),
mFlags(aParentReflowState.mFlags)
{
@ -159,7 +163,9 @@ nsHTMLReflowState::nsHTMLReflowState(nsIPresContext* aPresContext,
mFlags.mIsTopOfPage = aParentReflowState.mFlags.mIsTopOfPage;
mPercentHeightObserver = aParentReflowState.mPercentHeightObserver;
Init(aPresContext);
if (aInit) {
Init(aPresContext);
}
#ifdef IBMBIDI
mRightEdge = aParentReflowState.mRightEdge;
@ -228,7 +234,9 @@ nsHTMLReflowState::nsHTMLReflowState(nsIPresContext* aPresContext,
void
nsHTMLReflowState::Init(nsIPresContext* aPresContext,
nscoord aContainingBlockWidth,
nscoord aContainingBlockHeight)
nscoord aContainingBlockHeight,
nsMargin* aBorder,
nsMargin* aPadding)
{
mCompactMarginWidth = 0;
#ifdef DEBUG
@ -244,7 +252,7 @@ nsHTMLReflowState::Init(nsIPresContext* aPresContext,
GetStyleData(frame, &mStyleText);
mFrameType = DetermineFrameType(frame, mStyleDisplay);
InitConstraints(aPresContext, aContainingBlockWidth, aContainingBlockHeight);
InitConstraints(aPresContext, aContainingBlockWidth, aContainingBlockHeight, aBorder, aPadding);
}
const nsHTMLReflowState*
@ -261,7 +269,7 @@ nsHTMLReflowState::GetContainingBlockReflowState(const nsHTMLReflowState* aParen
if (aParentRS->parentReflowState) {
nsCOMPtr<nsIAtom> fType;
aParentRS->parentReflowState->frame->GetFrameType(getter_AddRefs(fType));
if (nsLayoutAtoms::tableCellFrame == fType.get()) {
if (IS_TABLE_CELL(fType.get())) {
aParentRS = aParentRS->parentReflowState;
}
}
@ -1575,7 +1583,9 @@ static PRBool BlinkIsAllowed(void)
void
nsHTMLReflowState::InitConstraints(nsIPresContext* aPresContext,
nscoord aContainingBlockWidth,
nscoord aContainingBlockHeight)
nscoord aContainingBlockHeight,
nsMargin* aBorder,
nsMargin* aPadding)
{
// If this is the root frame, then set the computed width and
// height equal to the available space
@ -1633,7 +1643,7 @@ nsHTMLReflowState::InitConstraints(nsIPresContext* aPresContext,
}
else {
cbrs->frame->GetFrameType(getter_AddRefs(fType));
if (nsLayoutAtoms::tableCellFrame == fType.get()) {
if (IS_TABLE_CELL(fType.get())) {
// use the cell's computed height
aContainingBlockHeight =
((nsHTMLReflowState*)cbrs)->mComputedHeight;
@ -1647,10 +1657,26 @@ nsHTMLReflowState::InitConstraints(nsIPresContext* aPresContext,
// XXX fix to provide 0,0 for the top&bottom margins for
// inline-non-replaced elements
ComputeMargin(aContainingBlockWidth, cbrs);
ComputePadding(aContainingBlockWidth, cbrs);
if (!mStyleBorder->GetBorder(mComputedBorderPadding)) {
// CSS2 has no percentage borders
mComputedBorderPadding.SizeTo(0, 0, 0, 0);
if (aPadding) { // padding is an input arg
mComputedPadding.top = aPadding->top;
mComputedPadding.right = aPadding->right;
mComputedPadding.bottom = aPadding->bottom;
mComputedPadding.left = aPadding->left;
}
else {
ComputePadding(aContainingBlockWidth, cbrs);
}
if (aBorder) { // border is an input arg
mComputedBorderPadding.top = aBorder->top;
mComputedBorderPadding.right = aBorder->right;
mComputedBorderPadding.bottom = aBorder->bottom;
mComputedBorderPadding.left = aBorder->left;
}
else {
if (!mStyleBorder->GetBorder(mComputedBorderPadding)) {
// CSS2 has no percentage borders
mComputedBorderPadding.SizeTo(0, 0, 0, 0);
}
}
mComputedBorderPadding += mComputedPadding;

View File

@ -270,12 +270,13 @@ struct nsHTMLReflowState {
// Initialize a reflow state for a child frames reflow. Some state
// is copied from the parent reflow state; the remaining state is
// computed.
// computed.
nsHTMLReflowState(nsIPresContext* aPresContext,
const nsHTMLReflowState& aParentReflowState,
nsIFrame* aFrame,
const nsSize& aAvailableSpace,
nsReflowReason aReason);
nsReflowReason aReason,
PRBool aInit = PR_TRUE);
// Same as the previous except that the reason is taken from the
// parent's reflow state.
@ -293,6 +294,13 @@ struct nsHTMLReflowState {
nscoord aContainingBlockWidth,
nscoord aContainingBlockHeight);
// This method initializes various data members. It is automatically
// called by the various constructors
void Init(nsIPresContext* aPresContext,
nscoord aContainingBlockWidth = -1,
nscoord aContainingBlockHeight = -1,
nsMargin* aBorder = nsnull,
nsMargin* aPadding = nsnull);
/**
* Get the containing block reflow state, starting from a frames
* <B>parent</B> reflow state (the parent reflow state may or may not end
@ -352,15 +360,12 @@ struct nsHTMLReflowState {
protected:
// This method initializes various data members. It is automatically
// called by the various constructors
void Init(nsIPresContext* aPresContext,
nscoord aContainingBlockWidth = -1,
nscoord aContainingBlockHeight = -1);
void InitConstraints(nsIPresContext* aPresContext,
nscoord aContainingBlockWidth,
nscoord aContainingBlockHeight);
nscoord aContainingBlockHeight,
nsMargin* aBorder,
nsMargin* aPadding);
void CalculateHypotheticalBox(nsIPresContext* aPresContext,
nsIFrame* aPlaceholderFrame,

View File

@ -4646,6 +4646,7 @@ void DR_State::InitFrameTypeTable()
AddFrameTypeInfo(nsLayoutAtoms::scrollFrame, "scroll", "scroll");
AddFrameTypeInfo(nsLayoutAtoms::tableCaptionFrame, "caption", "tableCaption");
AddFrameTypeInfo(nsLayoutAtoms::tableCellFrame, "cell", "tableCell");
AddFrameTypeInfo(nsLayoutAtoms::bcTableCellFrame, "bcCell", "bcTableCell");
AddFrameTypeInfo(nsLayoutAtoms::tableColFrame, "col", "tableCol");
AddFrameTypeInfo(nsLayoutAtoms::tableColGroupFrame, "colG", "tableColGroup");
AddFrameTypeInfo(nsLayoutAtoms::tableFrame, "tbl", "table");

View File

@ -204,7 +204,7 @@ extern nsresult NS_NewTableColFrame(nsIPresShell* aPresShell, nsIFrame** aResult
extern nsresult NS_NewTableColGroupFrame(nsIPresShell* aPresShell, nsIFrame** aResult);
extern nsresult NS_NewTableRowFrame(nsIPresShell* aPresShell, nsIFrame** aResult);
extern nsresult NS_NewTableRowGroupFrame(nsIPresShell* aPresShell, nsIFrame** aResult);
extern nsresult NS_NewTableCellFrame(nsIPresShell* aPresShell, nsIFrame** aResult);
extern nsresult NS_NewTableCellFrame(nsIPresShell* aPresShell, PRBool aIsBorderCollapse, nsIFrame** aResult);
// XXX passing aWebShell into this is wrong
extern nsresult NS_NewHTMLContentSink(nsIHTMLContentSink** aInstancePtrResult,

View File

@ -51,6 +51,9 @@
#include "nsIPref.h"
#include "nsIServiceManager.h"
#define IS_TABLE_CELL(frameType)\
((nsLayoutAtoms::tableCellFrame == frameType) || (nsLayoutAtoms::bcTableCellFrame == frameType))
#ifdef NS_DEBUG
#undef NOISY_VERTICAL_ALIGN
#else
@ -140,7 +143,8 @@ nsHTMLReflowState::nsHTMLReflowState(nsIPresContext* aPresContext,
const nsHTMLReflowState& aParentReflowState,
nsIFrame* aFrame,
const nsSize& aAvailableSpace,
nsReflowReason aReason)
nsReflowReason aReason,
PRBool aInit)
: mReflowDepth(aParentReflowState.mReflowDepth + 1),
mFlags(aParentReflowState.mFlags)
{
@ -159,7 +163,9 @@ nsHTMLReflowState::nsHTMLReflowState(nsIPresContext* aPresContext,
mFlags.mIsTopOfPage = aParentReflowState.mFlags.mIsTopOfPage;
mPercentHeightObserver = aParentReflowState.mPercentHeightObserver;
Init(aPresContext);
if (aInit) {
Init(aPresContext);
}
#ifdef IBMBIDI
mRightEdge = aParentReflowState.mRightEdge;
@ -228,7 +234,9 @@ nsHTMLReflowState::nsHTMLReflowState(nsIPresContext* aPresContext,
void
nsHTMLReflowState::Init(nsIPresContext* aPresContext,
nscoord aContainingBlockWidth,
nscoord aContainingBlockHeight)
nscoord aContainingBlockHeight,
nsMargin* aBorder,
nsMargin* aPadding)
{
mCompactMarginWidth = 0;
#ifdef DEBUG
@ -244,7 +252,7 @@ nsHTMLReflowState::Init(nsIPresContext* aPresContext,
GetStyleData(frame, &mStyleText);
mFrameType = DetermineFrameType(frame, mStyleDisplay);
InitConstraints(aPresContext, aContainingBlockWidth, aContainingBlockHeight);
InitConstraints(aPresContext, aContainingBlockWidth, aContainingBlockHeight, aBorder, aPadding);
}
const nsHTMLReflowState*
@ -261,7 +269,7 @@ nsHTMLReflowState::GetContainingBlockReflowState(const nsHTMLReflowState* aParen
if (aParentRS->parentReflowState) {
nsCOMPtr<nsIAtom> fType;
aParentRS->parentReflowState->frame->GetFrameType(getter_AddRefs(fType));
if (nsLayoutAtoms::tableCellFrame == fType.get()) {
if (IS_TABLE_CELL(fType.get())) {
aParentRS = aParentRS->parentReflowState;
}
}
@ -1575,7 +1583,9 @@ static PRBool BlinkIsAllowed(void)
void
nsHTMLReflowState::InitConstraints(nsIPresContext* aPresContext,
nscoord aContainingBlockWidth,
nscoord aContainingBlockHeight)
nscoord aContainingBlockHeight,
nsMargin* aBorder,
nsMargin* aPadding)
{
// If this is the root frame, then set the computed width and
// height equal to the available space
@ -1633,7 +1643,7 @@ nsHTMLReflowState::InitConstraints(nsIPresContext* aPresContext,
}
else {
cbrs->frame->GetFrameType(getter_AddRefs(fType));
if (nsLayoutAtoms::tableCellFrame == fType.get()) {
if (IS_TABLE_CELL(fType.get())) {
// use the cell's computed height
aContainingBlockHeight =
((nsHTMLReflowState*)cbrs)->mComputedHeight;
@ -1647,10 +1657,26 @@ nsHTMLReflowState::InitConstraints(nsIPresContext* aPresContext,
// XXX fix to provide 0,0 for the top&bottom margins for
// inline-non-replaced elements
ComputeMargin(aContainingBlockWidth, cbrs);
ComputePadding(aContainingBlockWidth, cbrs);
if (!mStyleBorder->GetBorder(mComputedBorderPadding)) {
// CSS2 has no percentage borders
mComputedBorderPadding.SizeTo(0, 0, 0, 0);
if (aPadding) { // padding is an input arg
mComputedPadding.top = aPadding->top;
mComputedPadding.right = aPadding->right;
mComputedPadding.bottom = aPadding->bottom;
mComputedPadding.left = aPadding->left;
}
else {
ComputePadding(aContainingBlockWidth, cbrs);
}
if (aBorder) { // border is an input arg
mComputedBorderPadding.top = aBorder->top;
mComputedBorderPadding.right = aBorder->right;
mComputedBorderPadding.bottom = aBorder->bottom;
mComputedBorderPadding.left = aBorder->left;
}
else {
if (!mStyleBorder->GetBorder(mComputedBorderPadding)) {
// CSS2 has no percentage borders
mComputedBorderPadding.SizeTo(0, 0, 0, 0);
}
}
mComputedBorderPadding += mComputedPadding;

View File

@ -168,6 +168,10 @@ table[align="right"] {
text-align: start;
}
table[rules] {
border-collapse: collapse;
}
*|*:table-outer {
display: table;
margin: 0;
@ -219,6 +223,11 @@ tr {
col, *|*:table-column {
display: table-column;
border: inherit;
width: inherit;
height: inherit;
background: inherit;
border: inherit;
}
colgroup, *|*:table-column-group {

View File

@ -52,8 +52,11 @@
#include "nsIPresContext.h"
#include "nsILinkHandler.h"
#include "nsIDocument.h"
#include "nsTableFrame.h"
#include "nsTableColGroupFrame.h"
#include "nsTableColFrame.h"
#include "nsIDOMHTMLTableColElement.h"
#include "nsTableCellFrame.h" // to get IS_CELL_FRAME
#include "nsHTMLIIDs.h"
#include "nsIStyleFrameConstruction.h"
#include "nsHTMLParts.h"
@ -859,6 +862,23 @@ nsFrameConstructorSaveState::~nsFrameConstructorSaveState()
}
}
static
PRBool IsBorderCollapse(nsIFrame* aFrame)
{
nsIFrame* frame = aFrame;
while (frame) {
nsCOMPtr<nsIAtom> fType;
frame->GetFrameType(getter_AddRefs(fType));
if (nsLayoutAtoms::tableFrame == fType.get()) {
return ((nsTableFrame*)frame)->IsBorderCollapse();
}
frame->GetParent(&frame);
}
NS_ASSERTION(PR_FALSE, "program error");
return PR_FALSE;
}
// -----------------------------------------------------------
// Structure used when creating table frames.
@ -870,7 +890,7 @@ struct nsTableCreator {
virtual nsresult CreateTableColFrame(nsIFrame** aNewFrame);
virtual nsresult CreateTableColGroupFrame(nsIFrame** aNewFrame);
virtual nsresult CreateTableRowFrame(nsIFrame** aNewFrame);
virtual nsresult CreateTableCellFrame(nsIFrame** aNewFrame);
virtual nsresult CreateTableCellFrame(nsIFrame* aParentFrame, nsIFrame** aNewFrame);
virtual nsresult CreateTableCellInnerFrame(nsIFrame** aNewFrame);
nsTableCreator(nsIPresShell* aPresShell)
@ -919,8 +939,9 @@ nsTableCreator::CreateTableRowFrame(nsIFrame** aNewFrame) {
}
nsresult
nsTableCreator::CreateTableCellFrame(nsIFrame** aNewFrame) {
return NS_NewTableCellFrame(mPresShell, aNewFrame);
nsTableCreator::CreateTableCellFrame(nsIFrame* aParentFrame,
nsIFrame** aNewFrame) {
return NS_NewTableCellFrame(mPresShell, IsBorderCollapse(aParentFrame), aNewFrame);
}
nsresult
@ -1527,7 +1548,7 @@ IsTableRelated(nsIAtom* aParentType,
((nsLayoutAtoms::tableCaptionFrame == aParentType) ||
(nsLayoutAtoms::tableColGroupFrame == aParentType) ||
(nsLayoutAtoms::tableColFrame == aParentType) ||
(nsLayoutAtoms::tableCellFrame == aParentType))) {
IS_TABLE_CELL(aParentType))) {
return PR_TRUE;
}
else return PR_FALSE;
@ -1629,7 +1650,7 @@ ProcessPseudoFrames(nsIPresContext* aPresContext,
if (aPseudoFrames.mCellOuter.mFrame) {
rv = ProcessPseudoCellFrame(aPresContext, aPseudoFrames, aHighestFrame);
if (nsLayoutAtoms::tableCellFrame == aHighestType) return rv;
if (IS_TABLE_CELL(aHighestType)) return rv;
}
if (aPseudoFrames.mRow.mFrame) {
rv = ProcessPseudoFrame(aPresContext, aPseudoFrames.mRow, aHighestFrame);
@ -1650,7 +1671,7 @@ ProcessPseudoFrames(nsIPresContext* aPresContext,
}
if (aPseudoFrames.mCellOuter.mFrame) {
rv = ProcessPseudoCellFrame(aPresContext, aPseudoFrames, aHighestFrame);
if (nsLayoutAtoms::tableCellFrame == aHighestType) return rv;
if (IS_TABLE_CELL(aHighestType)) return rv;
}
if (aPseudoFrames.mRow.mFrame) {
rv = ProcessPseudoFrame(aPresContext, aPseudoFrames.mRow, aHighestFrame);
@ -1671,12 +1692,12 @@ ProcessPseudoFrames(nsIPresContext* aPresContext,
}
if (aPseudoFrames.mCellOuter.mFrame) {
rv = ProcessPseudoCellFrame(aPresContext, aPseudoFrames, aHighestFrame);
if (nsLayoutAtoms::tableCellFrame == aHighestType) return rv;
if (IS_TABLE_CELL(aHighestType)) return rv;
}
}
else if (nsLayoutAtoms::tableCellFrame == aPseudoFrames.mLowestType) {
else if (IS_TABLE_CELL(aPseudoFrames.mLowestType)) {
rv = ProcessPseudoCellFrame(aPresContext, aPseudoFrames, aHighestFrame);
if (nsLayoutAtoms::tableCellFrame == aHighestType) return rv;
if (IS_TABLE_CELL(aHighestType)) return rv;
if (aPseudoFrames.mRow.mFrame) {
rv = ProcessPseudoFrame(aPresContext, aPseudoFrames.mRow, aHighestFrame);
@ -1942,6 +1963,7 @@ nsCSSFrameConstructor::CreatePseudoCellFrame(nsIPresShell* aPresShell
// set pseudo data for the newly created frames
pseudoOuter.mChildList.AddChild(pseudoInner.mFrame);
// give it nsLayoutAtoms::tableCellFrame, if it is really nsLayoutAtoms::bcTableCellFrame, it will match later
aState.mPseudoFrames.mLowestType = nsLayoutAtoms::tableCellFrame;
// set pseudo data for the parent
@ -2021,7 +2043,7 @@ nsCSSFrameConstructor::GetPseudoColGroupFrame(nsIPresShell* aPresShel
rv = CreatePseudoCellFrame(aPresShell, aPresContext, aTableCreator, aState, &aParentFrameIn);
created = PR_TRUE;
}
if (created || (nsLayoutAtoms::tableCellFrame == parentFrameType.get()) || // cell parent
if (created || IS_TABLE_CELL(parentFrameType.get()) || // cell parent
!IsTableRelated(parentFrameType.get(), PR_TRUE)) { // block parent
rv = CreatePseudoTableFrame(aPresShell, aPresContext, aTableCreator, aState, &aParentFrameIn);
}
@ -2065,7 +2087,7 @@ nsCSSFrameConstructor::GetPseudoRowGroupFrame(nsIPresShell* aPresShel
rv = CreatePseudoCellFrame(aPresShell, aPresContext, aTableCreator, aState, &aParentFrameIn);
created = PR_TRUE;
}
if (created || (nsLayoutAtoms::tableCellFrame == parentFrameType.get()) || // cell parent
if (created || IS_TABLE_CELL(parentFrameType.get()) || // cell parent
!IsTableRelated(parentFrameType.get(), PR_TRUE)) { // block parent
rv = CreatePseudoTableFrame(aPresShell, aPresContext, aTableCreator, aState, &aParentFrameIn);
}
@ -2102,7 +2124,7 @@ nsCSSFrameConstructor::GetPseudoRowFrame(nsIPresShell* aPresShell,
if (pseudoFrames.IsEmpty()) {
PRBool created = PR_FALSE;
if ((nsLayoutAtoms::tableCellFrame == parentFrameType.get()) || // cell parent
if (IS_TABLE_CELL(parentFrameType.get()) || // cell parent
!IsTableRelated(parentFrameType.get(), PR_TRUE)) { // block parent
rv = CreatePseudoTableFrame(aPresShell, aPresContext, aTableCreator, aState, &aParentFrameIn);
created = PR_TRUE;
@ -2230,7 +2252,7 @@ nsCSSFrameConstructor::GetParentFrame(nsIPresShell* aPresShell,
pseudoParentFrame = pseudoFrames.mRowGroup.mFrame;
}
}
else if (nsLayoutAtoms::tableCellFrame == aChildFrameType) { // cell child
else if (IS_TABLE_CELL(aChildFrameType)) { // cell child
if (nsLayoutAtoms::tableRowFrame != parentFrameType.get()) { // need pseudo row parent
rv = GetPseudoRowFrame(aPresShell, aPresContext, aTableCreator, aState, aParentFrameIn);
if (NS_FAILED(rv)) return rv;
@ -2572,7 +2594,7 @@ nsCSSFrameConstructor::ConstructTableColFrame(nsIPresShell* aPresShel
PRBool& aIsPseudoParent)
{
nsresult rv = NS_OK;
if (!aPresShell || !aPresContext || !aParentFrameIn) return rv;
if (!aPresShell || !aPresContext || !aParentFrameIn || !aStyleContext) return rv;
nsIFrame* parentFrame = aParentFrameIn;
aIsPseudoParent = PR_FALSE;
@ -2585,16 +2607,42 @@ nsCSSFrameConstructor::ConstructTableColFrame(nsIPresShell* aPresShel
}
}
rv = aTableCreator.CreateTableColFrame(&aNewFrame);
if (NS_FAILED(rv)) return rv;
InitAndRestoreFrame(aPresContext, aState, aContent,
parentFrame, aStyleContext, nsnull, aNewFrame);
rv = aTableCreator.CreateTableColFrame(&aNewFrame); if (NS_FAILED(rv)) return rv;
InitAndRestoreFrame(aPresContext, aState, aContent, parentFrame, aStyleContext, nsnull, aNewFrame);
// if the parent frame was anonymous then reparent the style context
nsCOMPtr<nsIStyleContext> parentStyleContext;
parentFrame->GetStyleContext(getter_AddRefs(parentStyleContext));
if (aIsPseudoParent) {
aPresContext->ReParentStyleContext(aNewFrame, parentStyleContext);
}
// construct additional col frames if the col frame has a span > 1
PRInt32 span = 1;
nsCOMPtr<nsIDOMHTMLTableColElement> cgContent(do_QueryInterface(aContent));
if (cgContent) {
cgContent->GetSpan(&span);
nsIFrame* lastCol = aNewFrame;
for (PRInt32 spanX = 1; spanX < span; spanX++) {
nsCOMPtr<nsIStyleContext> styleContext;
aPresContext->ResolvePseudoStyleContextFor(aContent, nsHTMLAtoms::tableColPseudo, aStyleContext,
PR_FALSE, getter_AddRefs(styleContext));
nsIFrame* newCol;
rv = aTableCreator.CreateTableColFrame(&newCol); if (NS_FAILED(rv)) return rv;
InitAndRestoreFrame(aPresContext, aState, aContent, parentFrame, styleContext, nsnull, newCol);
if (aIsPseudoParent) {
aPresContext->ReParentStyleContext(newCol, aStyleContext);
}
((nsTableColFrame*)newCol)->SetType(eColAnonymousCol);
lastCol->SetNextSibling(newCol);
lastCol = newCol;
}
}
if (!aIsPseudo) {
nsFrameItems childItems;
nsIFrame* captionFrame;
rv = TableProcessChildren(aPresShell, aPresContext, aState, aContent, aNewFrame,
aTableCreator, childItems, captionFrame);
if (NS_FAILED(rv)) return rv;
aTableCreator, childItems, captionFrame); if (NS_FAILED(rv)) return rv;
aNewFrame->SetInitialChildList(aPresContext, nsnull, childItems.childList);
if (aIsPseudoParent) {
aState.mPseudoFrames.mColGroup.mChildList.AddChild(aNewFrame);
@ -2625,6 +2673,7 @@ nsCSSFrameConstructor::ConstructTableCellFrame(nsIPresShell* aPresShe
aIsPseudoParent = PR_FALSE;
if (!aIsPseudo) {
// this frame may have a pseudo parent
// use nsLayoutAtoms::tableCellFrame which will match if it is really nsLayoutAtoms::bcTableCellFrame
GetParentFrame(aPresShell, aPresContext, aTableCreator, *aParentFrameIn,
nsLayoutAtoms::tableCellFrame, aState, parentFrame, aIsPseudoParent);
if (!aIsPseudoParent && !aState.mPseudoFrames.IsEmpty()) {
@ -2635,7 +2684,7 @@ nsCSSFrameConstructor::ConstructTableCellFrame(nsIPresShell* aPresShe
}
}
rv = aTableCreator.CreateTableCellFrame(&aNewCellOuterFrame);
rv = aTableCreator.CreateTableCellFrame(parentFrame, &aNewCellOuterFrame);
if (NS_FAILED(rv)) return rv;
// Initialize the table cell frame
@ -11328,7 +11377,7 @@ nsCSSFrameConstructor::CreateContinuingFrame(nsIPresShell* aPresShell,
// See if it's a table cell frame
cellFrame->GetFrameType(&tableType);
if (nsLayoutAtoms::tableCellFrame == tableType) {
if (IS_TABLE_CELL(tableType)) {
nsIFrame* continuingCellFrame;
CreateContinuingFrame(aPresShell, aPresContext, cellFrame, newFrame, &continuingCellFrame);
@ -11343,8 +11392,8 @@ nsCSSFrameConstructor::CreateContinuingFrame(nsIPresShell* aPresShell,
newFrame->SetInitialChildList(aPresContext, nsnull, newChildList.childList);
}
} else if (nsLayoutAtoms::tableCellFrame == frameType) {
rv = NS_NewTableCellFrame(aPresShell, &newFrame);
} else if (IS_TABLE_CELL(frameType)) {
rv = NS_NewTableCellFrame(aPresShell, IsBorderCollapse(aParentFrame), &newFrame);
if (NS_SUCCEEDED(rv)) {
newFrame->Init(aPresContext, content, aParentFrame, styleContext, aFrame);
nsHTMLContainerFrame::CreateViewForFrame(aPresContext, newFrame,

View File

@ -514,6 +514,7 @@ void nsCSSRendering::DrawSide(nsIRenderingContext& aContext,
}
}
/**
* Draw a dotted/dashed sides of a box
*/
@ -3821,3 +3822,356 @@ void FillOrInvertRect(nsIRenderingContext& aRC, const nsRect& aRect, PRBool aInv
}
}
// Begin table border-collapsing section
// These functions were written to not disrupt the normal ones and yet satisfy some additional requirements
// At some point, all functions should be unified to include the additional functionality that these provide
static nscoord
RoundIntToPixel(nscoord aValue,
nscoord aTwipsPerPixel,
PRBool aRoundDown = PR_FALSE)
{
nscoord halfPixel = NSToCoordRound(aTwipsPerPixel / 2.0f);
nscoord extra = aValue % aTwipsPerPixel;
nscoord finalValue = (!aRoundDown && (extra >= halfPixel)) ? aValue + (aTwipsPerPixel - extra) : aValue - extra;
return finalValue;
}
static nscoord
RoundFloatToPixel(float aValue,
nscoord aTwipsPerPixel,
PRBool aRoundDown = PR_FALSE)
{
return RoundIntToPixel(NSToCoordRound(aValue), aTwipsPerPixel, aRoundDown);
}
static void
SetPoly(const nsRect& aRect,
nsPoint* poly)
{
poly[0].x = aRect.x;
poly[0].y = aRect.y;
poly[1].x = aRect.x + aRect.width;
poly[1].y = aRect.y;
poly[2].x = aRect.x + aRect.width;
poly[2].y = aRect.y + aRect.height;
poly[3].x = aRect.x;
poly[3].y = aRect.y + aRect.height;
poly[4].x = aRect.x;
poly[4].y = aRect.y;
}
static void
DrawSolidBorderSegment(nsIRenderingContext& aContext,
nsRect aRect,
nscoord aTwipsPerPixel,
PRUint8 aStartBevelSide = 0,
nscoord aStartBevelOffset = 0,
PRUint8 aEndBevelSide = 0,
nscoord aEndBevelOffset = 0)
{
if ((aRect.width == aTwipsPerPixel) || (aRect.height == aTwipsPerPixel) ||
((0 == aStartBevelOffset) && (0 == aEndBevelOffset))) {
// simple line or rectangle
if ((NS_SIDE_TOP == aStartBevelSide) || (NS_SIDE_BOTTOM == aStartBevelSide)) {
if (1 == aRect.height)
aContext.DrawLine(aRect.x, aRect.y, aRect.x, aRect.y + aRect.height);
else
aContext.FillRect(aRect);
}
else {
if (1 == aRect.width)
aContext.DrawLine(aRect.x, aRect.y, aRect.x + aRect.width, aRect.y);
else
aContext.FillRect(aRect);
}
}
else {
// polygon with beveling
nsPoint poly[5];
SetPoly(aRect, poly);
switch(aStartBevelSide) {
case NS_SIDE_TOP:
poly[0].x += aStartBevelOffset;
poly[4].x = poly[0].x;
break;
case NS_SIDE_BOTTOM:
poly[3].x += aStartBevelOffset;
break;
case NS_SIDE_RIGHT:
poly[1].y += aStartBevelOffset;
break;
case NS_SIDE_LEFT:
poly[0].y += aStartBevelOffset;
poly[4].y = poly[0].y;
}
switch(aEndBevelSide) {
case NS_SIDE_TOP:
poly[1].x -= aEndBevelOffset;
break;
case NS_SIDE_BOTTOM:
poly[2].x -= aEndBevelOffset;
break;
case NS_SIDE_RIGHT:
poly[2].y -= aEndBevelOffset;
break;
case NS_SIDE_LEFT:
poly[3].y -= aEndBevelOffset;
}
aContext.FillPolygon(poly, 5);
}
}
static void
GetDashInfo(nscoord aBorderLength,
nscoord aDashLength,
nscoord aTwipsPerPixel,
PRInt32& aNumDashSpaces,
nscoord& aStartDashLength,
nscoord& aEndDashLength)
{
aNumDashSpaces = 0;
if (aStartDashLength + aDashLength + aEndDashLength >= aBorderLength) {
aStartDashLength = aBorderLength;
aEndDashLength = 0;
}
else {
aNumDashSpaces = aBorderLength / (2 * aDashLength); // round down
nscoord foo = ((2 * aNumDashSpaces) - 1) * aDashLength;
nscoord extra = aBorderLength - aStartDashLength - aEndDashLength - (((2 * aNumDashSpaces) - 1) * aDashLength);
if (extra > 0) {
nscoord half = RoundIntToPixel(extra / 2, aTwipsPerPixel);
aStartDashLength += half;
aEndDashLength += (extra - half);
}
}
}
void
nsCSSRendering::DrawTableBorderSegment(nsIRenderingContext& aContext,
PRUint8 aBorderStyle,
nscolor aBorderColor,
const nsStyleBackground* aBGColor,
const nsRect& aBorder,
float aPixelsToTwips,
PRUint8 aStartBevelSide,
nscoord aStartBevelOffset,
PRUint8 aEndBevelSide,
nscoord aEndBevelOffset)
{
aContext.SetColor (aBorderColor);
PRBool horizontal = ((NS_SIDE_TOP == aStartBevelSide) || (NS_SIDE_BOTTOM == aStartBevelSide));
nscoord twipsPerPixel = NSIntPixelsToTwips(1, aPixelsToTwips);
PRBool ridgeGroove = NS_STYLE_BORDER_STYLE_RIDGE;
if ((twipsPerPixel >= aBorder.width) || (twipsPerPixel >= aBorder.height) ||
(NS_STYLE_BORDER_STYLE_DASHED == aBorderStyle) || (NS_STYLE_BORDER_STYLE_DOTTED == aBorderStyle)) {
// no beveling for 1 pixel border, dash or dot
aStartBevelOffset = 0;
aEndBevelOffset = 0;
}
switch (aBorderStyle) {
case NS_STYLE_BORDER_STYLE_NONE:
case NS_STYLE_BORDER_STYLE_HIDDEN:
case NS_STYLE_BORDER_STYLE_BLANK:
//NS_ASSERTION(PR_FALSE, "style of none, hidden, or blank");
break;
case NS_STYLE_BORDER_STYLE_DOTTED:
case NS_STYLE_BORDER_STYLE_DASHED:
{
nscoord dashLength = (NS_STYLE_BORDER_STYLE_DASHED == aBorderStyle) ? DASH_LENGTH : DOT_LENGTH;
// make the dash length proportional to the border thickness
dashLength *= (horizontal) ? aBorder.height : aBorder.width;
// make the min dash length for the ends 1/2 the dash length
nscoord minDashLength = (NS_STYLE_BORDER_STYLE_DASHED == aBorderStyle)
? RoundFloatToPixel(((float)dashLength) / 2.0f, twipsPerPixel) : dashLength;
minDashLength = PR_MAX(minDashLength, twipsPerPixel);
nscoord numDashSpaces = 0;
nscoord startDashLength = minDashLength;
nscoord endDashLength = minDashLength;
if (horizontal) {
GetDashInfo(aBorder.width, dashLength, twipsPerPixel, numDashSpaces, startDashLength, endDashLength);
nsRect rect(aBorder.x, aBorder.y, startDashLength, aBorder.height);
DrawSolidBorderSegment(aContext, rect, PR_TRUE);
for (PRInt32 spaceX = 0; spaceX < numDashSpaces; spaceX++) {
rect.x += rect.width + dashLength;
rect.width = (spaceX == (numDashSpaces - 1)) ? endDashLength : dashLength;
DrawSolidBorderSegment(aContext, rect, PR_TRUE);
}
}
else {
GetDashInfo(aBorder.height, dashLength, twipsPerPixel, numDashSpaces, startDashLength, endDashLength);
nsRect rect(aBorder.x, aBorder.y, aBorder.width, startDashLength);
DrawSolidBorderSegment(aContext, rect, PR_FALSE);
for (PRInt32 spaceY = 0; spaceY < numDashSpaces; spaceY++) {
rect.y += rect.height + dashLength;
rect.height = (spaceY == (numDashSpaces - 1)) ? endDashLength : dashLength;
DrawSolidBorderSegment(aContext, rect, PR_FALSE);
}
}
}
break;
case NS_STYLE_BORDER_STYLE_GROOVE:
ridgeGroove = NS_STYLE_BORDER_STYLE_GROOVE; // and fall through to ridge
case NS_STYLE_BORDER_STYLE_RIDGE:
if ((horizontal && (twipsPerPixel >= aBorder.height)) ||
(!horizontal && (twipsPerPixel >= aBorder.width))) {
// a one pixel border
DrawSolidBorderSegment(aContext, aBorder, twipsPerPixel, aStartBevelSide, aStartBevelOffset,
aEndBevelSide, aEndBevelOffset);
}
else {
nscoord startBevel = (aStartBevelOffset > 0)
? RoundFloatToPixel(0.5f * (float)aStartBevelOffset, twipsPerPixel, PR_TRUE) : 0;
nscoord endBevel = (aEndBevelOffset > 0)
? RoundFloatToPixel(0.5f * (float)aEndBevelOffset, twipsPerPixel, PR_TRUE) : 0;
PRUint8 ridgeGrooveSide = (horizontal) ? NS_SIDE_TOP : NS_SIDE_LEFT;
aContext.SetColor (
MakeBevelColor (ridgeGrooveSide, ridgeGroove, aBGColor->mBackgroundColor, aBorderColor, PR_TRUE));
nsRect rect(aBorder);
nscoord half;
if (horizontal) { // top, bottom
half = RoundFloatToPixel(0.5f * (float)aBorder.height, twipsPerPixel);
rect.height = half;
if (NS_SIDE_TOP == aStartBevelSide) {
rect.x += startBevel;
rect.width -= startBevel;
}
if (NS_SIDE_TOP == aEndBevelSide) {
rect.width -= endBevel;
}
DrawSolidBorderSegment(aContext, rect, twipsPerPixel, aStartBevelSide,
startBevel, aEndBevelSide, endBevel);
}
else { // left, right
half = RoundFloatToPixel(0.5f * (float)aBorder.width, twipsPerPixel);
rect.width = half;
if (NS_SIDE_LEFT == aStartBevelSide) {
rect.y += startBevel;
rect.height -= startBevel;
}
if (NS_SIDE_LEFT == aEndBevelSide) {
rect.height -= endBevel;
}
DrawSolidBorderSegment(aContext, rect, twipsPerPixel, aStartBevelSide,
startBevel, aEndBevelSide, endBevel);
}
rect = aBorder;
ridgeGrooveSide = (NS_SIDE_TOP == ridgeGrooveSide) ? NS_SIDE_BOTTOM : NS_SIDE_RIGHT;
aContext.SetColor (
MakeBevelColor (ridgeGrooveSide, ridgeGroove, aBGColor->mBackgroundColor, aBorderColor, PR_TRUE));
if (horizontal) {
rect.y = rect.y + half;
rect.height = aBorder.height - half;
if (NS_SIDE_BOTTOM == aStartBevelSide) {
rect.x += startBevel;
rect.width -= startBevel;
}
if (NS_SIDE_BOTTOM == aEndBevelSide) {
rect.width -= endBevel;
}
DrawSolidBorderSegment(aContext, rect, twipsPerPixel, aStartBevelSide,
startBevel, aEndBevelSide, endBevel);
}
else {
rect.x = rect.x + half;
rect.width = aBorder.width - half;
if (NS_SIDE_RIGHT == aStartBevelSide) {
rect.y += aStartBevelOffset - startBevel;
rect.height -= startBevel;
}
if (NS_SIDE_RIGHT == aEndBevelSide) {
rect.height -= endBevel;
}
DrawSolidBorderSegment(aContext, rect, twipsPerPixel, aStartBevelSide,
startBevel, aEndBevelSide, endBevel);
}
}
break;
case NS_STYLE_BORDER_STYLE_DOUBLE:
if ((aBorder.width > 2) && (aBorder.height > 2)) {
nscoord startBevel = (aStartBevelOffset > 0)
? RoundFloatToPixel(0.333333f * (float)aStartBevelOffset, twipsPerPixel) : 0;
nscoord endBevel = (aEndBevelOffset > 0)
? RoundFloatToPixel(0.333333f * (float)aEndBevelOffset, twipsPerPixel) : 0;
if (horizontal) { // top, bottom
nscoord thirdHeight = RoundFloatToPixel(0.333333f * (float)aBorder.height, twipsPerPixel);
// draw the top line or rect
nsRect topRect(aBorder.x, aBorder.y, aBorder.width, thirdHeight);
if (NS_SIDE_TOP == aStartBevelSide) {
topRect.x += aStartBevelOffset - startBevel;
topRect.width -= aStartBevelOffset - startBevel;
}
if (NS_SIDE_TOP == aEndBevelSide) {
topRect.width -= aEndBevelOffset - endBevel;
}
DrawSolidBorderSegment(aContext, topRect, twipsPerPixel, aStartBevelSide,
startBevel, aEndBevelSide, endBevel);
// draw the botom line or rect
nscoord heightOffset = aBorder.height - thirdHeight;
nsRect bottomRect(aBorder.x, aBorder.y + heightOffset, aBorder.width, aBorder.height - heightOffset);
if (NS_SIDE_BOTTOM == aStartBevelSide) {
bottomRect.x += aStartBevelOffset - startBevel;
bottomRect.width -= aStartBevelOffset - startBevel;
}
if (NS_SIDE_BOTTOM == aEndBevelSide) {
bottomRect.width -= aEndBevelOffset - endBevel;
}
DrawSolidBorderSegment(aContext, bottomRect, twipsPerPixel, aStartBevelSide,
startBevel, aEndBevelSide, endBevel);
}
else { // left, right
nscoord thirdWidth = RoundFloatToPixel(0.333333f * (float)aBorder.width, twipsPerPixel);
nsRect leftRect(aBorder.x, aBorder.y, thirdWidth, aBorder.height);
if (NS_SIDE_LEFT == aStartBevelSide) {
leftRect.y += aStartBevelOffset - startBevel;
leftRect.height -= aStartBevelOffset - startBevel;
}
if (NS_SIDE_LEFT == aEndBevelSide) {
leftRect.height -= aEndBevelOffset - endBevel;
}
DrawSolidBorderSegment(aContext, leftRect, twipsPerPixel, aStartBevelSide,
startBevel, aEndBevelSide, endBevel);
nscoord widthOffset = aBorder.width - thirdWidth;
nsRect rightRect(aBorder.x + widthOffset, aBorder.y, aBorder.width - widthOffset, aBorder.height);
if (NS_SIDE_RIGHT == aStartBevelSide) {
rightRect.y += aStartBevelOffset - startBevel;
rightRect.height -= aStartBevelOffset - startBevel;
}
if (NS_SIDE_RIGHT == aEndBevelSide) {
rightRect.height -= aEndBevelOffset - endBevel;
}
DrawSolidBorderSegment(aContext, rightRect, twipsPerPixel, aStartBevelSide,
startBevel, aEndBevelSide, endBevel);
}
break;
}
// else fall through to solid
case NS_STYLE_BORDER_STYLE_SOLID:
DrawSolidBorderSegment(aContext, aBorder, twipsPerPixel, aStartBevelSide,
aStartBevelOffset, aEndBevelSide, aEndBevelOffset);
break;
case NS_STYLE_BORDER_STYLE_BG_OUTSET:
case NS_STYLE_BORDER_STYLE_BG_INSET:
case NS_STYLE_BORDER_STYLE_OUTSET:
case NS_STYLE_BORDER_STYLE_INSET:
NS_ASSERTION(PR_FALSE, "inset, outset should have been converted to groove, ridge");
break;
}
}
// End table border-collapsing section

View File

@ -180,6 +180,17 @@ public:
PRIntn aSkipSides,
nsRect* aGap);
// Draw a border segment in the table collapsing border model without beveling corners
static void DrawTableBorderSegment(nsIRenderingContext& aContext,
PRUint8 aBorderStyle,
nscolor aBorderColor,
const nsStyleBackground* aBGColor,
const nsRect& aBorderRect,
float aPixelsToTwips,
PRUint8 aStartBevelSide = 0,
nscoord aStartBevelOffset = 0,
PRUint8 aEndBevelSide = 0,
nscoord aEndBevelOffset = 0);
/**
* transform a color to a color that will show up on a printer if needed
* aMapColor - color to evaluate

View File

@ -139,7 +139,7 @@ PRBool BasicTableLayoutStrategy::Initialize(nsIPresContext* aPresContex
nscoord minWidth, prefWidth;
mTableFrame->CalcMinAndPreferredWidths(aPresContext, aReflowState, PR_FALSE, minWidth, prefWidth);
if (hasPctCol && mTableFrame->IsAutoWidth()) {
prefWidth = CalcPctAdjTableWidth(aReflowState, boxWidth, p2t);
prefWidth = CalcPctAdjTableWidth(*aPresContext, aReflowState, boxWidth, p2t);
}
// calc the desired width, considering if there is a specified width.
// don't use nsTableFrame::CalcDesiredWidth because it is based on table column widths.
@ -195,7 +195,7 @@ ResetPctValues(nsTableFrame* aTableFrame,
// initialize the col percent and cell percent values to 0.
PRInt32 colX;
for (colX = 0; colX < aNumCols; colX++) {
nsTableColFrame* colFrame = aTableFrame->GetColFrame(colX);
nsTableColFrame* colFrame = aTableFrame->GetColFrame(colX); if (!colFrame) ABORT0();
if (colFrame) {
colFrame->SetWidth(PCT, WIDTH_NOT_SET);
colFrame->SetWidth(PCT_ADJ, WIDTH_NOT_SET);
@ -207,6 +207,7 @@ PRBool
BasicTableLayoutStrategy::BalanceColumnWidths(nsIPresContext* aPresContext,
const nsHTMLReflowState& aReflowState)
{
if (!aPresContext) ABORT1(PR_FALSE);
#ifdef DEBUG_TABLE_STRATEGY
printf("BalanceColumnWidths en count=%d \n", gsDebugCount++); mTableFrame->Dump(aPresContext, PR_FALSE, PR_TRUE, PR_FALSE);
#endif
@ -220,8 +221,16 @@ BasicTableLayoutStrategy::BalanceColumnWidths(nsIPresContext* aPresCont
PRInt32 numCols = mTableFrame->GetColCount();
PRBool tableIsAutoWidth = mTableFrame->IsAutoWidth();
nscoord horBorderPadding = aReflowState.mComputedBorderPadding.left +
aReflowState.mComputedBorderPadding.right;
nscoord horOffset;
// get the reduction in available horizontal space due to borders and padding
if (mTableFrame->IsBorderCollapse()) {
nsMargin offset = mTableFrame->GetChildAreaOffset(*aPresContext, &aReflowState);
horOffset = offset.left + offset.right;
}
else {
horOffset = aReflowState.mComputedBorderPadding.left + aReflowState.mComputedBorderPadding.right;
}
// determine if the table is auto/fixed and get the fixed width if available
nscoord maxWidth = mTableFrame->CalcBorderBoxWidth(aPresContext, aReflowState);
@ -238,19 +247,19 @@ BasicTableLayoutStrategy::BalanceColumnWidths(nsIPresContext* aPresCont
// An auto table returns a new table width based on percent cells/cols if they exist
nscoord perAdjTableWidth = 0;
if (mTableFrame->HasPctCol()) {
perAdjTableWidth = AssignPctColumnWidths(aReflowState, maxWidth, tableIsAutoWidth, p2t);
perAdjTableWidth = AssignPctColumnWidths(*aPresContext, aReflowState, maxWidth, tableIsAutoWidth, p2t);
if (perAdjTableWidth > 0) {
// if an auto table has a pct col or cell, set the preferred table width
// here so that CalcPctAdjTableWidth wont't need to be called by the table
mTableFrame->SetPreferredWidth(perAdjTableWidth);
}
perAdjTableWidth = PR_MIN(perAdjTableWidth, maxWidth);
perAdjTableWidth -= horBorderPadding;
perAdjTableWidth -= horOffset;
perAdjTableWidth = PR_MAX(perAdjTableWidth, 0);
}
// reduce the maxWidth by border and padding, since we will be dealing with content width
maxWidth -= horBorderPadding;
maxWidth -= horOffset;
maxWidth = PR_MAX(0, maxWidth);
PRInt32 numNonZeroWidthCols = 0;
@ -258,7 +267,7 @@ BasicTableLayoutStrategy::BalanceColumnWidths(nsIPresContext* aPresCont
nscoord minTableWidth = 0;
PRInt32 colX;
for (colX = 0; colX < numCols; colX++) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); if (!colFrame) ABORT1(PR_FALSE);
if (!colFrame) continue;
nscoord colMinWidth = colFrame->GetMinWidth();
mTableFrame->SetColumnWidth(colX, colMinWidth);
@ -400,7 +409,7 @@ void BasicTableLayoutStrategy::AllocateFully(nscoord& aTotalAllocated,
{
PRInt32 numCols = mTableFrame->GetColCount();
for (PRInt32 colX = 0; colX < numCols; colX++) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); if (!colFrame) ABORT0();
if (!colFrame) continue;
if (!CanAllocate(aWidthType, aAllocTypes[colX], colFrame)) {
continue;
@ -454,7 +463,7 @@ void BasicTableLayoutStrategy::AllocateUnconstrained(PRInt32 aAllocAmount,
}
else {
if (aExclude0Pro) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); if (!colFrame) ABORT0();
if (colFrame->GetConstraint() == e0ProportionConstraint) {
aAllocTypes[colX] = FINISHED;
}
@ -467,7 +476,7 @@ void BasicTableLayoutStrategy::AllocateUnconstrained(PRInt32 aAllocAmount,
PRInt32 numColsAllocated = 0;
PRInt32 totalAllocated = 0;
for (colX = 0; colX < numCols; colX++) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); if (!colFrame) ABORT0();
PRBool skipColumn = aExclude0Pro && (e0ProportionConstraint == colFrame->GetConstraint());
if (FINISHED != aAllocTypes[colX] && !skipColumn ) {
divisor += mTableFrame->GetColumnWidth(colX);
@ -477,7 +486,7 @@ void BasicTableLayoutStrategy::AllocateUnconstrained(PRInt32 aAllocAmount,
for (colX = 0; colX < numCols; colX++) {
if (FINISHED != aAllocTypes[colX]) {
if (aExclude0Pro) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); if (!colFrame) ABORT0();
if (colFrame && (e0ProportionConstraint == colFrame->GetConstraint())) {
continue;
}
@ -533,7 +542,7 @@ BasicTableLayoutStrategy::ComputeNonPctColspanWidths(const nsHTMLReflowState& aR
PRInt32 colX;
for (colX = numCols - 1; colX >= 0; colX--) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); if (!colFrame) ABORT0();
if (!colFrame) continue;
colFrame->SetWidth(MIN_ADJ, WIDTH_NOT_SET);
colFrame->SetWidth(FIX_ADJ, WIDTH_NOT_SET);
@ -698,7 +707,7 @@ BasicTableLayoutStrategy::ComputeNonPctColspanWidths(PRInt32 aWidthInd
PRInt32 spanX;
// accumulate the various divisors to be used later
for (spanX = 0; spanX < aColSpan; spanX++) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(aColIndex + spanX);
nsTableColFrame* colFrame = mTableFrame->GetColFrame(aColIndex + spanX); if (!colFrame) ABORT1(PR_FALSE);
if (!colFrame) continue;
nscoord minWidth = PR_MAX(colFrame->GetMinWidth(), 0);
nscoord pctWidth = PR_MAX(colFrame->GetPctWidth(), 0);
@ -802,7 +811,7 @@ BasicTableLayoutStrategy::ComputeNonPctColspanWidths(PRInt32 aWidthInd
// get the correct numerator in a similar fashion to getting the divisor
for (spanX = 0; spanX < aColSpan; spanX++) {
if (usedWidth >= availWidth) break;
nsTableColFrame* colFrame = mTableFrame->GetColFrame(aColIndex + spanX);
nsTableColFrame* colFrame = mTableFrame->GetColFrame(aColIndex + spanX); if (!colFrame) ABORT1(PR_FALSE);
if (!colFrame) continue;
nscoord minWidth = colFrame->GetMinWidth();
nscoord pctWidth = PR_MAX(colFrame->GetPctWidth(), 0);
@ -974,7 +983,7 @@ BasicTableLayoutStrategy::AssignNonPctColumnWidths(nsIPresContext* aPre
nscoord fixWidth = WIDTH_NOT_SET;
// Get column frame and reset it
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); if (!colFrame) ABORT1(PR_FALSE);
if (!colFrame) continue;
NS_ASSERTION(nsnull != colFrame, "bad col frame");
colFrame->ResetSizingInfo();
@ -1079,7 +1088,7 @@ BasicTableLayoutStrategy::AssignNonPctColumnWidths(nsIPresContext* aPre
}
//set the table col fixed width if present
for (colX = 0; colX < numCols; colX++) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); if (!colFrame) ABORT1(PR_FALSE);
if (!colFrame) continue;
nscoord fixColWidth = colFrame->GetWidth(FIX);
// use the style width of a col only if the col hasn't gotten a fixed width from any cell
@ -1140,7 +1149,7 @@ BasicTableLayoutStrategy::AssignNonPctColumnWidths(nsIPresContext* aPre
// Set the table col width for each col to the content min.
for (colX = 0; colX < numCols; colX++) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); if (!colFrame) ABORT1(PR_FALSE);
nscoord minWidth = colFrame->GetMinWidth();
mTableFrame->SetColumnWidth(colX, minWidth);
}
@ -1159,7 +1168,7 @@ BasicTableLayoutStrategy::ReduceOverSpecifiedPctCols(nscoord aExcess)
{
nscoord numCols = mTableFrame->GetColCount();
for (PRInt32 colX = numCols - 1; (colX >= 0) && (aExcess > 0); colX--) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); if (!colFrame) ABORT0();
if (!colFrame) continue;
nscoord pctWidth = colFrame->GetWidth(PCT);
nscoord reduction = 0;
@ -1198,7 +1207,8 @@ inline nscoord WrapupAssignPctColumnWidths(nsTableFrame* aTableFrame,
#endif
nscoord
BasicTableLayoutStrategy::CalcPctAdjTableWidth(const nsHTMLReflowState& aReflowState,
BasicTableLayoutStrategy::CalcPctAdjTableWidth(nsIPresContext& aPresContext,
const nsHTMLReflowState& aReflowState,
nscoord aAvailWidthIn,
float aPixelToTwips)
{
@ -1219,7 +1229,7 @@ BasicTableLayoutStrategy::CalcPctAdjTableWidth(const nsHTMLReflowState& aReflowS
rawPctValues[colX] = 0.0f;
}
nsMargin borderPadding = mTableFrame->GetBorderPadding(aReflowState);
nsMargin borderPadding = mTableFrame->GetContentAreaOffset(aPresContext, &aReflowState);
nscoord availWidth = aAvailWidthIn;
if (NS_UNCONSTRAINEDSIZE != availWidth) {
// adjust the avail width to exclude table border, padding and cell spacing
@ -1227,7 +1237,7 @@ BasicTableLayoutStrategy::CalcPctAdjTableWidth(const nsHTMLReflowState& aReflowS
}
for (colX = 0; colX < numCols; colX++) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); if (!colFrame) ABORT1(0);
if (!colFrame) continue;
nscoord maxColBasis = -1;
// Scan the cells in the col
@ -1282,7 +1292,7 @@ BasicTableLayoutStrategy::CalcPctAdjTableWidth(const nsHTMLReflowState& aReflowS
nscoord fixDesTotalNoPct = 0; // total of fix or des widths of cols without pct
for (colX = 0; colX < numCols; colX++) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); if (!colFrame) ABORT1(0);
nscoord fixWidth = colFrame->GetFixWidth();
nscoord fixDesWidth = (fixWidth > 0) ? fixWidth : colFrame->GetDesWidth();
fixDesTotal += fixDesWidth;
@ -1329,7 +1339,8 @@ BasicTableLayoutStrategy::CalcPctAdjTableWidth(const nsHTMLReflowState& aReflowS
// Determine percentage col widths for each col frame
nscoord
BasicTableLayoutStrategy::AssignPctColumnWidths(const nsHTMLReflowState& aReflowState,
BasicTableLayoutStrategy::AssignPctColumnWidths(nsIPresContext& aPresContext,
const nsHTMLReflowState& aReflowState,
nscoord aAvailWidth,
PRBool aTableIsAutoWidth,
float aPixelToTwips)
@ -1349,11 +1360,11 @@ BasicTableLayoutStrategy::AssignPctColumnWidths(const nsHTMLReflowState& aReflow
// on percent cells/cols. This probably should only be a NavQuirks thing, since
// a percentage based cell or column on an auto table should force the column to auto
nscoord basis = (aTableIsAutoWidth)
? CalcPctAdjTableWidth(aReflowState, aAvailWidth, aPixelToTwips)
? CalcPctAdjTableWidth(aPresContext, aReflowState, aAvailWidth, aPixelToTwips)
: aAvailWidth;
// adjust the basis to exclude table border, padding and cell spacing
nsMargin borderPadding = mTableFrame->GetBorderPadding(aReflowState);
nsMargin borderPadding = mTableFrame->GetContentAreaOffset(aPresContext, &aReflowState);
basis -= borderPadding.left + borderPadding.right + mCellSpacingTotal;
nscoord colPctTotal = 0;
@ -1361,7 +1372,7 @@ BasicTableLayoutStrategy::AssignPctColumnWidths(const nsHTMLReflowState& aReflow
// Determine the percentage contribution for cols and for cells with colspan = 1
// Iterate backwards, similarly to the reasoning in AssignNonPctColumnWidths
for (colX = numCols - 1; colX >= 0; colX--) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); if (!colFrame) ABORT1(0);
if (!colFrame) continue;
nscoord maxColPctWidth = WIDTH_NOT_SET;
float maxColPct = 0.0f;
@ -1431,7 +1442,7 @@ BasicTableLayoutStrategy::AssignPctColumnWidths(const nsHTMLReflowState& aReflow
}
// determine if the cell spans cols which have a pct value
for (PRInt32 spanX = 0; (spanX < colSpan) && !done; spanX++) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX + spanX);
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX + spanX); if (!colFrame) ABORT1(0);
if (!colFrame) continue;
if (colFrame->GetWidth(PCT) > 0) {
mTableFrame->SetHasCellSpanningPctCol(PR_TRUE);
@ -1511,7 +1522,7 @@ BasicTableLayoutStrategy::AssignPctColumnWidths(const nsHTMLReflowState& aReflow
// accumulate the spanTotal as the max of MIN, DES, FIX, PCT
PRInt32 spanX;
for (spanX = 0; spanX < colSpan; spanX++) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX + spanX);
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX + spanX); if (!colFrame) ABORT1(0);
if (!colFrame) continue;
nscoord colPctWidth = colFrame->GetWidth(PCT);
if (colPctWidth > 0) { // skip pct cols
@ -1546,7 +1557,7 @@ BasicTableLayoutStrategy::AssignPctColumnWidths(const nsHTMLReflowState& aReflow
// record the percent contributions for the spanned cols
PRInt32 usedColumns = colSpan;
for (spanX = colSpan-1; spanX >= 0; spanX--) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX + spanX);
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX + spanX); if (!colFrame) ABORT1(0);
if (!colFrame) continue;
if ((colFrame->GetWidth(PCT) > 0) || (canSkipPctAdj && (colFrame->GetWidth(PCT_ADJ) > 0))) {
// dont use pct cols or if we can skip the pct adj event do not take the PCT_ADJ cols
@ -1621,7 +1632,7 @@ void BasicTableLayoutStrategy::CalculateTotals(PRInt32* aTotalCounts,
PRInt32 colX;
for (colX = 0; colX < numEffCols; colX++) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); if (!colFrame) ABORT0();
if (!colFrame) continue;
nscoord minCol = colFrame->GetMinWidth();
aTotalCounts[MIN_CON]++;
@ -1820,7 +1831,7 @@ void BasicTableLayoutStrategy::AllocateConstrained(PRInt32 aAvailWidth,
PRInt32 colX;
// find out how many constrained cols there are
for (colX = 0; colX < numCols; colX++) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); if (!colFrame) ABORT0();
if (!colFrame) continue;
if (!CanAllocate(aWidthType, aAllocTypes[colX], colFrame)) {
continue;
@ -1837,7 +1848,7 @@ void BasicTableLayoutStrategy::AllocateConstrained(PRInt32 aAvailWidth,
PRInt32 constrColX = 0;
// set the col info entries for each constrained col
for (colX = 0; colX < numCols; colX++) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); if (!colFrame) ABORT0();
if (!colFrame) continue;
if (!CanAllocate(aWidthType, aAllocTypes[colX], colFrame)) {
continue;

View File

@ -93,7 +93,8 @@ public:
* @param aPixelToTwips - the number of twips in a pixel.
* @return - the basis for percent calculations
*/
virtual nscoord CalcPctAdjTableWidth(const nsHTMLReflowState& aReflowState,
virtual nscoord CalcPctAdjTableWidth(nsIPresContext& aPresContext,
const nsHTMLReflowState& aReflowState,
nscoord aAvailWidth,
float aPixelToTwips);
void Dump(PRInt32 aIndent);
@ -159,7 +160,8 @@ protected:
* @param aPixelToTwips - the number of twips in a pixel.
* @return - the adjusted basis including table border, padding and cell spacing
*/
nscoord AssignPctColumnWidths(const nsHTMLReflowState& aReflowState,
nscoord AssignPctColumnWidths(nsIPresContext& aPresContext,
const nsHTMLReflowState& aReflowState,
nscoord aBasis,
PRBool aTableIsAutoWidth,
float aPixelToTwips);

View File

@ -38,6 +38,7 @@
#define CellData_h__
#include "nsISupports.h"
#include "nsCoord.h"
class nsTableCellFrame;
@ -51,8 +52,9 @@ public:
~CellData();
void Init(nsTableCellFrame* aCellFrame);
PRBool IsOrig() const;
PRBool IsDead() const;
PRBool IsSpan() const;
PRBool IsRowSpan() const;
@ -84,6 +86,93 @@ protected:
};
};
// Border Collapsing Cell Data
enum BCBorderOwner
{
eTableOwner = 0,
eColGroupOwner = 1,
eAjaColGroupOwner = 2, // col group to the left
eColOwner = 3,
eAjaColOwner = 4, // col to the left
eRowGroupOwner = 5,
eAjaRowGroupOwner = 6, // row group above
eRowOwner = 7,
eAjaRowOwner = 8, // row above
eCellOwner = 9,
eAjaCellOwner = 10, // cell to the top or to the left
};
// These are the max sizes that are stored. If they are exceeded, then the max is stored and
// the actual value is computed when needed.
#define MAX_BORDER_WIDTH 64
#define MAX_CORNER_SUB_WIDTH 128
// BCData stores the top and left border info and the corner connecting the two.
class BCData
{
public:
BCData();
~BCData();
nscoord GetLeftEdge(BCBorderOwner& aOwner,
PRBool& aStart) const;
void SetLeftEdge(BCBorderOwner aOwner,
nscoord aSize,
PRBool aStart);
nscoord GetTopEdge(BCBorderOwner& aOwner,
PRBool& aStart) const;
void SetTopEdge(BCBorderOwner aOwner,
nscoord aSize,
PRBool aStart);
PRUint8 GetCorner(PRUint8& aCornerOwner,
PRPackedBool& aBevel) const;
void SetCorner(PRUint8 aOwner,
PRUint8 aSubSize,
PRBool aBevel);
PRBool IsLeftStart() const;
void SetLeftStart(PRBool aValue);
PRBool IsTopStart() const;
void SetTopStart(PRBool aValue);
protected:
unsigned mLeftOwner: 4; // owner of left border
unsigned mLeftSize: 6; // size in pixels of left border
unsigned mLeftStart: 1; // set if this is the start of a vertical border segment
unsigned mCornerSide: 2; // side of the owner of the upper left corner relative to the corner
unsigned mCornerSubSize: 7; // size of the largest border not in the dominate plane (for example, if
// corner is owned by the segment to its top or bottom, then the size is the
// max of the border sizes of the segments to its left or right.
unsigned mCornerBevel: 1; // is the corner beveled (only two segments, perpendicular, not dashed or dotted).
unsigned mTopOwner: 4; // owner of top border
unsigned mTopSize: 6; // size in pixels of top border
unsigned mTopStart: 1; // set if this is the start of a horizontal border segment
};
// BCCellData entries replace CellData entries in the cell map if the border collapsing model is in
// effect. BCData for a row and col entry contains the left and top borders of cell at that row and
// col and the corner connecting the two. The right borders of the cells in the last col and the bottom
// borders of the last row are stored in separate BCData entries in the cell map.
class BCCellData : public CellData
{
public:
BCCellData(nsTableCellFrame* aOrigCell);
~BCCellData();
BCData mData;
};
#define SPAN 0x00000001 // there a row or col span
#define ROW_SPAN 0x00000002 // there is a row span
#define ROW_SPAN_0 0x00000004 // the row span is 0
@ -103,9 +192,19 @@ inline nsTableCellFrame* CellData::GetCellFrame() const
return nsnull;
}
inline void CellData::Init(nsTableCellFrame* aCellFrame)
{
mOrigCell = aCellFrame;
}
inline PRBool CellData::IsOrig() const
{
return (SPAN != (SPAN & mBits));
return ((nsnull != mOrigCell) && (SPAN != (SPAN & mBits)));
}
inline PRBool CellData::IsDead() const
{
return (0 == mBits);
}
inline PRBool CellData::IsSpan() const
@ -213,4 +312,88 @@ inline void CellData::SetOverlap(PRBool aOverlap)
}
}
inline BCData::BCData()
{
mLeftOwner = mTopOwner = eCellOwner;
mLeftStart = mTopStart = 1;
mLeftSize = mCornerSide = mCornerSubSize = mTopSize = 0;
}
inline BCData::~BCData()
{
}
inline nscoord BCData::GetLeftEdge(BCBorderOwner& aOwner,
PRBool& aStart) const
{
aOwner = (BCBorderOwner)mLeftOwner;
aStart = (PRBool)mLeftStart;
return (nscoord)mLeftSize;
}
inline void BCData::SetLeftEdge(BCBorderOwner aOwner,
nscoord aSize,
PRBool aStart)
{
mLeftOwner = aOwner;
mLeftSize = (aSize > MAX_BORDER_WIDTH) ? MAX_BORDER_WIDTH : aSize;
mLeftStart = aStart;
}
inline nscoord BCData::GetTopEdge(BCBorderOwner& aOwner,
PRBool& aStart) const
{
aOwner = (BCBorderOwner)mTopOwner;
aStart = (PRBool)mTopStart;
return (nscoord)mTopSize;
}
inline void BCData::SetTopEdge(BCBorderOwner aOwner,
nscoord aSize,
PRBool aStart)
{
mTopOwner = aOwner;
mTopSize = (aSize > MAX_BORDER_WIDTH) ? MAX_BORDER_WIDTH : aSize;
mTopStart = aStart;
}
inline PRUint8 BCData::GetCorner(PRUint8& aOwnerSide,
PRPackedBool& aBevel) const
{
aOwnerSide = mCornerSide;
aBevel = (PRBool)mCornerBevel;
return (PRUint8)mCornerSubSize;
}
inline void BCData::SetCorner(PRUint8 aSubSize,
PRUint8 aOwnerSide,
PRBool aBevel)
{
mCornerSubSize = (aSubSize > MAX_CORNER_SUB_WIDTH) ? MAX_CORNER_SUB_WIDTH : aSubSize;
mCornerSide = aOwnerSide;
mCornerBevel = aBevel;
}
inline PRBool BCData::IsLeftStart() const
{
return (PRBool)mLeftStart;
}
inline void BCData::SetLeftStart(PRBool aValue)
{
mLeftStart = aValue;
}
inline PRBool BCData::IsTopStart() const
{
return (PRBool)mTopStart;
}
inline void BCData::SetTopStart(PRBool aValue)
{
mTopStart = aValue;
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -40,6 +40,8 @@
#include "nscore.h"
#include "celldata.h"
#include "nsVoidArray.h"
#include "nsRect.h"
class nsTableColFrame;
class nsTableCellFrame;
class nsIPresContext;
@ -58,10 +60,27 @@ struct nsColInfo
PRInt32 aNumCellsSpan);
};
enum Corner
{
eTopLeft = 0,
eTopRight = 1,
eBottomRight = 2,
eBottomLeft = 3
};
struct BCInfo
{
nsVoidArray mRightBorders;
nsVoidArray mBottomBorders;
BCData mLowerRightCorner;
};
class nsTableCellMap
{
public:
nsTableCellMap(nsIPresContext* aPresContext, nsTableFrame& aTableFrame);
nsTableCellMap(nsIPresContext* aPresContext,
nsTableFrame& aTableFrame,
PRBool aBorderCollapse);
/** destructor
* NOT VIRTUAL BECAUSE THIS CLASS SHOULD **NEVER** BE SUBCLASSED
@ -69,43 +88,52 @@ public:
~nsTableCellMap();
void RemoveGroupCellMap(nsTableRowGroupFrame* aRowGroup);
void InsertGroupCellMap(nsTableRowGroupFrame& aNewRowGroup,
nsTableRowGroupFrame*& aPrevRowGroup);
nsCellMap* GetMapFor(nsTableRowGroupFrame& aRowGroup);
nsTableCellFrame* GetCellFrame(PRInt32 aRowIndex,
PRInt32 aColIndex,
CellData& aData,
PRBool aUseRowIfOverlap) const;
/** return the CellData for the cell at (aTableRowIndex, aTableColIndex) */
CellData* GetCellAt(PRInt32 aRowIndex,
PRInt32 aColIndex);
CellData* GetDataAt(PRInt32 aRowIndex,
PRInt32 aColIndex,
PRBool aUpdateZeroSpan = PR_TRUE);
nsColInfo* GetColInfoAt(PRInt32 aColIndex);
/** append the cellFrame at the end of the row at aRowIndex and return the col index
*/
PRInt32 AppendCell(nsTableCellFrame& aCellFrame,
PRInt32 aRowIndex,
PRBool aRebuildIfNecessary);
CellData* AppendCell(nsTableCellFrame& aCellFrame,
PRInt32 aRowIndex,
PRBool aRebuildIfNecessary,
nsRect& aDamageArea);
void InsertCells(nsVoidArray& aCellFrames,
PRInt32 aRowIndex,
PRInt32 aColIndexBefore);
PRInt32 aColIndexBefore,
nsRect& aDamageArea);
void RemoveCell(nsTableCellFrame* aCellFrame,
PRInt32 aRowIndex);
PRInt32 aRowIndex,
nsRect& aDamageArea);
void InsertRows(nsIPresContext* aPresContext,
nsTableRowGroupFrame& aRowGroup,
nsVoidArray& aRows,
PRInt32 aFirstRowIndex,
PRBool aConsiderSpans);
PRBool aConsiderSpans,
nsRect& aDamageArea);
void RemoveRows(nsIPresContext* aPresContext,
PRInt32 aFirstRowIndex,
PRInt32 aNumRowsToRemove,
PRBool aConsiderSpans);
PRBool aConsiderSpans,
nsRect& aDamageArea);
PRInt32 GetNumCellsOriginatingInRow(PRInt32 aRowIndex);
PRInt32 GetNumCellsOriginatingInCol(PRInt32 aColIndex) const;
@ -134,6 +162,32 @@ public:
PRBool ColIsSpannedInto(PRInt32 aColIndex);
PRBool ColHasSpanningCells(PRInt32 aColIndex);
BCData* GetBCData(PRUint8 aSide,
nsCellMap& aCellMap,
PRUint32 aYPos,
PRUint32 aXPos,
PRBool aIsLowerRight = PR_FALSE);
void SetBCBorderEdge(PRUint8 aEdge,
nsCellMap& aCellMap,
PRUint32 aCellMapStart,
PRUint32 aYPos,
PRUint32 aXPos,
PRUint32 aLength,
BCBorderOwner aOwner,
nscoord aSize,
PRBool aChanged);
void SetBCBorderCorner(Corner aCorner,
nsCellMap& aCellMap,
PRUint32 aCellMapStart,
PRUint32 aYPos,
PRUint32 aXPos,
PRUint8 aOwner,
nscoord aSubSize,
PRBool aBevel,
PRBool aIsBottomRight = PR_FALSE);
/** dump a representation of the cell map to stdout for debugging */
#ifdef NS_DEBUG
void Dump(char* aString = nsnull) const;
@ -144,13 +198,21 @@ public:
#endif
protected:
BCData* GetRightMostBorder(PRInt32 aRowIndex);
BCData* GetBottomMostBorder(PRInt32 aColIndex);
friend class nsCellMap;
friend class BCMapCellIterator;
friend class BCMapBorderIterator;
void InsertGroupCellMap(nsCellMap* aPrevMap,
nsCellMap& aNewMap);
void DeleteRightBottomBorders();
nsTableFrame& mTableFrame;
nsTableFrame& mTableFrame;
nsAutoVoidArray mCols;
nsCellMap* mFirstMap;
nsCellMap* mFirstMap;
// border collapsing info
BCInfo* mBCInfo;
};
/** nsCellMap is a support class for nsTablePart.
@ -190,40 +252,38 @@ public:
CellData& aData,
PRBool aUseRowSpanIfOverlap) const;
/** return the CellData for the cell at (aTableRowIndex, aTableColIndex) */
CellData* GetCellAt(nsTableCellMap& aMap,
PRInt32 aRowIndex,
PRInt32 aColIndex);
/** append the cellFrame at the end of the row at aRowIndex and return the col index
*/
PRInt32 AppendCell(nsTableCellMap& aMap,
nsTableCellFrame& aCellFrame,
PRInt32 aRowIndex,
PRBool aRebuildIfNecessary);
CellData* AppendCell(nsTableCellMap& aMap,
nsTableCellFrame* aCellFrame,
PRInt32 aRowIndex,
PRBool aRebuildIfNecessary,
nsRect& aDamageArea);
void InsertCells(nsTableCellMap& aMap,
nsVoidArray& aCellFrames,
PRInt32 aRowIndex,
PRInt32 aColIndexBefore);
PRInt32 aColIndexBefore,
nsRect& aDamageArea);
void RemoveCell(nsTableCellMap& aMap,
nsTableCellFrame* aCellFrame,
PRInt32 aRowIndex);
void RemoveCol(PRInt32 aColIndex);
PRInt32 aRowIndex,
nsRect& aDamageArea);
void InsertRows(nsIPresContext* aPresContext,
nsTableCellMap& aMap,
nsVoidArray& aRows,
PRInt32 aFirstRowIndex,
PRBool aConsiderSpans);
PRBool aConsiderSpans,
nsRect& aDamageArea);
void RemoveRows(nsIPresContext* aPresContext,
nsTableCellMap& aMap,
PRInt32 aFirstRowIndex,
PRInt32 aNumRowsToRemove,
PRBool aConsiderSpans);
PRBool aConsiderSpans,
nsRect& aDamageArea);
PRInt32 GetNumCellsOriginatingInRow(PRInt32 aRowIndex) const;
PRInt32 GetNumCellsOriginatingInCol(PRInt32 aColIndex) const;
@ -246,9 +306,20 @@ public:
PRBool ColHasSpanningCells(nsTableCellMap& aMap,
PRInt32 aColIndex);
PRInt32 GetRowSpan(nsTableCellMap& aMap,
PRInt32 aRowIndex,
PRInt32 aColIndex,
PRBool aGetEffective,
PRBool& aIsZeroRowSpan);
PRInt32 GetEffectiveColSpan(nsTableCellMap& aMap,
PRInt32 aRowIndex,
PRInt32 aColIndex,
PRBool& aIsZeroColSpan);
/** dump a representation of the cell map to stdout for debugging */
#ifdef NS_DEBUG
void Dump() const;
void Dump(PRBool aIsBorderCollapse) const;
#endif
#ifdef DEBUG
@ -257,6 +328,9 @@ public:
protected:
friend class nsTableCellMap;
friend class BCMapCellIterator;
friend class BCMapBorderIterator;
friend class nsTableFrame;
PRBool Grow(nsTableCellMap& aMap,
PRInt32 aNumRows,
@ -266,51 +340,57 @@ protected:
PRInt32 aNumCols);
/** assign aCellData to the cell at (aRow,aColumn) */
void SetMapCellAt(nsTableCellMap& aMap,
CellData& aCellData,
PRInt32 aMapRowIndex,
PRInt32 aColIndex,
PRBool aCountZeroSpanAsSpan);
void SetDataAt(nsTableCellMap& aMap,
CellData& aCellData,
PRInt32 aMapRowIndex,
PRInt32 aColIndex,
PRBool aCountZeroSpanAsSpan);
CellData* GetMapCellAt(nsTableCellMap& aMap,
PRInt32 aMapRowIndex,
PRInt32 aColIndex,
PRBool aUpdateZeroSpan);
CellData* GetDataAt(nsTableCellMap& aMap,
PRInt32 aMapRowIndex,
PRInt32 aColIndex,
PRBool aUpdateZeroSpan);
PRInt32 GetNumCellsIn(PRInt32 aColIndex) const;
void ExpandWithRows(nsIPresContext* aPresContext,
nsTableCellMap& aMap,
nsVoidArray& aRowFrames,
PRInt32 aStartRowIndex);
PRInt32 aStartRowIndex,
nsRect& aDamageArea);
void ExpandWithCells(nsTableCellMap& aMap,
nsVoidArray& aCellFrames,
PRInt32 aRowIndex,
PRInt32 aColIndex,
PRInt32 aRowSpan,
PRBool aRowSpanIsZero);
PRBool aRowSpanIsZero,
nsRect& aDamageArea);
void ShrinkWithoutRows(nsTableCellMap& aMap,
PRInt32 aFirstRowIndex,
PRInt32 aNumRowsToRemove);
PRInt32 aNumRowsToRemove,
nsRect& aDamageArea);
void ShrinkWithoutCell(nsTableCellMap& aMap,
nsTableCellFrame& aCellFrame,
PRInt32 aRowIndex,
PRInt32 aColIndex);
PRInt32 aColIndex,
nsRect& aDamageArea);
void RebuildConsideringRows(nsIPresContext* aPresContext,
nsTableCellMap& aMap,
PRInt32 aStartRowIndex,
nsVoidArray* aRowsToInsert,
PRInt32 aNumRowsToRemove = 0);
PRInt32 aNumRowsToRemove,
nsRect& aDamageArea);
void RebuildConsideringCells(nsTableCellMap& aMap,
nsVoidArray* aCellFrames,
PRInt32 aRowIndex,
PRInt32 aColIndex,
PRBool aInsert);
PRBool aInsert,
nsRect& aDamageArea);
PRBool CellsSpanOut(nsIPresContext* aPresContext,
nsVoidArray& aNewRows);
@ -327,21 +407,10 @@ protected:
PRBool CreateEmptyRow(PRInt32 aRowIndex,
PRInt32 aNumCols);
PRInt32 GetRowSpan(nsTableCellMap& aMap,
PRInt32 aRowIndex,
PRInt32 aColIndex,
PRBool aGetEffective,
PRBool& aIsZeroRowSpan);
PRInt32 GetRowSpanForNewCell(nsTableCellFrame& aCellFrameToAdd,
PRInt32 aRowIndex,
PRBool& aIsZeroRowSpan);
PRInt32 GetEffectiveColSpan(nsTableCellMap& aMap,
PRInt32 aRowIndex,
PRInt32 aColIndex,
PRBool& aIsZeroColSpan);
PRInt32 GetColSpanForNewCell(nsTableCellFrame& aCellFrameToAdd,
PRInt32 aColIndex,
PRInt32 aNumColsInTable,

View File

@ -76,7 +76,8 @@ public:
* @param aPixelToTwips - the number of twips in a pixel.
* @return - the basis for percent calculations
*/
virtual nscoord CalcPctAdjTableWidth(const nsHTMLReflowState& aReflowState,
virtual nscoord CalcPctAdjTableWidth(nsIPresContext& aPresContext,
const nsHTMLReflowState& aReflowState,
nscoord aAvailWidth,
float aPixelToTwips)=0;

View File

@ -100,7 +100,7 @@ nsTableCellFrame::GetNextCell() const
while (childFrame) {
nsCOMPtr<nsIAtom> frameType;
childFrame->GetFrameType(getter_AddRefs(frameType));
if (nsLayoutAtoms::tableCellFrame == frameType.get()) {
if (IS_TABLE_CELL(frameType.get())) {
return (nsTableCellFrame*)childFrame;
}
childFrame->GetNextSibling(&childFrame);
@ -439,7 +439,7 @@ nsTableCellFrame::Paint(nsIPresContext* aPresContext,
if ((NS_SUCCEEDED(rv)) && tableFrame) {
const nsStyleTableBorder* tableStyle;
tableFrame->GetStyleData(eStyleStruct_TableBorder, ((const nsStyleStruct *&)tableStyle));
if (NS_STYLE_BORDER_SEPARATE == tableFrame->GetBorderCollapseStyle()) {
if (!tableFrame->IsBorderCollapse()) {
nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this,
aDirtyRect, rect, *myBorder, mStyleContext, skipSides);
}
@ -582,10 +582,9 @@ void nsTableCellFrame::VerticallyAlignChild(nsIPresContext* aPresContex
const nsStyleTextReset* textStyle =
(const nsStyleTextReset*)mStyleContext->GetStyleData(eStyleStruct_TextReset);
/* XXX: remove tableFrame when border-collapse inherits */
nsTableFrame* tableFrame = nsnull;
(void) nsTableFrame::GetTableFrame(this, tableFrame);
GET_PIXELS_TO_TWIPS(aPresContext, p2t);
nsMargin borderPadding;
GetCellBorder (borderPadding, tableFrame);
GetBorderWidth (p2t, borderPadding);
nsMargin padding = nsTableFrame::GetPadding(aReflowState, this);
borderPadding += padding;
@ -822,13 +821,13 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext,
PRBool contentEmptyBeforeReflow = GetContentEmpty();
/* XXX: remove tableFrame when border-collapse inherits */
nsTableFrame* tableFrame=nsnull;
rv = nsTableFrame::GetTableFrame(this, tableFrame);
nsTableFrame* tableFrame = nsnull;
rv = nsTableFrame::GetTableFrame(this, tableFrame); if (!tableFrame) ABORT1(NS_ERROR_NULL_POINTER);
nsTableFrame* tableFrameFirstInFlow = (nsTableFrame*)tableFrame->GetFirstInFlow();
nsMargin borderPadding = aReflowState.mComputedPadding;
nsMargin border;
GetCellBorder(border, tableFrame);
GetBorderWidth(p2t, border);
if ((NS_UNCONSTRAINEDSIZE == availSize.width) || !contentEmptyBeforeReflow) {
borderPadding += border;
}
@ -1130,51 +1129,6 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext,
return NS_OK;
}
/**
*
* Update the border style to map to the HTML border style
*
*/
void nsTableCellFrame::MapHTMLBorderStyle(nsIPresContext* aPresContext,
nsStyleBorder& aBorderStyle,
nsTableFrame* aTableFrame)
{
//adjust the border style based on the table rules attribute
/* The RULES code below has been disabled because collapsing borders have been disabled
and RULES depend on collapsing borders
const nsStyleTable* tableStyle;
aTableFrame->GetStyleData(eStyleStruct_Table, (const nsStyleStruct *&)tableStyle);
switch (tableStyle->mRules)
{
case NS_STYLE_TABLE_RULES_NONE:
aBorderStyle.SetBorderStyle(NS_SIDE_TOP, NS_STYLE_BORDER_STYLE_NONE);
aBorderStyle.SetBorderStyle(NS_SIDE_LEFT, NS_STYLE_BORDER_STYLE_NONE);
aBorderStyle.SetBorderStyle(NS_SIDE_BOTTOM, NS_STYLE_BORDER_STYLE_NONE);
aBorderStyle.SetBorderStyle(NS_SIDE_RIGHT, NS_STYLE_BORDER_STYLE_NONE);
break;
case NS_STYLE_TABLE_RULES_COLS:
aBorderStyle.SetBorderStyle(NS_SIDE_TOP, NS_STYLE_BORDER_STYLE_NONE);
aBorderStyle.SetBorderStyle(NS_SIDE_BOTTOM, NS_STYLE_BORDER_STYLE_NONE);
break;
case NS_STYLE_TABLE_RULES_ROWS:
aBorderStyle.SetBorderStyle(NS_SIDE_LEFT, NS_STYLE_BORDER_STYLE_NONE);
aBorderStyle.SetBorderStyle(NS_SIDE_RIGHT, NS_STYLE_BORDER_STYLE_NONE);
break;
default:
// do nothing for "GROUPS" or "ALL" or for any illegal value
// "GROUPS" will be handled in nsTableFrame::ProcessGroupRules
break;
}
*/
}
PRBool nsTableCellFrame::ConvertToPixelValue(nsHTMLValue& aValue, PRInt32 aDefault, PRInt32& aResult)
{
if (aValue.GetUnit() == eHTMLUnit_Pixel)
@ -1401,13 +1355,16 @@ nsTableCellFrame::GetNextCellInColumn(nsITableCellLayout **aCellLayout)
}
nsresult
NS_NewTableCellFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
NS_NewTableCellFrame(nsIPresShell* aPresShell,
PRBool aIsBorderCollapse,
nsIFrame** aNewFrame)
{
NS_PRECONDITION(aNewFrame, "null OUT ptr");
if (nsnull == aNewFrame) {
return NS_ERROR_NULL_POINTER;
}
nsTableCellFrame* it = new (aPresShell) nsTableCellFrame;
nsTableCellFrame* it = (aIsBorderCollapse) ? new (aPresShell) nsBCTableCellFrame
: new (aPresShell) nsTableCellFrame;
if (nsnull == it) {
return NS_ERROR_OUT_OF_MEMORY;
}
@ -1415,27 +1372,16 @@ NS_NewTableCellFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
return NS_OK;
}
/* ----- methods from CellLayoutData ----- */
void
nsTableCellFrame::GetCellBorder(nsMargin& aBorder,
nsTableFrame* aTableFrame)
nsMargin*
nsTableCellFrame::GetBorderWidth(float aPixelsToTwips,
nsMargin& aBorder) const
{
aBorder.left = aBorder.right = aBorder.top = aBorder.bottom = 0;
if (nsnull==aTableFrame) {
return;
}
if (NS_STYLE_BORDER_SEPARATE == aTableFrame->GetBorderCollapseStyle()) {
const nsStyleBorder* borderData;
GetStyleData(eStyleStruct_Border, (const nsStyleStruct*&)borderData);
borderData->GetBorder(aBorder);
}
else {
NS_ASSERTION(PR_FALSE, "not implemented");
}
const nsStyleBorder* borderData;
GetStyleData(eStyleStruct_Border, (const nsStyleStruct*&)borderData);
borderData->GetBorder(aBorder);
return &aBorder;
}
NS_IMETHODIMP
@ -1502,3 +1448,100 @@ nsTableCellFrame::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const
return NS_OK;
}
#endif
// nsBCTableCellFrame
nsBCTableCellFrame::nsBCTableCellFrame()
:nsTableCellFrame()
{
mTopBorder = mRightBorder = mBottomBorder = mLeftBorder = 0;
}
nsBCTableCellFrame::~nsBCTableCellFrame()
{
}
NS_IMETHODIMP
nsBCTableCellFrame::GetFrameType(nsIAtom** aType) const
{
NS_PRECONDITION(nsnull != aType, "null OUT parameter pointer");
*aType = nsLayoutAtoms::bcTableCellFrame;
NS_ADDREF(*aType);
return NS_OK;
}
#ifdef DEBUG
NS_IMETHODIMP
nsBCTableCellFrame::GetFrameName(nsAString& aResult) const
{
return MakeFrameName(NS_LITERAL_STRING("BCTableCell"), aResult);
}
#endif
void
nsBCTableCellFrame::SetBorderWidth(const nsMargin& aBorder)
{
mTopBorder = aBorder.top;
mRightBorder = aBorder.right;
mBottomBorder = aBorder.bottom;
mLeftBorder = aBorder.left;
}
nsMargin*
nsBCTableCellFrame::GetBorderWidth(float aPixelsToTwips,
nsMargin& aBorder) const
{
aBorder.top = (aPixelsToTwips) ? NSToCoordRound(aPixelsToTwips * mTopBorder) : mTopBorder;
aBorder.right = (aPixelsToTwips) ? NSToCoordRound(aPixelsToTwips * mRightBorder) : mRightBorder;
aBorder.bottom = (aPixelsToTwips) ? NSToCoordRound(aPixelsToTwips * mBottomBorder): mBottomBorder;
aBorder.left = (aPixelsToTwips) ? NSToCoordRound(aPixelsToTwips * mLeftBorder): mLeftBorder;
return &aBorder;
}
nscoord
nsBCTableCellFrame::GetBorderWidth(PRUint8 aSide) const
{
switch(aSide) {
case NS_SIDE_TOP:
return (PRUint8)mTopBorder;
case NS_SIDE_RIGHT:
return (PRUint8)mRightBorder;
case NS_SIDE_BOTTOM:
return (PRUint8)mBottomBorder;
default:
return (PRUint8)mLeftBorder;
}
}
void
nsBCTableCellFrame::SetBorderWidth(PRUint8 aSide,
nscoord aValue)
{
switch(aSide) {
case NS_SIDE_TOP:
mTopBorder = aValue;
break;
case NS_SIDE_RIGHT:
mRightBorder = aValue;
break;
case NS_SIDE_BOTTOM:
mBottomBorder = aValue;
break;
default:
mLeftBorder = aValue;
}
}
#ifdef DEBUG
NS_IMETHODIMP
nsBCTableCellFrame::SizeOf(nsISizeOfHandler* aHandler,
PRUint32* aResult) const
{
if (!aResult) {
return NS_ERROR_NULL_POINTER;
}
PRUint32 sum = sizeof(*this);
*aResult = sum;
return NS_OK;
}
#endif

View File

@ -43,6 +43,7 @@
#include "nsTableRowFrame.h" // need to actually include this here to inline GetRowIndex
#include "nsIStyleContext.h"
#include "nsIPercentHeightObserver.h"
#include "nsLayoutAtoms.h"
class nsTableFrame;
class nsHTMLValue;
@ -266,6 +267,9 @@ public:
nsTableCellFrame* GetNextCell() const;
virtual nsMargin* GetBorderWidth(float aPixelsToTwips,
nsMargin& aBorder) const;
protected:
/** implement abstract method on nsHTMLContainerFrame */
virtual PRIntn GetSkipSides() const;
@ -277,18 +281,11 @@ private:
// All these methods are support methods for RecalcLayoutData
nsIFrame* GetFrameAt(nsVoidArray* aList, PRInt32 aIndex);
//XXX: aTableFrame can be removed as soon as border-collapse inherits correctly
void GetCellBorder(nsMargin &aBorder, nsTableFrame *aTableFrame);
protected:
friend class nsTableRowFrame;
void MapBorderPadding(nsIPresContext* aPresContext);
void MapHTMLBorderStyle(nsIPresContext* aPresContext,
nsStyleBorder& aBorderStyle,
nsTableFrame* aTableFrame);
void MapVAlignAttribute(nsIPresContext* aPresContext, nsTableFrame *aTableFrame);
void MapHAlignAttribute(nsIPresContext* aPresContext, nsTableFrame *aTableFrame);
@ -421,6 +418,41 @@ inline void nsTableCellFrame::SetLastBlockHeight(nscoord aValue)
{
mBits.mLastBlockHeight = aValue;
}
// nsBCTableCellFrame
class nsBCTableCellFrame : public nsTableCellFrame
{
public:
nsBCTableCellFrame();
~nsBCTableCellFrame();
NS_IMETHOD GetFrameType(nsIAtom** aType) const;
virtual nsMargin* GetBorderWidth(float aPixelsToTwips,
nsMargin& aBorder) const;
nscoord GetBorderWidth(PRUint8 aSide) const;
void SetBorderWidth(const nsMargin& aBorder);
void SetBorderWidth(PRUint8 aSide, nscoord aPixelValue);
#ifdef DEBUG
NS_IMETHOD GetFrameName(nsAString& aResult) const;
NS_IMETHOD SizeOf(nsISizeOfHandler* aSizer, PRUint32* aResult) const;
#endif
private:
PRUint32 mTopBorder: 8;
PRUint32 mRightBorder: 8;
PRUint32 mBottomBorder: 8;
PRUint32 mLeftBorder: 8;
};
#define IS_TABLE_CELL(frameType)\
((nsLayoutAtoms::tableCellFrame == frameType) || (nsLayoutAtoms::bcTableCellFrame == frameType))
#endif

View File

@ -113,7 +113,8 @@ nsStyleCoord nsTableColFrame::GetStyleWidth() const
nsStyleCoord styleWidth = position->mWidth;
// the following should not be necessary since html.css defines table-col and
// :table-col to inherit. However, :table-col is not inheriting properly
if (eStyleUnit_Auto == styleWidth.GetUnit()) {
if (eStyleUnit_Auto == styleWidth.GetUnit() ||
eStyleUnit_Inherit == styleWidth.GetUnit()) {
nsIFrame* parent;
GetParent(&parent);
nsCOMPtr<nsIStyleContext> styleContext;
@ -305,6 +306,22 @@ nsTableColFrame::Init(nsIPresContext* aPresContext,
return rv;
}
nsTableColFrame*
nsTableColFrame::GetNextCol() const
{
nsIFrame* childFrame;
GetNextSibling(&childFrame);
while (childFrame) {
nsCOMPtr<nsIAtom> frameType;
childFrame->GetFrameType(getter_AddRefs(frameType));
if (nsLayoutAtoms::tableColFrame == frameType.get()) {
return (nsTableColFrame*)childFrame;
}
childFrame->GetNextSibling(&childFrame);
}
return nsnull;
}
NS_IMETHODIMP
nsTableColFrame::GetFrameType(nsIAtom** aType) const
{

View File

@ -102,6 +102,8 @@ public:
void SetColIndex (PRInt32 aColIndex);
nsTableColFrame* GetNextCol() const;
NS_IMETHOD Init(nsIPresContext* aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
@ -164,6 +166,11 @@ public:
void ResetSizingInfo();
nscoord GetLeftBorderWidth(float* aPixelsToTwips = nsnull);
void SetLeftBorderWidth(nscoord aWidth);
nscoord GetRightBorderWidth(float* aPixelsToTwips = nsnull);
void SetRightBorderWidth(nscoord aWidth);
void Dump(PRInt32 aIndent);
protected:
@ -172,17 +179,46 @@ protected:
~nsTableColFrame();
// the starting index of the column (starting at 0) that this col object represents //
PRInt32 mColIndex;
PRUint32 mColIndex: 16;
PRUint32 mLeftBorderWidth: 8; // stored as pixels
PRUint32 mRightBorderWidth: 8; // stored as pixels
// 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.
nscoord mWidths[NUM_WIDTHS];
};
inline PRInt32 nsTableColFrame::GetColIndex() const
{ return mColIndex; }
{
return mColIndex;
}
inline void nsTableColFrame::SetColIndex (PRInt32 aColIndex)
{ mColIndex = aColIndex; }
{
mColIndex = aColIndex;
}
inline nscoord nsTableColFrame::GetLeftBorderWidth(float* aPixelsToTwips)
{
nscoord width = (aPixelsToTwips) ? NSToCoordRound(*aPixelsToTwips * mLeftBorderWidth) : mLeftBorderWidth;
return width;
}
inline void nsTableColFrame::SetLeftBorderWidth(nscoord aWidth)
{
mLeftBorderWidth = aWidth;
}
inline nscoord nsTableColFrame::GetRightBorderWidth(float* aPixelsToTwips)
{
nscoord width = (aPixelsToTwips) ? NSToCoordRound(*aPixelsToTwips * mRightBorderWidth) : mRightBorderWidth;
return width;
}
inline void nsTableColFrame::SetRightBorderWidth(nscoord aWidth)
{
mRightBorderWidth = aWidth;
}
#endif

View File

@ -250,29 +250,6 @@ nsTableColGroupFrame::SetInitialChildList(nsIPresContext* aPresContext,
return NS_OK;
}
nsIFrame* kidFrame = aChildList;
while (kidFrame) {
nsIAtom* kidType;
kidFrame->GetFrameType(&kidType);
if (nsLayoutAtoms::tableColFrame == kidType) {
// Set the preliminary values for the column frame
PRInt32 span = ((nsTableColFrame*)kidFrame)->GetSpan();
if (span > 1) {
nsTableColFrame* firstSpannedCol;
tableFrame->CreateAnonymousColFrames(*aPresContext, *this, span - 1, eColAnonymousCol,
PR_FALSE, (nsTableColFrame*)kidFrame, (nsIFrame **)&firstSpannedCol);
nsIFrame* spanner = kidFrame;
kidFrame->GetNextSibling(&kidFrame); // need to do this before we insert the new frames
nsFrameList newChildren(aChildList); // used as a convience to hook up siblings
newChildren.InsertFrames(this, (nsTableColFrame*)spanner, (nsIFrame *)firstSpannedCol);
NS_RELEASE(kidType);
continue;
}
}
NS_IF_RELEASE(kidType);
kidFrame->GetNextSibling(&kidFrame);
}
mFrames.AppendFrames(this, aChildList);
return NS_OK;
}

File diff suppressed because it is too large Load Diff

View File

@ -53,7 +53,6 @@ class nsTableColFrame;
class nsTableRowGroupFrame;
class nsTableRowFrame;
class nsTableColGroupFrame;
class nsTableBorderCollapser;
class nsITableLayoutStrategy;
class nsHTMLValue;
@ -208,6 +207,8 @@ public:
nsIAtom* aPropertyName,
PRBool aCreateIfNecessary = PR_FALSE);
static float GetTwipsToPixels(nsIPresContext* aPresContext);
static nscoord RoundToPixel(nscoord aValue,
float aPixelToTwips,
nsPixelRound aRound= eAlwaysRoundUp);
@ -249,7 +250,13 @@ public:
nsIAtom* aListName,
nsIFrame* aOldFrame);
nsMargin GetBorderPadding(const nsHTMLReflowState& aReflowState) const;
// Get the offset from the border box to the area where the row groups fit
nsMargin GetChildAreaOffset(nsIPresContext& aPresContext,
const nsHTMLReflowState* aReflowState) const;
// Get the offset from the border box to the area where the content fits
nsMargin GetContentAreaOffset(nsIPresContext& aPresContext,
const nsHTMLReflowState* aReflowState) const;
/** helper method to find the table parent of any table frame object */
// TODO: today, this depends on display types. This should be changed to rely
@ -297,6 +304,17 @@ public:
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags = 0);
nsMargin* GetBCBorder(nsIPresContext& aPresContext,
PRBool aInnerBorderOnly,
nsMargin& aBorder) const;
void SetBCDamageArea(nsIPresContext& aPresContext,
const nsRect& aValue);
void PaintBCBorders(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect);
NS_IMETHOD GetFrameForPoint(nsIPresContext* aPresContext,
const nsPoint& aPoint,
nsFramePaintLayer aWhichLayer,
@ -371,15 +389,12 @@ public:
/** set the width of the column at aColIndex to aWidth */
virtual void SetColumnWidth(PRInt32 aColIndex, nscoord aWidth);
/** helper to get the border collapse style value */
virtual PRUint8 GetBorderCollapseStyle();
/** helper to get the cell spacing X style value */
virtual nscoord GetCellSpacingX();
/** helper to get the cell spacing Y style value */
virtual nscoord GetCellSpacingY();
/** return the row span of a cell, taking into account row span magic at the bottom
* of a table. The row span equals the number of rows spanned by aCell starting at
* aStartRowIndex, and can be smaller if aStartRowIndex is greater than the row
@ -440,9 +455,9 @@ public:
/** empty the column frame cache */
void ClearColCache();
virtual PRInt32 AppendCell(nsIPresContext& aPresContext,
nsTableCellFrame& aCellFrame,
PRInt32 aRowIndex);
virtual void AppendCell(nsIPresContext& aPresContext,
nsTableCellFrame& aCellFrame,
PRInt32 aRowIndex);
virtual void InsertCells(nsIPresContext& aPresContext,
nsVoidArray& aCellFrames,
@ -522,6 +537,9 @@ protected:
/** destructor, responsible for mColumnLayoutData */
virtual ~nsTableFrame();
void InitChildReflowState(nsIPresContext& aPresContext,
nsHTMLReflowState& aReflowState);
/** implement abstract method on nsHTMLContainerFrame */
virtual PRIntn GetSkipSides() const;
@ -619,7 +637,8 @@ protected:
nsIFrame* aKidFrame,
nscoord aDeltaY);
nsresult RecoverState(nsTableReflowState& aReflowState,
nsresult RecoverState(nsIPresContext& aPresContext,
nsTableReflowState& aReflowState,
nsIFrame* aKidFrame);
NS_METHOD CollapseRowGroupIfNecessary(nsIPresContext* aPresContext,
@ -646,10 +665,11 @@ public:
// calculate the computed height of aFrame including its border and padding given
// its reflow state.
nscoord CalcBorderBoxHeight(const nsHTMLReflowState& aReflowState);
nscoord CalcBorderBoxHeight(nsIPresContext* aPresContext,
const nsHTMLReflowState& aReflowState);
// calculate the minimum width to layout aFrame and its desired width
// including border and padding given its reflow state and column width information
void CalcMinAndPreferredWidths(nsIPresContext* aPresContextconst,
void CalcMinAndPreferredWidths(nsIPresContext* aPresContext,
const nsHTMLReflowState& aReflowState,
PRBool aCalcPrefWidthIfAutoWithPctCol,
nscoord& aMinWidth,
@ -657,7 +677,8 @@ public:
protected:
// calcs the width of the table according to the computed widths of each column.
virtual PRInt32 CalcDesiredWidth(const nsHTMLReflowState& aReflowState);
virtual PRInt32 CalcDesiredWidth(nsIPresContext& aPresContext,
const nsHTMLReflowState& aReflowState);
// return the desired height of this table accounting for the current
// reflow state, and for the table attributes and parent
@ -699,7 +720,7 @@ public:
PRUint32& aNumRowGroups,
nsIFrame** aFirstBody = nsnull,
nsTableRowGroupFrame** aHead = nsnull,
nsTableRowGroupFrame** aFoot = nsnull);
nsTableRowGroupFrame** aFoot = nsnull) const;
// Returns PR_TRUE if there are any cells above the row at
// aRowIndex and spanning into the row at aRowIndex
@ -735,9 +756,6 @@ protected:
PRBool DidResizeReflow() const;
void SetResizeReflow(PRBool aValue);
/** Support methods for DidSetStyleContext */
void MapBorderMarginPadding(nsIPresContext* aPresContext);
void MapHTMLBorderStyle(nsStyleBorder& aBorderStyle, nscoord aBorderWidth);
PRBool ConvertToPixelValue(nsHTMLValue& aValue,
PRInt32 aDefault,
PRInt32& aResult);
@ -749,6 +767,11 @@ public:
PRBool NeedStrategyBalance() const;
void SetNeedStrategyBalance(PRBool aValue);
PRBool IsBorderCollapse() const;
PRBool NeedToCalcBCBorders() const;
void SetNeedToCalcBCBorders(PRBool aValue);
/** Get the cell map for this table frame. It is not always mCellMap.
* Only the firstInFlow has a legit cell map
*/
@ -763,9 +786,6 @@ public:
PRInt32 aRowIndex,
PRInt32 anAdjustment);
// Return PR_TRUE if rules=groups is set for the table content
PRBool HasGroupRules() const;
// Remove cell borders which aren't bordering row and/or col groups
void ProcessGroupRules(nsIPresContext* aPresContext);
@ -775,10 +795,16 @@ public:
* Return aFrame's child if aFrame is an nsScrollFrame, otherwise return aFrame
*/
nsTableRowGroupFrame* GetRowGroupFrame(nsIFrame* aFrame,
nsIAtom* aFrameTypeIn = nsnull);
nsIAtom* aFrameTypeIn = nsnull) const;
protected:
void SetBorderCollapse(PRBool aValue);
void CalcBCBorders(nsIPresContext& aPresContext);
void ExpandBCDamageArea(nsRect& aRect) const;
PRBool HadInitialReflow() const;
void SetHadInitialReflow(PRBool aValue);
@ -809,8 +835,8 @@ public: /* ----- Cell Map public methods ----- */
/** returns the number of columns in this table after redundant columns have been removed
*/
virtual PRInt32 GetEffectiveColCount();
virtual PRInt32 GetColCount();
virtual PRInt32 GetEffectiveColCount() const;
virtual PRInt32 GetColCount() const;
/** return the column frame at colIndex.
* returns nsnull if the col frame has not yet been allocated, or if aColIndex is out of range
@ -886,6 +912,7 @@ protected:
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
// true if a descendant was reflowed normally since the last time we reflowed.
// We will likely need a timeout reflow (targeted either at us or below)
unsigned mDescendantReflowedNotTimeout:1;
@ -896,7 +923,8 @@ protected:
unsigned mRowInserted:1;
unsigned mNeedSpecialReflow:1;
unsigned mNeedToInitiateSpecialReflow:1;
unsigned : 20; // unused
unsigned mNeedToCalcBCBorders:1;
unsigned : 18; // unused
} mBits;
nsTableCellMap* mCellMap; // maintains the relationships between rows, cols, and cells
@ -1054,8 +1082,26 @@ inline void nsTableFrame::SetPreferredWidth(nscoord aWidth)
mPreferredWidth = aWidth;
}
inline PRBool nsTableFrame::IsBorderCollapse() const
{
return (PRBool)mBits.mIsBorderCollapse;
}
inline void nsTableFrame::SetBorderCollapse(PRBool aValue)
{
mBits.mIsBorderCollapse = aValue;
}
inline PRBool nsTableFrame::NeedToCalcBCBorders() const
{
return (PRBool)mBits.mNeedToCalcBCBorders;
}
inline void nsTableFrame::SetNeedToCalcBCBorders(PRBool aValue)
{
mBits.mNeedToCalcBCBorders = (unsigned)aValue;
}
enum nsTableIteration {
eTableLTR = 0,
eTableRTL = 1,
@ -1085,6 +1131,23 @@ protected:
PRInt32 mCount;
};
#define ABORT0() \
{NS_ASSERTION(PR_FALSE, "CellIterator program error"); \
return;}
#define ABORT1(aReturn) \
{NS_ASSERTION(PR_FALSE, "CellIterator program error"); \
return aReturn;}
#define GET_PIXELS_TO_TWIPS(presContext,var) \
float var; \
(presContext)->GetScaledPixelsToTwips(&var);
#define GET_TWIPS_TO_PIXELS(presContext,var) \
float var; \
(presContext)->GetScaledPixelsToTwips(&var); \
var = 1.0f / var;
#endif

View File

@ -232,7 +232,14 @@ nsTableOuterFrame::SetInitialChildList(nsIPresContext* aPresContext,
}
else {
mFrames.SetFrames(aChildList);
mInnerTableFrame = aChildList;
mInnerTableFrame = nsnull;
if (aChildList) {
nsCOMPtr<nsIAtom> fType;
aChildList->GetFrameType(getter_AddRefs(fType));
if (nsLayoutAtoms::tableFrame == fType.get()) {
mInnerTableFrame = (nsTableFrame*)aChildList;
}
}
}
return NS_OK;
@ -466,21 +473,46 @@ FixAutoMargins(nscoord aAvailWidth,
}
}
void
nsTableOuterFrame::InitChildReflowState(nsIPresContext& aPresContext,
nsHTMLReflowState& aReflowState)
{
nsMargin collapseBorder;
nsMargin collapsePadding(0,0,0,0);
nsMargin* pCollapseBorder = nsnull;
nsMargin* pCollapsePadding = nsnull;
if ((aReflowState.frame == mInnerTableFrame) && (mInnerTableFrame->IsBorderCollapse())) {
if (mInnerTableFrame->NeedToCalcBCBorders()) {
mInnerTableFrame->CalcBCBorders(aPresContext);
}
pCollapseBorder = mInnerTableFrame->GetBCBorder(aPresContext, PR_FALSE, collapseBorder);
pCollapsePadding = &collapsePadding;
}
aReflowState.Init(&aPresContext, -1, -1, pCollapseBorder, pCollapsePadding);
}
// get the margin and padding data. nsHTMLReflowState doesn't handle the
// case of auto margins
void
GetMarginPadding(nsIPresContext* aPresContext,
const nsHTMLReflowState& aOuterRS,
nsIFrame* aChildFrame,
nsMargin& aMargin,
nsMargin& aMarginNoAuto,
nsMargin& aPadding)
nsTableOuterFrame::GetMarginPadding(nsIPresContext* aPresContext,
const nsHTMLReflowState& aOuterRS,
nsIFrame* aChildFrame,
nsMargin& aMargin,
nsMargin& aMarginNoAuto,
nsMargin& aPadding)
{
if (!aPresContext) ABORT0();
GET_PIXELS_TO_TWIPS(aPresContext, p2t);
// construct a reflow state to compute margin and padding. Auto margins
// will not be computed at this time.
// create an init the child reflow state
nsHTMLReflowState childRS(aPresContext, aOuterRS, aChildFrame,
nsSize(aOuterRS.availableWidth, aOuterRS.availableHeight),
eReflowReason_Resize);
eReflowReason_Resize, PR_FALSE);
InitChildReflowState(*aPresContext, childRS);
nsRect childRect;
aChildFrame->GetRect(childRect);
FixAutoMargins(aOuterRS.availableWidth, childRect.width, childRS);
@ -931,6 +963,7 @@ nsTableOuterFrame::OuterReflowChild(nsIPresContext* aPresContext,
nsReflowReason aReflowReason,
nsReflowStatus& aStatus)
{
if (!aPresContext) ABORT1(NS_ERROR_NULL_POINTER);
aMargin = aPadding = nsMargin(0,0,0,0);
nscoord availWidth = GetChildAvailWidth(aPresContext, aChildFrame, aOuterRS,
@ -946,9 +979,10 @@ nsTableOuterFrame::OuterReflowChild(nsIPresContext* aPresContext,
availHeight = nsTableFrame::RoundToPixel(availHeight, p2t, eAlwaysRoundDown);
}
nsHTMLReflowState childRS(aPresContext, aOuterRS, aChildFrame,
nsSize(availWidth, availHeight));
childRS.reason = aReflowReason;
// create and init the child reflow state
nsHTMLReflowState childRS(aPresContext, aOuterRS, aChildFrame, nsSize(availWidth, availHeight),
aReflowReason);
InitChildReflowState(*aPresContext, childRS);
childRS.mPercentHeightObserver = nsnull; // the observer is for non table related frames inside cells

View File

@ -47,6 +47,7 @@ class nsReflowTimer;
#endif
struct nsStyleTable;
class nsTableFrame;
class nsTableCaptionFrame : public nsBlockFrame
{
@ -201,6 +202,9 @@ protected:
nsTableOuterFrame();
virtual ~nsTableOuterFrame();
void InitChildReflowState(nsIPresContext& aPresContext,
nsHTMLReflowState& aReflowState);
/** Always returns 0, since the outer table frame has no border of its own
* The inner table frame can answer this question in a meaningful way.
* @see nsHTMLContainerFrame::GetSkipSides */
@ -362,11 +366,17 @@ protected:
PRBool aInnerChanged,
PRBool aCaptionChanged);
void GetMarginPadding(nsIPresContext* aPresContext,
const nsHTMLReflowState& aOuterRS,
nsIFrame* aChildFrame,
nsMargin& aMargin,
nsMargin& aMarginNoAuto,
nsMargin& aPadding);
private:
// used to keep track of this frame's children. They are redundant with mFrames, but more convient
nsIFrame* mInnerTableFrame;
nsIFrame* mCaptionFrame;
nsTableFrame* mInnerTableFrame;
nsIFrame* mCaptionFrame;
// used to track caption max element size
PRInt32 mMinCaptionWidth;

View File

@ -68,11 +68,6 @@ struct nsTableCellReflowState : public nsHTMLReflowState
const nsSize& aAvailableSpace,
nsReflowReason aReason);
nsTableCellReflowState(nsIPresContext* aPresContext,
const nsHTMLReflowState& aParentReflowState,
nsIFrame* aFrame,
const nsSize& aAvailableSpace);
void FixUp(const nsSize& aAvailSpace);
};
@ -83,16 +78,43 @@ nsTableCellReflowState::nsTableCellReflowState(nsIPresContext* aPresCon
nsReflowReason aReason)
:nsHTMLReflowState(aPresContext, aParentRS, aFrame, aAvailSpace, aReason)
{
FixUp(aAvailSpace);
}
nsTableCellReflowState::nsTableCellReflowState(nsIPresContext* aPresContext,
const nsHTMLReflowState& aParentRS,
nsIFrame* aFrame,
const nsSize& aAvailSpace)
:nsHTMLReflowState(aPresContext, aParentRS, aFrame, aAvailSpace)
void nsTableCellReflowState::FixUp(const nsSize& aAvailSpace)
{
FixUp(aAvailSpace);
// fix the mComputed values during a pass 2 reflow since the cell can be a percentage base
if (NS_UNCONSTRAINEDSIZE != aAvailSpace.width) {
if (NS_UNCONSTRAINEDSIZE != mComputedWidth) {
mComputedWidth = aAvailSpace.width - mComputedBorderPadding.left - mComputedBorderPadding.right;
mComputedWidth = PR_MAX(0, mComputedWidth);
}
if (NS_UNCONSTRAINEDSIZE != mComputedHeight) {
if (NS_UNCONSTRAINEDSIZE != aAvailSpace.height) {
mComputedHeight = aAvailSpace.height - mComputedBorderPadding.top - mComputedBorderPadding.bottom;
mComputedHeight = PR_MAX(0, mComputedHeight);
}
}
}
}
void
nsTableRowFrame::InitChildReflowState(nsIPresContext& aPresContext,
const nsSize& aAvailSize,
PRBool aBorderCollapse,
float aPixelsToTwips,
nsTableCellReflowState& aReflowState)
{
nsMargin collapseBorder;
nsMargin* pCollapseBorder = nsnull;
if (aBorderCollapse) {
// we only reflow cells, so don't need to check frame type
nsBCTableCellFrame* bcCellFrame = (nsBCTableCellFrame*)aReflowState.frame;
if (bcCellFrame) {
pCollapseBorder = bcCellFrame->GetBorderWidth(aPixelsToTwips, collapseBorder);
}
}
aReflowState.Init(&aPresContext, -1, -1, pCollapseBorder);
aReflowState.FixUp(aAvailSize);
}
void
@ -132,23 +154,6 @@ nsTableRowFrame::SetPctHeight(float aPctValue,
}
}
void nsTableCellReflowState::FixUp(const nsSize& aAvailSpace)
{
// fix the mComputed values during a pass 2 reflow since the cell can be a percentage base
if (NS_UNCONSTRAINEDSIZE != aAvailSpace.width) {
if (NS_UNCONSTRAINEDSIZE != mComputedWidth) {
mComputedWidth = aAvailSpace.width - mComputedBorderPadding.left - mComputedBorderPadding.right;
mComputedWidth = PR_MAX(0, mComputedWidth);
}
if (NS_UNCONSTRAINEDSIZE != mComputedHeight) {
if (NS_UNCONSTRAINEDSIZE != aAvailSpace.height) {
mComputedHeight = aAvailSpace.height - mComputedBorderPadding.top - mComputedBorderPadding.bottom;
mComputedHeight = PR_MAX(0, mComputedHeight);
}
}
}
}
// 'old' is old cached cell's desired size
// 'new' is new cell's size including style constraints
static PRBool
@ -217,7 +222,7 @@ nsTableRowFrame::SetInitialChildList(nsIPresContext* aPresContext,
kidFrame->GetNextSibling(&kidFrame)) {
nsCOMPtr<nsIAtom> frameType;
kidFrame->GetFrameType(getter_AddRefs(frameType));
if (nsLayoutAtoms::tableCellFrame == frameType.get()) {
if (IS_TABLE_CELL(frameType.get())) {
if (((nsTableCellFrame*)kidFrame)->GetRowSpan() > 1) {
mState |= NS_FRAME_OUTSIDE_CHILDREN;
}
@ -241,7 +246,7 @@ nsTableRowFrame::AppendFrames(nsIPresContext* aPresContext,
for (nsIFrame* childFrame = aFrameList; childFrame; childFrame->GetNextSibling(&childFrame)) {
nsCOMPtr<nsIAtom> frameType;
childFrame->GetFrameType(getter_AddRefs(frameType));
if (nsLayoutAtoms::tableCellFrame == frameType.get()) {
if (IS_TABLE_CELL(frameType.get())) {
// Add the cell to the cell map
tableFrame->AppendCell(*aPresContext, (nsTableCellFrame&)*childFrame, GetRowIndex());
// XXX this could be optimized with some effort
@ -272,12 +277,13 @@ nsTableRowFrame::InsertFrames(nsIPresContext* aPresContext,
nsTableFrame::GetTableFrame(this, tableFrame);
// gather the new frames (only those which are cells) into an array
nsTableCellFrame* prevCellFrame = (nsTableCellFrame *)nsTableFrame::GetFrameAtOrBefore(aPresContext, this, aPrevFrame, nsLayoutAtoms::tableCellFrame);
nsIAtom* cellFrameType = (tableFrame->IsBorderCollapse()) ? nsLayoutAtoms::bcTableCellFrame : nsLayoutAtoms::tableCellFrame;
nsTableCellFrame* prevCellFrame = (nsTableCellFrame *)nsTableFrame::GetFrameAtOrBefore(aPresContext, this, aPrevFrame, cellFrameType);
nsVoidArray cellChildren;
for (nsIFrame* childFrame = aFrameList; childFrame; childFrame->GetNextSibling(&childFrame)) {
nsCOMPtr<nsIAtom> frameType;
childFrame->GetFrameType(getter_AddRefs(frameType));
if (nsLayoutAtoms::tableCellFrame == frameType.get()) {
if (IS_TABLE_CELL(frameType.get())) {
cellChildren.AppendElement(childFrame);
// XXX this could be optimized with some effort
tableFrame->SetNeedStrategyInit(PR_TRUE);
@ -315,7 +321,7 @@ nsTableRowFrame::RemoveFrame(nsIPresContext* aPresContext,
if (tableFrame) {
nsCOMPtr<nsIAtom> frameType;
aOldFrame->GetFrameType(getter_AddRefs(frameType));
if (nsLayoutAtoms::tableCellFrame == frameType.get()) {
if (IS_TABLE_CELL(frameType.get())) {
nsTableCellFrame* cellFrame = (nsTableCellFrame*)aOldFrame;
PRInt32 colIndex;
cellFrame->GetColIndex(colIndex);
@ -372,7 +378,7 @@ nsTableRowFrame::GetFirstCell()
while (childFrame) {
nsCOMPtr<nsIAtom> frameType;
childFrame->GetFrameType(getter_AddRefs(frameType));
if (nsLayoutAtoms::tableCellFrame == frameType.get()) {
if (IS_TABLE_CELL(frameType.get())) {
return (nsTableCellFrame*)childFrame;
}
childFrame->GetNextSibling(&childFrame);
@ -398,7 +404,7 @@ nsTableRowFrame::DidResize(nsIPresContext* aPresContext,
while (childFrame) {
nsCOMPtr<nsIAtom> frameType;
childFrame->GetFrameType(getter_AddRefs(frameType));
if (nsLayoutAtoms::tableCellFrame == frameType.get()) {
if (IS_TABLE_CELL(frameType.get())) {
nsTableCellFrame* cellFrame = (nsTableCellFrame*)childFrame;
nscoord cellHeight = mRect.height + GetHeightOfRowsSpannedBelowFirst(*cellFrame, *tableFrame);
@ -534,7 +540,7 @@ nsTableRowFrame::CalcHeight(const nsHTMLReflowState& aReflowState)
for (nsIFrame* kidFrame = mFrames.FirstChild(); kidFrame; kidFrame->GetNextSibling(&kidFrame)) {
nsCOMPtr<nsIAtom> frameType;
kidFrame->GetFrameType(getter_AddRefs(frameType));
if (nsLayoutAtoms::tableCellFrame == frameType.get()) {
if (IS_TABLE_CELL(frameType.get())) {
nscoord availWidth = ((nsTableCellFrame *)kidFrame)->GetPriorAvailWidth();
nsSize desSize = ((nsTableCellFrame *)kidFrame)->GetDesiredSize();
if ((NS_UNCONSTRAINEDSIZE == aReflowState.availableHeight) && !mPrevInFlow) {
@ -888,28 +894,29 @@ nsTableRowFrame::ReflowChildren(nsIPresContext* aPresContext,
aStatus = NS_FRAME_COMPLETE;
if (!mFrames.FirstChild()) return NS_OK;
nsTableFrame* tableFrame = &aTableFrame;
if (!tableFrame) return NS_ERROR_NULL_POINTER;
GET_PIXELS_TO_TWIPS(aPresContext, p2t);
PRBool borderCollapse = (((nsTableFrame*)aTableFrame.GetFirstInFlow())->IsBorderCollapse());
nsIFrame* tablePrevInFlow;
tableFrame->GetPrevInFlow(&tablePrevInFlow);
aTableFrame.GetPrevInFlow(&tablePrevInFlow);
PRBool isPaginated;
aPresContext->IsPaginated(&isPaginated);
nsresult rv = NS_OK;
nscoord cellSpacingX = tableFrame->GetCellSpacingX();
nscoord cellSpacingX = aTableFrame.GetCellSpacingX();
PRInt32 cellColSpan = 1; // must be defined here so it's set properly for non-cell kids
nsTableIteration dir = (aReflowState.availableWidth == NS_UNCONSTRAINEDSIZE)
? eTableLTR : eTableDIR;
nsTableIterator iter(aPresContext, *this, dir);
// remember the col index of the previous cell to handle rowspans into this row
PRInt32 firstPrevColIndex = (iter.IsLeftToRight()) ? -1 : tableFrame->GetColCount();
PRInt32 firstPrevColIndex = (iter.IsLeftToRight()) ? -1 : aTableFrame.GetColCount();
PRInt32 prevColIndex = firstPrevColIndex;
nscoord x = 0; // running total of children x offset
nsTableFrame* tableFirstInFlow = (nsTableFrame*)tableFrame->GetFirstInFlow();
PRBool isAutoLayout = tableFrame->IsAutoLayout();
nsTableFrame* tableFirstInFlow = (nsTableFrame*)aTableFrame.GetFirstInFlow();
PRBool isAutoLayout = aTableFrame.IsAutoLayout();
PRBool needToNotifyTable = PR_TRUE;
nscoord paginatedHeight = 0;
// If the incremental reflow command is a StyleChanged reflow and
@ -945,7 +952,7 @@ nsTableRowFrame::ReflowChildren(nsIPresContext* aPresContext,
doReflowChild = PR_FALSE;
}
if (aReflowState.mFlags.mSpecialHeightReflow) {
if (!isPaginated && (nsLayoutAtoms::tableCellFrame == frameType.get() &&
if (!isPaginated && (IS_TABLE_CELL(frameType.get()) &&
!((nsTableCellFrame*)kidFrame)->NeedSpecialReflow())) {
kidFrame = iter.Next();
continue;
@ -954,22 +961,22 @@ nsTableRowFrame::ReflowChildren(nsIPresContext* aPresContext,
// Reflow the child frame
if (doReflowChild) {
if (nsLayoutAtoms::tableCellFrame == frameType.get()) {
if (IS_TABLE_CELL(frameType.get())) {
nsTableCellFrame* cellFrame = (nsTableCellFrame*)kidFrame;
PRInt32 cellColIndex;
cellFrame->GetColIndex(cellColIndex);
cellColSpan = tableFrame->GetEffectiveColSpan(*cellFrame);
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))) {
x += GetSpaceBetween(prevColIndex, cellColIndex, cellColSpan, *tableFrame,
x += GetSpaceBetween(prevColIndex, cellColIndex, cellColSpan, aTableFrame,
cellSpacingX, iter.IsLeftToRight());
}
// Calculate the available width for the table cell using the known column widths
nscoord availColWidth, availCellWidth;
CalcAvailWidth(*tableFrame, GetComputedWidth(aReflowState, *tableFrame),
CalcAvailWidth(aTableFrame, GetComputedWidth(aReflowState, aTableFrame),
*cellFrame, cellSpacingX, availColWidth, availCellWidth);
if (0 == availColWidth) availColWidth = NS_UNCONSTRAINEDSIZE;
if (0 == availCellWidth) availCellWidth = NS_UNCONSTRAINEDSIZE;
@ -1032,6 +1039,8 @@ nsTableRowFrame::ReflowChildren(nsIPresContext* aPresContext,
// Reflow the child
nsTableCellReflowState kidReflowState(aPresContext, aReflowState,
kidFrame, kidAvailSize, reason);
InitChildReflowState(*aPresContext, kidAvailSize, borderCollapse, p2t, kidReflowState);
nsReflowStatus status;
rv = ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState,
x, 0, 0, status);
@ -1052,7 +1061,7 @@ nsTableRowFrame::ReflowChildren(nsIPresContext* aPresContext,
// allow the table to determine if/how the table needs to be rebalanced
if (cellToWatch && needToNotifyTable) {
needToNotifyTable = !tableFrame->CellChangedWidth(*cellFrame, oldMaxWidth, oldMaxElemWidth);
needToNotifyTable = !aTableFrame.CellChangedWidth(*cellFrame, oldMaxWidth, oldMaxElemWidth);
}
// If any of the cells are not complete, then we're not complete
@ -1081,10 +1090,10 @@ nsTableRowFrame::ReflowChildren(nsIPresContext* aPresContext,
// height may have changed, adjust descent to absorb any excess difference
nscoord ascent = cellFrame->GetDesiredAscent();
nscoord descent = desiredSize.height - ascent;
UpdateHeight(desiredSize.height, ascent, descent, tableFrame, cellFrame);
UpdateHeight(desiredSize.height, ascent, descent, &aTableFrame, cellFrame);
}
else {
PRInt32 rowSpan = tableFrame->GetEffectiveRowSpan((nsTableCellFrame&)*kidFrame);
PRInt32 rowSpan = aTableFrame.GetEffectiveRowSpan((nsTableCellFrame&)*kidFrame);
if ((1 == rowSpan) && (desiredSize.height > paginatedHeight)) {
paginatedHeight = desiredSize.height;
SetContentHeight(paginatedHeight);
@ -1102,13 +1111,14 @@ nsTableRowFrame::ReflowChildren(nsIPresContext* aPresContext,
else {// it's an unknown frame type, give it a generic reflow and ignore the results
nsTableCellReflowState kidReflowState(aPresContext, aReflowState,
kidFrame, nsSize(0,0), eReflowReason_Resize);
InitChildReflowState(*aPresContext, nsSize(0,0), PR_FALSE, p2t, kidReflowState);
nsHTMLReflowMetrics desiredSize(nsnull);
nsReflowStatus status;
ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState, 0, 0, 0, status);
kidFrame->DidReflow(aPresContext, nsnull, NS_FRAME_REFLOW_FINISHED);
}
}
else if (nsLayoutAtoms::tableCellFrame == frameType.get()) {
else if (IS_TABLE_CELL(frameType.get())) {
// we need to account for the cell's width even if it isn't reflowed
nsRect rect;
kidFrame->GetRect(rect);
@ -1244,7 +1254,10 @@ nsTableRowFrame::IR_TargetIsChild(nsIPresContext* aPresContext,
// update its maximum width.
nsHTMLReflowMetrics cellMet(&kidMaxElementSize, isAutoLayout ?
NS_REFLOW_CALC_MAX_WIDTH : 0);
nsTableCellReflowState kidRS(aPresContext, aReflowState, aNextFrame, cellAvailSize);
GET_PIXELS_TO_TWIPS(aPresContext, p2t);
nsTableCellReflowState kidRS(aPresContext, aReflowState, aNextFrame, cellAvailSize,
aReflowState.reason);
InitChildReflowState(*aPresContext, cellAvailSize, aTableFrame.IsBorderCollapse(), p2t, kidRS);
// Remember the current desired size, we'll need it later
nscoord oldCellMinWidth = cellFrame->GetPass1MaxElementWidth();
@ -1492,13 +1505,20 @@ nsTableRowFrame::ReflowCellFrame(nsIPresContext* aPresContext,
nscoord aAvailableHeight,
nsReflowStatus& aStatus)
{
nsTableFrame* tableFrame = nsnull;
nsTableFrame::GetTableFrame(this, tableFrame); if (!tableFrame) ABORT1(0);
// Reflow the cell frame with the specified height. Use the existing width
nsSize cellSize;
aCellFrame->GetSize(cellSize);
nsSize availSize(cellSize.width, aAvailableHeight);
PRBool borderCollapse = ((nsTableFrame*)tableFrame->GetFirstInFlow())->IsBorderCollapse();
GET_PIXELS_TO_TWIPS(aPresContext, p2t);
nsTableCellReflowState cellReflowState(aPresContext, aReflowState, aCellFrame, availSize,
eReflowReason_Resize);
InitChildReflowState(*aPresContext, availSize, borderCollapse, p2t, cellReflowState);
nsHTMLReflowMetrics desiredSize(nsnull);
ReflowChild(aCellFrame, aPresContext, desiredSize, cellReflowState,
@ -1534,7 +1554,7 @@ nsTableRowFrame::InsertCellFrame(nsTableCellFrame* aFrame,
for (nsIFrame* child = mFrames.FirstChild(); child; child->GetNextSibling(&child)) {
nsCOMPtr<nsIAtom> frameType;
child->GetFrameType(getter_AddRefs(frameType));
if (nsLayoutAtoms::tableCellFrame != frameType.get()) {
if (!IS_TABLE_CELL(frameType.get())) {
nsTableCellFrame* cellFrame = (nsTableCellFrame*)child;
PRInt32 colIndex;
cellFrame->GetColIndex(colIndex);

View File

@ -42,6 +42,7 @@
class nsTableFrame;
class nsTableCellFrame;
struct nsTableCellReflowState;
#ifdef DEBUG_TABLE_REFLOW_TIMING
class nsReflowTimer;
@ -240,6 +241,12 @@ public:
nscoord GetUnpaginatedHeight(nsIPresContext* aPresContext);
void SetUnpaginatedHeight(nsIPresContext* aPresContext, nscoord aValue);
nscoord GetTopBCBorderWidth(float* aPixelsToTwips = nsnull);
void SetTopBCBorderWidth(nscoord aWidth);
nscoord GetBottomBCBorderWidth(float* aPixelsToTwips = nsnull);
void SetBottomBCBorderWidth(nscoord aWidth);
nsMargin* GetBCBorderWidth(float aPixelsToTwips,
nsMargin& aBorder);
protected:
/** protected constructor.
@ -247,6 +254,12 @@ protected:
*/
nsTableRowFrame();
void InitChildReflowState(nsIPresContext& aPresContext,
const nsSize& aAvailSize,
PRBool aBorderCollapse,
float aPixelsToTwips,
nsTableCellReflowState& aReflowState);
/** implement abstract method on nsHTMLContainerFrame */
virtual PRIntn GetSkipSides() const;
@ -315,6 +328,10 @@ private:
nscoord mMaxCellAscent; // does include cells with rowspan > 1
nscoord mMaxCellDescent; // does *not* include cells with rowspan > 1
// border widths in pixels in the collapsing border model
unsigned mTopBorderWidth:8;
unsigned mBottomBorderWidth:8;
#ifdef DEBUG_TABLE_REFLOW_TIMING
public:
nsReflowTimer* mTimer;
@ -421,4 +438,37 @@ inline void nsTableRowFrame::SetHasUnpaginatedHeight(PRBool aValue)
}
}
inline nscoord nsTableRowFrame::GetTopBCBorderWidth(float* aPixelsToTwips)
{
nscoord width = (aPixelsToTwips) ? NSToCoordRound(*aPixelsToTwips * mTopBorderWidth) : mTopBorderWidth;
return width;
}
inline void nsTableRowFrame::SetTopBCBorderWidth(nscoord aWidth)
{
mTopBorderWidth = aWidth;
}
inline nscoord nsTableRowFrame::GetBottomBCBorderWidth(float* aPixelsToTwips)
{
nscoord width = (aPixelsToTwips) ? NSToCoordRound(*aPixelsToTwips * mBottomBorderWidth) : mBottomBorderWidth;
return width;
}
inline void nsTableRowFrame::SetBottomBCBorderWidth(nscoord aWidth)
{
mBottomBorderWidth = aWidth;
}
inline nsMargin* nsTableRowFrame::GetBCBorderWidth(float aPixelsToTwips,
nsMargin& aBorder)
{
aBorder.left = aBorder.right = 0;
aBorder.top = NSToCoordRound(aPixelsToTwips * mTopBorderWidth);
aBorder.bottom = NSToCoordRound(aPixelsToTwips * mBottomBorderWidth);
return &aBorder;
}
#endif

View File

@ -180,7 +180,7 @@ nsTableRowGroupFrame::InitRepeatedFrame(nsIPresContext* aPresContext,
nsIAtom* frameType;
copyCellFrame->GetFrameType(&frameType);
if (nsLayoutAtoms::tableCellFrame == frameType) {
if (IS_TABLE_CELL(frameType)) {
#ifdef NS_DEBUG
nsIContent* content1;
nsIContent* content2;
@ -360,6 +360,28 @@ nsTableRowGroupFrame::PlaceChild(nsIPresContext* aPresContext,
}
}
void
nsTableRowGroupFrame::InitChildReflowState(nsIPresContext& aPresContext,
PRBool aBorderCollapse,
float aPixelsToTwips,
nsHTMLReflowState& aReflowState)
{
nsMargin collapseBorder;
nsMargin padding(0,0,0,0);
nsMargin* pCollapseBorder = nsnull;
if (aBorderCollapse) {
if (aReflowState.frame) {
nsCOMPtr<nsIAtom> fType;
aReflowState.frame->GetFrameType(getter_AddRefs(fType));
if (nsLayoutAtoms::tableRowFrame == fType.get()) {
nsTableRowFrame* rowFrame = (nsTableRowFrame*)aReflowState.frame;
pCollapseBorder = rowFrame->GetBCBorderWidth(aPixelsToTwips, collapseBorder);
}
}
}
aReflowState.Init(&aPresContext, -1, -1, pCollapseBorder, &padding);
}
// Reflow the frames we've already created. If aDirtyOnly is set then only
// reflow dirty frames. This assumes that all of the dirty frames are contiguous.
NS_METHOD
@ -372,8 +394,10 @@ nsTableRowGroupFrame::ReflowChildren(nsIPresContext* aPresContext,
nsTableRowFrame** aFirstRowReflowed)
{
nsTableFrame* tableFrame = nsnull;
nsresult rv = nsTableFrame::GetTableFrame(this, tableFrame);
if (NS_FAILED(rv) || !tableFrame) return rv;
nsresult rv = nsTableFrame::GetTableFrame(this, tableFrame); if (!tableFrame) ABORT1(rv);
PRBool borderCollapse = tableFrame->IsBorderCollapse();
GET_PIXELS_TO_TWIPS(aPresContext, p2t);
nscoord cellSpacingY = tableFrame->GetCellSpacingY();
@ -439,6 +463,7 @@ nsTableRowGroupFrame::ReflowChildren(nsIPresContext* aPresContext,
}
nsHTMLReflowState kidReflowState(aPresContext, aReflowState.reflowState, kidFrame,
kidAvailSize, reason);
InitChildReflowState(*aPresContext, borderCollapse, p2t, kidReflowState);
// If this isn't the first row frame, then we can't be at the top of
// the page anymore...
@ -555,7 +580,7 @@ HasMoreThanOneCell(nsTableCellMap* aCellMap,
PRInt32 colIndex = 0;
PRInt32 count = 0;
do {
cellData = aCellMap->GetCellAt(aRowIndex, colIndex);
cellData = aCellMap->GetDataAt(aRowIndex, colIndex);
if (cellData && (cellData->GetCellFrame() || cellData->IsRowSpan()))
count++;
if (count > 1)
@ -998,8 +1023,8 @@ nsTableRowGroupFrame::SplitRowGroup(nsIPresContext* aPresContext,
presShell->GetStyleSet(getter_AddRefs(styleSet));
if (!styleSet) {NS_ASSERTION(PR_FALSE, "no style set"); return NS_ERROR_NULL_POINTER;}
float p2t;
aPresContext->GetPixelsToTwips(&p2t);
GET_PIXELS_TO_TWIPS(aPresContext, p2t);
PRBool borderCollapse = ((nsTableFrame*)aTableFrame->GetFirstInFlow())->IsBorderCollapse();
nscoord availWidth = nsTableFrame::RoundToPixel(aReflowState.availableWidth, p2t);
nscoord availHeight = nsTableFrame::RoundToPixel(aReflowState.availableHeight, p2t);
@ -1022,9 +1047,11 @@ nsTableRowGroupFrame::SplitRowGroup(nsIPresContext* aPresContext,
// row or there is at least 5% of the current page available
if (!prevRowFrame || (availHeight - aDesiredSize.height > pageHeight / 20)) {
// Reflow the row in the available space and have it split
nsSize availSize(availWidth, availHeight - bounds.y);
nsHTMLReflowState rowReflowState(aPresContext, aReflowState, rowFrame,
availSize, eReflowReason_Resize);
nsSize availSize(availWidth, availHeight - bounds.y);
nsHTMLReflowState rowReflowState(aPresContext, aReflowState, rowFrame, availSize,
eReflowReason_Resize);
InitChildReflowState(*aPresContext, borderCollapse, p2t, rowReflowState);
nsHTMLReflowMetrics desiredSize(nsnull);
rv = ReflowChild(rowFrame, aPresContext, desiredSize, rowReflowState,
@ -1530,6 +1557,10 @@ nsTableRowGroupFrame::IR_TargetIsChild(nsIPresContext* aPresContext,
{
nsresult rv;
nsTableFrame* tableFrame = nsnull;
nsTableFrame::GetTableFrame(this, tableFrame); if (!tableFrame) ABORT1(NS_ERROR_NULL_POINTER);
GET_PIXELS_TO_TWIPS(aPresContext, p2t);
// Recover the state as if aNextFrame is about to be reflowed
RecoverState(aReflowState, aNextFrame);
@ -1540,9 +1571,11 @@ nsTableRowGroupFrame::IR_TargetIsChild(nsIPresContext* aPresContext,
// Reflow the child giving it as much room as it wants. We'll deal with
// splitting later after final determination of rows heights taking into
// account cells with row spans...
nsSize kidAvailSize(aReflowState.availSize.width, NS_UNCONSTRAINEDSIZE);
nsHTMLReflowState kidReflowState(aPresContext, aReflowState.reflowState,
aNextFrame, kidAvailSize);
nsSize kidAvailSize(aReflowState.availSize.width, NS_UNCONSTRAINEDSIZE);
nsHTMLReflowState kidReflowState(aPresContext, aReflowState.reflowState, aNextFrame,
kidAvailSize, aReflowState.reason);
InitChildReflowState(*aPresContext, tableFrame->IsBorderCollapse(), p2t, kidReflowState);
nsSize kidMaxElementSize;
nsHTMLReflowMetrics desiredSize(aDesiredSize.maxElementSize ? &kidMaxElementSize : nsnull,
aDesiredSize.mFlags);
@ -1715,6 +1748,28 @@ nsTableRowGroupFrame::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) cons
}
#endif
nsMargin*
nsTableRowGroupFrame::GetBCBorderWidth(float aPixelsToTwips,
nsMargin& aBorder)
{
aBorder.left = aBorder.right = 0;
nsTableRowFrame* firstRowFrame = nsnull;
nsTableRowFrame* lastRowFrame = nsnull;
for (nsTableRowFrame* rowFrame = GetFirstRow(); rowFrame; rowFrame = rowFrame->GetNextRow()) {
if(!firstRowFrame) {
firstRowFrame = rowFrame;
}
lastRowFrame = rowFrame;
}
if (firstRowFrame) {
aBorder.top = firstRowFrame->GetTopBCBorderWidth(&aPixelsToTwips);
aBorder.bottom = lastRowFrame->GetBottomBCBorderWidth(&aPixelsToTwips);
}
return &aBorder;
}
//nsILineIterator methods for nsTableFrame
NS_IMETHODIMP
nsTableRowGroupFrame::GetNumLines(PRInt32* aResult)
@ -1757,7 +1812,7 @@ nsTableRowGroupFrame::GetLine(PRInt32 aLineNumber,
*aLineFlags = 0;/// should we fill these in later?
// not gonna touch aLineBounds right now
CellData* firstCellData = cellMap->GetCellAt(aLineNumber, 0);
CellData* firstCellData = cellMap->GetDataAt(aLineNumber, 0);
if(!firstCellData)
return NS_ERROR_FAILURE;
@ -1767,7 +1822,7 @@ nsTableRowGroupFrame::GetLine(PRInt32 aLineNumber,
while((aLineNumber > 0)&&(!(*aFirstFrameOnLine)))
{
aLineNumber--;
firstCellData = cellMap->GetCellAt(aLineNumber, 0);
firstCellData = cellMap->GetDataAt(aLineNumber, 0);
*aFirstFrameOnLine = (nsIFrame*)firstCellData->GetCellFrame();
}
}
@ -1847,7 +1902,7 @@ nsTableRowGroupFrame::FindFrameAt(PRInt32 aLineNumber,
PRBool gotParentRect = PR_FALSE;
for(int i =0;i < cellCount; i++)
{
cellData = cellMap->GetCellAt(aLineNumber, i);
cellData = cellMap->GetDataAt(aLineNumber, i);
tempFrame = (nsIFrame*)cellData->GetCellFrame();
if(!tempFrame)
@ -1919,11 +1974,11 @@ nsTableRowGroupFrame::GetNextSiblingOnLine(nsIFrame*& aFrame,
PRInt32& colIndexRef = colIndex;
cellFrame->GetColIndex(colIndexRef);
CellData* cellData = cellMap->GetCellAt(aLineNumber, colIndex + 1);
CellData* cellData = cellMap->GetDataAt(aLineNumber, colIndex + 1);
if(!cellData)// if this isnt a valid cell, drop down and check the next line
{
cellData = cellMap->GetCellAt(aLineNumber + 1, 0);
cellData = cellMap->GetDataAt(aLineNumber + 1, 0);
if(!cellData)
{
//*aFrame = nsnull;
@ -1940,14 +1995,14 @@ nsTableRowGroupFrame::GetNextSiblingOnLine(nsIFrame*& aFrame,
while((tempCol > 0) && (!aFrame))
{
tempCol--;
cellData = cellMap->GetCellAt(aLineNumber, tempCol);
cellData = cellMap->GetDataAt(aLineNumber, tempCol);
aFrame = (nsIFrame*)cellData->GetCellFrame();
if(!aFrame && (tempCol==0))
{
while((tempRow > 0) && (!aFrame))
{
tempRow--;
cellData = cellMap->GetCellAt(tempRow, 0);
cellData = cellMap->GetDataAt(tempRow, 0);
aFrame = (nsIFrame*)cellData->GetCellFrame();
}
}

View File

@ -216,6 +216,8 @@ public:
nscoord GetHeightOfRows(nsIPresContext* aPresContext);
nscoord GetHeightBasis(const nsHTMLReflowState& aReflowState);
nsMargin* GetBCBorderWidth(float aPixelsToTwips,
nsMargin& aBorder);
// nsILineIterator methods
public:
NS_IMETHOD GetNumLines(PRInt32* aResult);
@ -251,6 +253,11 @@ public:
protected:
nsTableRowGroupFrame();
void InitChildReflowState(nsIPresContext& aPresContext,
PRBool aBorderCollapse,
float aPixelsToTwips,
nsHTMLReflowState& aReflowState);
/** implement abstract method on nsHTMLContainerFrame */
virtual PRIntn GetSkipSides() const;

View File

@ -168,6 +168,10 @@ table[align="right"] {
text-align: start;
}
table[rules] {
border-collapse: collapse;
}
*|*:table-outer {
display: table;
margin: 0;
@ -219,6 +223,11 @@ tr {
col, *|*:table-column {
display: table-column;
border: inherit;
width: inherit;
height: inherit;
background: inherit;
border: inherit;
}
colgroup, *|*:table-column-group {

View File

@ -103,7 +103,7 @@ CSS_PROP(border-bottom-color, border_bottom_color, VISUAL)
CSS_PROP(-moz-border-bottom-colors, border_bottom_colors, VISUAL)
CSS_PROP(border-bottom-style, border_bottom_style, REFLOW) // on/off will need reflow
CSS_PROP(border-bottom-width, border_bottom_width, REFLOW)
CSS_PROP(border-collapse, border_collapse, REFLOW)
CSS_PROP(border-collapse, border_collapse, FRAMECHANGE)
CSS_PROP(border-color, border_color, VISUAL)
CSS_PROP(border-left, border_left, REFLOW)
CSS_PROP(border-left-color, border_left_color, VISUAL)

View File

@ -475,6 +475,254 @@ TableTHRule::MapRuleInfoInto(nsRuleData* aRuleData)
return NS_OK;
}
static void
ProcessTableRulesAttribute(nsStyleStruct* aStyleStruct,
nsRuleData* aRuleData,
PRUint8 aSide,
PRBool aGroup,
PRUint8 aRulesArg1,
PRUint8 aRulesArg2,
PRUint8 aRulesArg3)
{
if (!aStyleStruct || !aRuleData || !aRuleData->mPresContext) return;
nsCOMPtr<nsIStyleContext> tableContext = getter_AddRefs(aRuleData->mStyleContext->GetParent()); if (!tableContext) return;
if (!aGroup) {
tableContext = getter_AddRefs(tableContext->GetParent()); if (!tableContext) return;
}
const nsStyleTable* tableData =
(const nsStyleTable*)tableContext->GetStyleData(eStyleStruct_Table);
if (tableData && ((aRulesArg1 == tableData->mRules) ||
(aRulesArg2 == tableData->mRules) ||
(aRulesArg3 == tableData->mRules))) {
const nsStyleBorder* tableBorderData =
(const nsStyleBorder*)tableContext->GetStyleData(eStyleStruct_Border); if (!tableBorderData) return;
PRUint8 tableBorderStyle = tableBorderData->GetBorderStyle(aSide);
nsStyleBorder* borderData = (nsStyleBorder*)aStyleStruct; if (!borderData) return;
PRUint8 borderStyle = borderData->GetBorderStyle(aSide);
// XXX It appears that the style system erronously applies the custom style rule after css style,
// consequently it does not properly fit into the casade. For now, assume that a border style of none
// implies that the style has not been set.
if (NS_STYLE_BORDER_STYLE_NONE == borderStyle) {
// use the table's border style if it is dashed or dotted, otherwise use solid
PRUint8 bStyle = ((NS_STYLE_BORDER_STYLE_NONE != tableBorderStyle) &&
(NS_STYLE_BORDER_STYLE_HIDDEN != tableBorderStyle))
? tableBorderStyle : NS_STYLE_BORDER_STYLE_SOLID;
if ((NS_STYLE_BORDER_STYLE_DASHED != bStyle) &&
(NS_STYLE_BORDER_STYLE_DOTTED != bStyle) &&
(NS_STYLE_BORDER_STYLE_SOLID != bStyle)) {
bStyle = NS_STYLE_BORDER_STYLE_SOLID;
}
bStyle |= NS_STYLE_BORDER_STYLE_RULES_MASK;
borderData->SetBorderStyle(aSide, bStyle);
nscolor borderColor;
PRBool transparent, foreground;
borderData->GetBorderColor(aSide, borderColor, transparent, foreground);
if (transparent || foreground) {
// use the table's border color if it is set, otherwise use black
nscolor tableBorderColor;
tableBorderData->GetBorderColor(aSide, tableBorderColor, transparent, foreground);
borderColor = (transparent || foreground) ? NS_RGB(0,0,0) : tableBorderColor;
borderData->SetBorderColor(aSide, borderColor);
}
// set the border width to be 1 pixel
float p2t;
aRuleData->mPresContext->GetScaledPixelsToTwips(&p2t);
nscoord onePixel = NSToCoordRound(p2t);
nsStyleCoord coord(onePixel);
switch(aSide) {
case NS_SIDE_TOP:
borderData->mBorder.SetTop(coord);
break;
case NS_SIDE_RIGHT:
borderData->mBorder.SetRight(coord);
break;
case NS_SIDE_BOTTOM:
borderData->mBorder.SetBottom(coord);
break;
default: // NS_SIDE_LEFT
borderData->mBorder.SetLeft(coord);
break;
}
}
}
}
// -----------------------------------------------------------
// this rule handles borders on a <thead>, <tbody>, <tfoot> when rules is set on its <table>
// -----------------------------------------------------------
class TableTbodyRule: public GenericTableRule {
public:
TableTbodyRule(nsIHTMLStyleSheet* aSheet);
virtual ~TableTbodyRule();
void Reset()
{
GenericTableRule::Reset();
}
NS_IMETHOD MapRuleInfoInto(nsRuleData* aRuleData);
};
TableTbodyRule::TableTbodyRule(nsIHTMLStyleSheet* aSheet)
: GenericTableRule(aSheet)
{
}
TableTbodyRule::~TableTbodyRule()
{
}
static void TbodyPostResolveCallback(nsStyleStruct* aStyleStruct, nsRuleData* aRuleData)
{
::ProcessTableRulesAttribute(aStyleStruct, aRuleData, NS_SIDE_TOP, PR_TRUE, NS_STYLE_TABLE_RULES_ALL,
NS_STYLE_TABLE_RULES_GROUPS, NS_STYLE_TABLE_RULES_ROWS);
::ProcessTableRulesAttribute(aStyleStruct, aRuleData, NS_SIDE_BOTTOM, PR_TRUE, NS_STYLE_TABLE_RULES_ALL,
NS_STYLE_TABLE_RULES_GROUPS, NS_STYLE_TABLE_RULES_ROWS);
}
NS_IMETHODIMP
TableTbodyRule::MapRuleInfoInto(nsRuleData* aRuleData)
{
if (aRuleData && aRuleData->mSID == eStyleStruct_Border) {
aRuleData->mCanStoreInRuleTree = PR_FALSE;
aRuleData->mPostResolveCallback = &TbodyPostResolveCallback;
}
return NS_OK;
}
// -----------------------------------------------------------
// -----------------------------------------------------------
// this rule handles borders on a <row> when rules is set on its <table>
// -----------------------------------------------------------
class TableRowRule: public GenericTableRule {
public:
TableRowRule(nsIHTMLStyleSheet* aSheet);
virtual ~TableRowRule();
void Reset()
{
GenericTableRule::Reset();
}
NS_IMETHOD MapRuleInfoInto(nsRuleData* aRuleData);
};
TableRowRule::TableRowRule(nsIHTMLStyleSheet* aSheet)
: GenericTableRule(aSheet)
{
}
TableRowRule::~TableRowRule()
{
}
static void RowPostResolveCallback(nsStyleStruct* aStyleStruct, nsRuleData* aRuleData)
{
::ProcessTableRulesAttribute(aStyleStruct, aRuleData, NS_SIDE_TOP, PR_FALSE, NS_STYLE_TABLE_RULES_ALL,
NS_STYLE_TABLE_RULES_ROWS, NS_STYLE_TABLE_RULES_ROWS);
::ProcessTableRulesAttribute(aStyleStruct, aRuleData, NS_SIDE_BOTTOM, PR_FALSE, NS_STYLE_TABLE_RULES_ALL,
NS_STYLE_TABLE_RULES_ROWS, NS_STYLE_TABLE_RULES_ROWS);
}
NS_IMETHODIMP
TableRowRule::MapRuleInfoInto(nsRuleData* aRuleData)
{
if (aRuleData && aRuleData->mSID == eStyleStruct_Border) {
aRuleData->mCanStoreInRuleTree = PR_FALSE;
aRuleData->mPostResolveCallback = &RowPostResolveCallback;
}
return NS_OK;
}
// -----------------------------------------------------------
// this rule handles borders on a <colgroup> when rules is set on its <table>
// -----------------------------------------------------------
class TableColgroupRule: public GenericTableRule {
public:
TableColgroupRule(nsIHTMLStyleSheet* aSheet);
virtual ~TableColgroupRule();
void Reset()
{
GenericTableRule::Reset();
}
NS_IMETHOD MapRuleInfoInto(nsRuleData* aRuleData);
};
TableColgroupRule::TableColgroupRule(nsIHTMLStyleSheet* aSheet)
: GenericTableRule(aSheet)
{
}
TableColgroupRule::~TableColgroupRule()
{
}
static void ColgroupPostResolveCallback(nsStyleStruct* aStyleStruct, nsRuleData* aRuleData)
{
::ProcessTableRulesAttribute(aStyleStruct, aRuleData, NS_SIDE_LEFT, PR_TRUE, NS_STYLE_TABLE_RULES_ALL,
NS_STYLE_TABLE_RULES_GROUPS, NS_STYLE_TABLE_RULES_COLS);
::ProcessTableRulesAttribute(aStyleStruct, aRuleData, NS_SIDE_RIGHT, PR_TRUE, NS_STYLE_TABLE_RULES_ALL,
NS_STYLE_TABLE_RULES_GROUPS, NS_STYLE_TABLE_RULES_COLS);
}
NS_IMETHODIMP
TableColgroupRule::MapRuleInfoInto(nsRuleData* aRuleData)
{
if (aRuleData && aRuleData->mSID == eStyleStruct_Border) {
aRuleData->mCanStoreInRuleTree = PR_FALSE;
aRuleData->mPostResolveCallback = &ColgroupPostResolveCallback;
}
return NS_OK;
}
// -----------------------------------------------------------
// this rule handles borders on a <col> when rules is set on its <table>
// -----------------------------------------------------------
class TableColRule: public GenericTableRule {
public:
TableColRule(nsIHTMLStyleSheet* aSheet);
virtual ~TableColRule();
void Reset()
{
GenericTableRule::Reset();
}
NS_IMETHOD MapRuleInfoInto(nsRuleData* aRuleData);
};
TableColRule::TableColRule(nsIHTMLStyleSheet* aSheet)
: GenericTableRule(aSheet)
{
}
TableColRule::~TableColRule()
{
}
static void ColPostResolveCallback(nsStyleStruct* aStyleStruct, nsRuleData* aRuleData)
{
::ProcessTableRulesAttribute(aStyleStruct, aRuleData, NS_SIDE_LEFT, PR_FALSE, NS_STYLE_TABLE_RULES_ALL,
NS_STYLE_TABLE_RULES_COLS, NS_STYLE_TABLE_RULES_COLS);
::ProcessTableRulesAttribute(aStyleStruct, aRuleData, NS_SIDE_RIGHT, PR_FALSE, NS_STYLE_TABLE_RULES_ALL,
NS_STYLE_TABLE_RULES_COLS, NS_STYLE_TABLE_RULES_COLS);
}
NS_IMETHODIMP
TableColRule::MapRuleInfoInto(nsRuleData* aRuleData)
{
if (aRuleData && aRuleData->mSID == eStyleStruct_Border) {
aRuleData->mCanStoreInRuleTree = PR_FALSE;
aRuleData->mPostResolveCallback = &ColPostResolveCallback;
}
return NS_OK;
}
// -----------------------------------------------------------
class AttributeKey: public nsHashKey
@ -653,6 +901,10 @@ protected:
HTMLColorRule* mVisitedRule;
HTMLColorRule* mActiveRule;
HTMLDocumentColorRule* mDocumentColorRule;
TableTbodyRule* mTableTbodyRule;
TableRowRule* mTableRowRule;
TableColgroupRule* mTableColgroupRule;
TableColRule* mTableColRule;
TableTHRule* mTableTHRule;
// NOTE: if adding more rules, be sure to update
// the SizeOf method to include them
@ -710,6 +962,26 @@ HTMLStyleSheetImpl::HTMLStyleSheetImpl(void)
nsresult
HTMLStyleSheetImpl::Init()
{
mTableTbodyRule = new TableTbodyRule(this);
if (!mTableTbodyRule)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(mTableTbodyRule);
mTableRowRule = new TableRowRule(this);
if (!mTableRowRule)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(mTableRowRule);
mTableColgroupRule = new TableColgroupRule(this);
if (!mTableColgroupRule)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(mTableColgroupRule);
mTableColRule = new TableColRule(this);
if (!mTableColRule)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(mTableColRule);
mTableTHRule = new TableTHRule(this);
if (!mTableTHRule)
return NS_ERROR_OUT_OF_MEMORY;
@ -750,6 +1022,22 @@ HTMLStyleSheetImpl::~HTMLStyleSheetImpl()
mDocumentColorRule->mSheet = nsnull;
NS_RELEASE(mDocumentColorRule);
}
if (nsnull != mTableTbodyRule) {
mTableTbodyRule->mSheet = nsnull;
NS_RELEASE(mTableTbodyRule);
}
if (nsnull != mTableRowRule) {
mTableRowRule->mSheet = nsnull;
NS_RELEASE(mTableRowRule);
}
if (nsnull != mTableColgroupRule) {
mTableColgroupRule->mSheet = nsnull;
NS_RELEASE(mTableColgroupRule);
}
if (nsnull != mTableColRule) {
mTableColRule->mSheet = nsnull;
NS_RELEASE(mTableColRule);
}
if (nsnull != mTableTHRule) {
mTableTHRule->mSheet = nsnull;
NS_RELEASE(mTableTHRule);
@ -848,6 +1136,18 @@ HTMLStyleSheetImpl::RulesMatching(ElementRuleProcessorData* aData,
else if (tag == nsHTMLAtoms::th) {
ruleWalker->Forward(mTableTHRule);
}
else if (tag == nsHTMLAtoms::tr) {
ruleWalker->Forward(mTableRowRule);
}
else if ((tag == nsHTMLAtoms::thead) || (tag == nsHTMLAtoms::tbody) || (tag == nsHTMLAtoms::tfoot)) {
ruleWalker->Forward(mTableTbodyRule);
}
else if (tag == nsHTMLAtoms::col) {
ruleWalker->Forward(mTableColRule);
}
else if (tag == nsHTMLAtoms::colgroup) {
ruleWalker->Forward(mTableColgroupRule);
}
else if (tag == nsHTMLAtoms::table) {
if (aData->mIsQuirkMode)
ruleWalker->Forward(mDocumentColorRule);
@ -888,7 +1188,13 @@ NS_IMETHODIMP
HTMLStyleSheetImpl::RulesMatching(PseudoRuleProcessorData* aData,
nsIAtom* aMedium)
{
// no pseudo frame style
nsIAtom* pseudoTag = aData->mPseudoTag;
if (pseudoTag == nsHTMLAtoms::tableColPseudo) {
nsRuleWalker *ruleWalker = aData->mRuleWalker;
if (ruleWalker) {
ruleWalker->Forward(mTableColRule);
}
}
return NS_OK;
}
@ -1008,6 +1314,11 @@ HTMLStyleSheetImpl::Reset(nsIURI* aURL)
NS_RELEASE(mActiveRule);
}
mDocumentColorRule->Reset();
mTableTbodyRule->Reset();
mTableRowRule->Reset();
mTableColgroupRule->Reset();
mTableColRule->Reset();
mTableTHRule->Reset();
mMappedAttrTable.Enumerate(MappedDropSheet);
@ -1264,6 +1575,10 @@ MappedSizeAttributes(nsHashKey *aKey, void *aData, void* closure)
* - mVisitedRule
* - mActiveRule
* - mDocumentColorRule
* - mTableTbodyRule
* - mTableRowRule
* - mTableColgroupRule
* - mTableColRule
* - mTableTHRule
* - mMappedAttrTable
* 2) Delegates (really) to the MappedAttributes in the mMappedAttrTable
@ -1298,6 +1613,10 @@ HTMLStyleSheetImpl::SizeOf(nsISizeOfHandler *aSizeOfHandler, PRUint32 &aSize)
// - mVisitedRule : sizeof object
// - mActiveRule : sizeof object
// - mDocumentColorRule : sizeof object
// - mTableTbodyRule : sizeof object
// - mTableRowRule : sizeof object
// - mTableColgroupRule : sizeof object
// - mTableColRule : sizeof object
// - mTableTHRule : sizeof object
// - mMappedAttrTable
@ -1321,6 +1640,26 @@ HTMLStyleSheetImpl::SizeOf(nsISizeOfHandler *aSizeOfHandler, PRUint32 &aSize)
tag = getter_AddRefs(NS_NewAtom("DocumentColorRule"));
aSizeOfHandler->AddSize(tag,localSize);
}
if(uniqueItems->AddItem((void*)mTableTbodyRule)){
localSize = sizeof(*mTableTbodyRule);
tag = getter_AddRefs(NS_NewAtom("TableTbodyRule"));
aSizeOfHandler->AddSize(tag,localSize);
}
if(uniqueItems->AddItem((void*)mTableRowRule)){
localSize = sizeof(*mTableRowRule);
tag = getter_AddRefs(NS_NewAtom("TableRowRule"));
aSizeOfHandler->AddSize(tag,localSize);
}
if(uniqueItems->AddItem((void*)mTableColgroupRule)){
localSize = sizeof(*mTableColgroupRule);
tag = getter_AddRefs(NS_NewAtom("TableColgroupRule"));
aSizeOfHandler->AddSize(tag,localSize);
}
if(uniqueItems->AddItem((void*)mTableColRule)){
localSize = sizeof(*mTableColRule);
tag = getter_AddRefs(NS_NewAtom("TableColRule"));
aSizeOfHandler->AddSize(tag,localSize);
}
if(uniqueItems->AddItem((void*)mTableTHRule)){
localSize = sizeof(*mTableTHRule);
tag = getter_AddRefs(NS_NewAtom("TableTHRule"));

View File

@ -605,6 +605,28 @@ nsStyleBorder::CalcBorderFor(const nsIFrame* aFrame, nsMargin& aBorder) const
}
}
void
nsStyleBorder::CalcBorderFor(const nsIFrame* aFrame, PRUint8 aSide, nscoord& aWidth) const
{
aWidth = 0;
// using mCachedBorder as above, doesn't work properly
nsStyleCoord coord;
switch(aSide) {
case NS_SIDE_TOP:
coord = mBorder.GetTop(coord);
break;
case NS_SIDE_RIGHT:
coord = mBorder.GetRight(coord);
break;
case NS_SIDE_BOTTOM:
coord = mBorder.GetBottom(coord);
break;
default: // NS_SIDE_LEFT
coord = mBorder.GetLeft(coord);
}
aWidth = CalcSideFor(aFrame, coord, NS_SPACING_BORDER, aSide, mBorderWidths, 3);
}
nsStyleOutline::nsStyleOutline(nsIPresContext* aPresContext)
{
// XXX support mBorderWidths until deprecated methods are removed
@ -862,7 +884,7 @@ nsStyleTable::nsStyleTable()
mLayoutStrategy = NS_STYLE_TABLE_LAYOUT_AUTO;
mCols = NS_STYLE_TABLE_COLS_NONE;
mFrame = NS_STYLE_TABLE_FRAME_NONE;
mRules = NS_STYLE_TABLE_RULES_ALL;
mRules = NS_STYLE_TABLE_RULES_NONE;
mSpan = 1;
}

View File

@ -465,7 +465,8 @@ struct nsStyleBorder: public nsStyleStruct {
// XXX these are deprecated methods
void CalcBorderFor(const nsIFrame* aFrame, nsMargin& aBorder) const;
void CalcBorderFor(const nsIFrame* aFrame, PRUint8 aSide, nscoord& aWidth) const;
protected:
PRPackedBool mHasCachedBorder;
nsMargin mCachedBorder;

View File

@ -139,7 +139,7 @@ PRBool BasicTableLayoutStrategy::Initialize(nsIPresContext* aPresContex
nscoord minWidth, prefWidth;
mTableFrame->CalcMinAndPreferredWidths(aPresContext, aReflowState, PR_FALSE, minWidth, prefWidth);
if (hasPctCol && mTableFrame->IsAutoWidth()) {
prefWidth = CalcPctAdjTableWidth(aReflowState, boxWidth, p2t);
prefWidth = CalcPctAdjTableWidth(*aPresContext, aReflowState, boxWidth, p2t);
}
// calc the desired width, considering if there is a specified width.
// don't use nsTableFrame::CalcDesiredWidth because it is based on table column widths.
@ -195,7 +195,7 @@ ResetPctValues(nsTableFrame* aTableFrame,
// initialize the col percent and cell percent values to 0.
PRInt32 colX;
for (colX = 0; colX < aNumCols; colX++) {
nsTableColFrame* colFrame = aTableFrame->GetColFrame(colX);
nsTableColFrame* colFrame = aTableFrame->GetColFrame(colX); if (!colFrame) ABORT0();
if (colFrame) {
colFrame->SetWidth(PCT, WIDTH_NOT_SET);
colFrame->SetWidth(PCT_ADJ, WIDTH_NOT_SET);
@ -207,6 +207,7 @@ PRBool
BasicTableLayoutStrategy::BalanceColumnWidths(nsIPresContext* aPresContext,
const nsHTMLReflowState& aReflowState)
{
if (!aPresContext) ABORT1(PR_FALSE);
#ifdef DEBUG_TABLE_STRATEGY
printf("BalanceColumnWidths en count=%d \n", gsDebugCount++); mTableFrame->Dump(aPresContext, PR_FALSE, PR_TRUE, PR_FALSE);
#endif
@ -220,8 +221,16 @@ BasicTableLayoutStrategy::BalanceColumnWidths(nsIPresContext* aPresCont
PRInt32 numCols = mTableFrame->GetColCount();
PRBool tableIsAutoWidth = mTableFrame->IsAutoWidth();
nscoord horBorderPadding = aReflowState.mComputedBorderPadding.left +
aReflowState.mComputedBorderPadding.right;
nscoord horOffset;
// get the reduction in available horizontal space due to borders and padding
if (mTableFrame->IsBorderCollapse()) {
nsMargin offset = mTableFrame->GetChildAreaOffset(*aPresContext, &aReflowState);
horOffset = offset.left + offset.right;
}
else {
horOffset = aReflowState.mComputedBorderPadding.left + aReflowState.mComputedBorderPadding.right;
}
// determine if the table is auto/fixed and get the fixed width if available
nscoord maxWidth = mTableFrame->CalcBorderBoxWidth(aPresContext, aReflowState);
@ -238,19 +247,19 @@ BasicTableLayoutStrategy::BalanceColumnWidths(nsIPresContext* aPresCont
// An auto table returns a new table width based on percent cells/cols if they exist
nscoord perAdjTableWidth = 0;
if (mTableFrame->HasPctCol()) {
perAdjTableWidth = AssignPctColumnWidths(aReflowState, maxWidth, tableIsAutoWidth, p2t);
perAdjTableWidth = AssignPctColumnWidths(*aPresContext, aReflowState, maxWidth, tableIsAutoWidth, p2t);
if (perAdjTableWidth > 0) {
// if an auto table has a pct col or cell, set the preferred table width
// here so that CalcPctAdjTableWidth wont't need to be called by the table
mTableFrame->SetPreferredWidth(perAdjTableWidth);
}
perAdjTableWidth = PR_MIN(perAdjTableWidth, maxWidth);
perAdjTableWidth -= horBorderPadding;
perAdjTableWidth -= horOffset;
perAdjTableWidth = PR_MAX(perAdjTableWidth, 0);
}
// reduce the maxWidth by border and padding, since we will be dealing with content width
maxWidth -= horBorderPadding;
maxWidth -= horOffset;
maxWidth = PR_MAX(0, maxWidth);
PRInt32 numNonZeroWidthCols = 0;
@ -258,7 +267,7 @@ BasicTableLayoutStrategy::BalanceColumnWidths(nsIPresContext* aPresCont
nscoord minTableWidth = 0;
PRInt32 colX;
for (colX = 0; colX < numCols; colX++) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); if (!colFrame) ABORT1(PR_FALSE);
if (!colFrame) continue;
nscoord colMinWidth = colFrame->GetMinWidth();
mTableFrame->SetColumnWidth(colX, colMinWidth);
@ -400,7 +409,7 @@ void BasicTableLayoutStrategy::AllocateFully(nscoord& aTotalAllocated,
{
PRInt32 numCols = mTableFrame->GetColCount();
for (PRInt32 colX = 0; colX < numCols; colX++) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); if (!colFrame) ABORT0();
if (!colFrame) continue;
if (!CanAllocate(aWidthType, aAllocTypes[colX], colFrame)) {
continue;
@ -454,7 +463,7 @@ void BasicTableLayoutStrategy::AllocateUnconstrained(PRInt32 aAllocAmount,
}
else {
if (aExclude0Pro) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); if (!colFrame) ABORT0();
if (colFrame->GetConstraint() == e0ProportionConstraint) {
aAllocTypes[colX] = FINISHED;
}
@ -467,7 +476,7 @@ void BasicTableLayoutStrategy::AllocateUnconstrained(PRInt32 aAllocAmount,
PRInt32 numColsAllocated = 0;
PRInt32 totalAllocated = 0;
for (colX = 0; colX < numCols; colX++) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); if (!colFrame) ABORT0();
PRBool skipColumn = aExclude0Pro && (e0ProportionConstraint == colFrame->GetConstraint());
if (FINISHED != aAllocTypes[colX] && !skipColumn ) {
divisor += mTableFrame->GetColumnWidth(colX);
@ -477,7 +486,7 @@ void BasicTableLayoutStrategy::AllocateUnconstrained(PRInt32 aAllocAmount,
for (colX = 0; colX < numCols; colX++) {
if (FINISHED != aAllocTypes[colX]) {
if (aExclude0Pro) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); if (!colFrame) ABORT0();
if (colFrame && (e0ProportionConstraint == colFrame->GetConstraint())) {
continue;
}
@ -533,7 +542,7 @@ BasicTableLayoutStrategy::ComputeNonPctColspanWidths(const nsHTMLReflowState& aR
PRInt32 colX;
for (colX = numCols - 1; colX >= 0; colX--) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); if (!colFrame) ABORT0();
if (!colFrame) continue;
colFrame->SetWidth(MIN_ADJ, WIDTH_NOT_SET);
colFrame->SetWidth(FIX_ADJ, WIDTH_NOT_SET);
@ -698,7 +707,7 @@ BasicTableLayoutStrategy::ComputeNonPctColspanWidths(PRInt32 aWidthInd
PRInt32 spanX;
// accumulate the various divisors to be used later
for (spanX = 0; spanX < aColSpan; spanX++) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(aColIndex + spanX);
nsTableColFrame* colFrame = mTableFrame->GetColFrame(aColIndex + spanX); if (!colFrame) ABORT1(PR_FALSE);
if (!colFrame) continue;
nscoord minWidth = PR_MAX(colFrame->GetMinWidth(), 0);
nscoord pctWidth = PR_MAX(colFrame->GetPctWidth(), 0);
@ -802,7 +811,7 @@ BasicTableLayoutStrategy::ComputeNonPctColspanWidths(PRInt32 aWidthInd
// get the correct numerator in a similar fashion to getting the divisor
for (spanX = 0; spanX < aColSpan; spanX++) {
if (usedWidth >= availWidth) break;
nsTableColFrame* colFrame = mTableFrame->GetColFrame(aColIndex + spanX);
nsTableColFrame* colFrame = mTableFrame->GetColFrame(aColIndex + spanX); if (!colFrame) ABORT1(PR_FALSE);
if (!colFrame) continue;
nscoord minWidth = colFrame->GetMinWidth();
nscoord pctWidth = PR_MAX(colFrame->GetPctWidth(), 0);
@ -974,7 +983,7 @@ BasicTableLayoutStrategy::AssignNonPctColumnWidths(nsIPresContext* aPre
nscoord fixWidth = WIDTH_NOT_SET;
// Get column frame and reset it
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); if (!colFrame) ABORT1(PR_FALSE);
if (!colFrame) continue;
NS_ASSERTION(nsnull != colFrame, "bad col frame");
colFrame->ResetSizingInfo();
@ -1079,7 +1088,7 @@ BasicTableLayoutStrategy::AssignNonPctColumnWidths(nsIPresContext* aPre
}
//set the table col fixed width if present
for (colX = 0; colX < numCols; colX++) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); if (!colFrame) ABORT1(PR_FALSE);
if (!colFrame) continue;
nscoord fixColWidth = colFrame->GetWidth(FIX);
// use the style width of a col only if the col hasn't gotten a fixed width from any cell
@ -1140,7 +1149,7 @@ BasicTableLayoutStrategy::AssignNonPctColumnWidths(nsIPresContext* aPre
// Set the table col width for each col to the content min.
for (colX = 0; colX < numCols; colX++) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); if (!colFrame) ABORT1(PR_FALSE);
nscoord minWidth = colFrame->GetMinWidth();
mTableFrame->SetColumnWidth(colX, minWidth);
}
@ -1159,7 +1168,7 @@ BasicTableLayoutStrategy::ReduceOverSpecifiedPctCols(nscoord aExcess)
{
nscoord numCols = mTableFrame->GetColCount();
for (PRInt32 colX = numCols - 1; (colX >= 0) && (aExcess > 0); colX--) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); if (!colFrame) ABORT0();
if (!colFrame) continue;
nscoord pctWidth = colFrame->GetWidth(PCT);
nscoord reduction = 0;
@ -1198,7 +1207,8 @@ inline nscoord WrapupAssignPctColumnWidths(nsTableFrame* aTableFrame,
#endif
nscoord
BasicTableLayoutStrategy::CalcPctAdjTableWidth(const nsHTMLReflowState& aReflowState,
BasicTableLayoutStrategy::CalcPctAdjTableWidth(nsIPresContext& aPresContext,
const nsHTMLReflowState& aReflowState,
nscoord aAvailWidthIn,
float aPixelToTwips)
{
@ -1219,7 +1229,7 @@ BasicTableLayoutStrategy::CalcPctAdjTableWidth(const nsHTMLReflowState& aReflowS
rawPctValues[colX] = 0.0f;
}
nsMargin borderPadding = mTableFrame->GetBorderPadding(aReflowState);
nsMargin borderPadding = mTableFrame->GetContentAreaOffset(aPresContext, &aReflowState);
nscoord availWidth = aAvailWidthIn;
if (NS_UNCONSTRAINEDSIZE != availWidth) {
// adjust the avail width to exclude table border, padding and cell spacing
@ -1227,7 +1237,7 @@ BasicTableLayoutStrategy::CalcPctAdjTableWidth(const nsHTMLReflowState& aReflowS
}
for (colX = 0; colX < numCols; colX++) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); if (!colFrame) ABORT1(0);
if (!colFrame) continue;
nscoord maxColBasis = -1;
// Scan the cells in the col
@ -1282,7 +1292,7 @@ BasicTableLayoutStrategy::CalcPctAdjTableWidth(const nsHTMLReflowState& aReflowS
nscoord fixDesTotalNoPct = 0; // total of fix or des widths of cols without pct
for (colX = 0; colX < numCols; colX++) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); if (!colFrame) ABORT1(0);
nscoord fixWidth = colFrame->GetFixWidth();
nscoord fixDesWidth = (fixWidth > 0) ? fixWidth : colFrame->GetDesWidth();
fixDesTotal += fixDesWidth;
@ -1329,7 +1339,8 @@ BasicTableLayoutStrategy::CalcPctAdjTableWidth(const nsHTMLReflowState& aReflowS
// Determine percentage col widths for each col frame
nscoord
BasicTableLayoutStrategy::AssignPctColumnWidths(const nsHTMLReflowState& aReflowState,
BasicTableLayoutStrategy::AssignPctColumnWidths(nsIPresContext& aPresContext,
const nsHTMLReflowState& aReflowState,
nscoord aAvailWidth,
PRBool aTableIsAutoWidth,
float aPixelToTwips)
@ -1349,11 +1360,11 @@ BasicTableLayoutStrategy::AssignPctColumnWidths(const nsHTMLReflowState& aReflow
// on percent cells/cols. This probably should only be a NavQuirks thing, since
// a percentage based cell or column on an auto table should force the column to auto
nscoord basis = (aTableIsAutoWidth)
? CalcPctAdjTableWidth(aReflowState, aAvailWidth, aPixelToTwips)
? CalcPctAdjTableWidth(aPresContext, aReflowState, aAvailWidth, aPixelToTwips)
: aAvailWidth;
// adjust the basis to exclude table border, padding and cell spacing
nsMargin borderPadding = mTableFrame->GetBorderPadding(aReflowState);
nsMargin borderPadding = mTableFrame->GetContentAreaOffset(aPresContext, &aReflowState);
basis -= borderPadding.left + borderPadding.right + mCellSpacingTotal;
nscoord colPctTotal = 0;
@ -1361,7 +1372,7 @@ BasicTableLayoutStrategy::AssignPctColumnWidths(const nsHTMLReflowState& aReflow
// Determine the percentage contribution for cols and for cells with colspan = 1
// Iterate backwards, similarly to the reasoning in AssignNonPctColumnWidths
for (colX = numCols - 1; colX >= 0; colX--) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); if (!colFrame) ABORT1(0);
if (!colFrame) continue;
nscoord maxColPctWidth = WIDTH_NOT_SET;
float maxColPct = 0.0f;
@ -1431,7 +1442,7 @@ BasicTableLayoutStrategy::AssignPctColumnWidths(const nsHTMLReflowState& aReflow
}
// determine if the cell spans cols which have a pct value
for (PRInt32 spanX = 0; (spanX < colSpan) && !done; spanX++) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX + spanX);
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX + spanX); if (!colFrame) ABORT1(0);
if (!colFrame) continue;
if (colFrame->GetWidth(PCT) > 0) {
mTableFrame->SetHasCellSpanningPctCol(PR_TRUE);
@ -1511,7 +1522,7 @@ BasicTableLayoutStrategy::AssignPctColumnWidths(const nsHTMLReflowState& aReflow
// accumulate the spanTotal as the max of MIN, DES, FIX, PCT
PRInt32 spanX;
for (spanX = 0; spanX < colSpan; spanX++) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX + spanX);
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX + spanX); if (!colFrame) ABORT1(0);
if (!colFrame) continue;
nscoord colPctWidth = colFrame->GetWidth(PCT);
if (colPctWidth > 0) { // skip pct cols
@ -1546,7 +1557,7 @@ BasicTableLayoutStrategy::AssignPctColumnWidths(const nsHTMLReflowState& aReflow
// record the percent contributions for the spanned cols
PRInt32 usedColumns = colSpan;
for (spanX = colSpan-1; spanX >= 0; spanX--) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX + spanX);
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX + spanX); if (!colFrame) ABORT1(0);
if (!colFrame) continue;
if ((colFrame->GetWidth(PCT) > 0) || (canSkipPctAdj && (colFrame->GetWidth(PCT_ADJ) > 0))) {
// dont use pct cols or if we can skip the pct adj event do not take the PCT_ADJ cols
@ -1621,7 +1632,7 @@ void BasicTableLayoutStrategy::CalculateTotals(PRInt32* aTotalCounts,
PRInt32 colX;
for (colX = 0; colX < numEffCols; colX++) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); if (!colFrame) ABORT0();
if (!colFrame) continue;
nscoord minCol = colFrame->GetMinWidth();
aTotalCounts[MIN_CON]++;
@ -1820,7 +1831,7 @@ void BasicTableLayoutStrategy::AllocateConstrained(PRInt32 aAvailWidth,
PRInt32 colX;
// find out how many constrained cols there are
for (colX = 0; colX < numCols; colX++) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); if (!colFrame) ABORT0();
if (!colFrame) continue;
if (!CanAllocate(aWidthType, aAllocTypes[colX], colFrame)) {
continue;
@ -1837,7 +1848,7 @@ void BasicTableLayoutStrategy::AllocateConstrained(PRInt32 aAvailWidth,
PRInt32 constrColX = 0;
// set the col info entries for each constrained col
for (colX = 0; colX < numCols; colX++) {
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); if (!colFrame) ABORT0();
if (!colFrame) continue;
if (!CanAllocate(aWidthType, aAllocTypes[colX], colFrame)) {
continue;

View File

@ -93,7 +93,8 @@ public:
* @param aPixelToTwips - the number of twips in a pixel.
* @return - the basis for percent calculations
*/
virtual nscoord CalcPctAdjTableWidth(const nsHTMLReflowState& aReflowState,
virtual nscoord CalcPctAdjTableWidth(nsIPresContext& aPresContext,
const nsHTMLReflowState& aReflowState,
nscoord aAvailWidth,
float aPixelToTwips);
void Dump(PRInt32 aIndent);
@ -159,7 +160,8 @@ protected:
* @param aPixelToTwips - the number of twips in a pixel.
* @return - the adjusted basis including table border, padding and cell spacing
*/
nscoord AssignPctColumnWidths(const nsHTMLReflowState& aReflowState,
nscoord AssignPctColumnWidths(nsIPresContext& aPresContext,
const nsHTMLReflowState& aReflowState,
nscoord aBasis,
PRBool aTableIsAutoWidth,
float aPixelToTwips);

View File

@ -38,6 +38,7 @@
#define CellData_h__
#include "nsISupports.h"
#include "nsCoord.h"
class nsTableCellFrame;
@ -51,8 +52,9 @@ public:
~CellData();
void Init(nsTableCellFrame* aCellFrame);
PRBool IsOrig() const;
PRBool IsDead() const;
PRBool IsSpan() const;
PRBool IsRowSpan() const;
@ -84,6 +86,93 @@ protected:
};
};
// Border Collapsing Cell Data
enum BCBorderOwner
{
eTableOwner = 0,
eColGroupOwner = 1,
eAjaColGroupOwner = 2, // col group to the left
eColOwner = 3,
eAjaColOwner = 4, // col to the left
eRowGroupOwner = 5,
eAjaRowGroupOwner = 6, // row group above
eRowOwner = 7,
eAjaRowOwner = 8, // row above
eCellOwner = 9,
eAjaCellOwner = 10, // cell to the top or to the left
};
// These are the max sizes that are stored. If they are exceeded, then the max is stored and
// the actual value is computed when needed.
#define MAX_BORDER_WIDTH 64
#define MAX_CORNER_SUB_WIDTH 128
// BCData stores the top and left border info and the corner connecting the two.
class BCData
{
public:
BCData();
~BCData();
nscoord GetLeftEdge(BCBorderOwner& aOwner,
PRBool& aStart) const;
void SetLeftEdge(BCBorderOwner aOwner,
nscoord aSize,
PRBool aStart);
nscoord GetTopEdge(BCBorderOwner& aOwner,
PRBool& aStart) const;
void SetTopEdge(BCBorderOwner aOwner,
nscoord aSize,
PRBool aStart);
PRUint8 GetCorner(PRUint8& aCornerOwner,
PRPackedBool& aBevel) const;
void SetCorner(PRUint8 aOwner,
PRUint8 aSubSize,
PRBool aBevel);
PRBool IsLeftStart() const;
void SetLeftStart(PRBool aValue);
PRBool IsTopStart() const;
void SetTopStart(PRBool aValue);
protected:
unsigned mLeftOwner: 4; // owner of left border
unsigned mLeftSize: 6; // size in pixels of left border
unsigned mLeftStart: 1; // set if this is the start of a vertical border segment
unsigned mCornerSide: 2; // side of the owner of the upper left corner relative to the corner
unsigned mCornerSubSize: 7; // size of the largest border not in the dominate plane (for example, if
// corner is owned by the segment to its top or bottom, then the size is the
// max of the border sizes of the segments to its left or right.
unsigned mCornerBevel: 1; // is the corner beveled (only two segments, perpendicular, not dashed or dotted).
unsigned mTopOwner: 4; // owner of top border
unsigned mTopSize: 6; // size in pixels of top border
unsigned mTopStart: 1; // set if this is the start of a horizontal border segment
};
// BCCellData entries replace CellData entries in the cell map if the border collapsing model is in
// effect. BCData for a row and col entry contains the left and top borders of cell at that row and
// col and the corner connecting the two. The right borders of the cells in the last col and the bottom
// borders of the last row are stored in separate BCData entries in the cell map.
class BCCellData : public CellData
{
public:
BCCellData(nsTableCellFrame* aOrigCell);
~BCCellData();
BCData mData;
};
#define SPAN 0x00000001 // there a row or col span
#define ROW_SPAN 0x00000002 // there is a row span
#define ROW_SPAN_0 0x00000004 // the row span is 0
@ -103,9 +192,19 @@ inline nsTableCellFrame* CellData::GetCellFrame() const
return nsnull;
}
inline void CellData::Init(nsTableCellFrame* aCellFrame)
{
mOrigCell = aCellFrame;
}
inline PRBool CellData::IsOrig() const
{
return (SPAN != (SPAN & mBits));
return ((nsnull != mOrigCell) && (SPAN != (SPAN & mBits)));
}
inline PRBool CellData::IsDead() const
{
return (0 == mBits);
}
inline PRBool CellData::IsSpan() const
@ -213,4 +312,88 @@ inline void CellData::SetOverlap(PRBool aOverlap)
}
}
inline BCData::BCData()
{
mLeftOwner = mTopOwner = eCellOwner;
mLeftStart = mTopStart = 1;
mLeftSize = mCornerSide = mCornerSubSize = mTopSize = 0;
}
inline BCData::~BCData()
{
}
inline nscoord BCData::GetLeftEdge(BCBorderOwner& aOwner,
PRBool& aStart) const
{
aOwner = (BCBorderOwner)mLeftOwner;
aStart = (PRBool)mLeftStart;
return (nscoord)mLeftSize;
}
inline void BCData::SetLeftEdge(BCBorderOwner aOwner,
nscoord aSize,
PRBool aStart)
{
mLeftOwner = aOwner;
mLeftSize = (aSize > MAX_BORDER_WIDTH) ? MAX_BORDER_WIDTH : aSize;
mLeftStart = aStart;
}
inline nscoord BCData::GetTopEdge(BCBorderOwner& aOwner,
PRBool& aStart) const
{
aOwner = (BCBorderOwner)mTopOwner;
aStart = (PRBool)mTopStart;
return (nscoord)mTopSize;
}
inline void BCData::SetTopEdge(BCBorderOwner aOwner,
nscoord aSize,
PRBool aStart)
{
mTopOwner = aOwner;
mTopSize = (aSize > MAX_BORDER_WIDTH) ? MAX_BORDER_WIDTH : aSize;
mTopStart = aStart;
}
inline PRUint8 BCData::GetCorner(PRUint8& aOwnerSide,
PRPackedBool& aBevel) const
{
aOwnerSide = mCornerSide;
aBevel = (PRBool)mCornerBevel;
return (PRUint8)mCornerSubSize;
}
inline void BCData::SetCorner(PRUint8 aSubSize,
PRUint8 aOwnerSide,
PRBool aBevel)
{
mCornerSubSize = (aSubSize > MAX_CORNER_SUB_WIDTH) ? MAX_CORNER_SUB_WIDTH : aSubSize;
mCornerSide = aOwnerSide;
mCornerBevel = aBevel;
}
inline PRBool BCData::IsLeftStart() const
{
return (PRBool)mLeftStart;
}
inline void BCData::SetLeftStart(PRBool aValue)
{
mLeftStart = aValue;
}
inline PRBool BCData::IsTopStart() const
{
return (PRBool)mTopStart;
}
inline void BCData::SetTopStart(PRBool aValue)
{
mTopStart = aValue;
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -40,6 +40,8 @@
#include "nscore.h"
#include "celldata.h"
#include "nsVoidArray.h"
#include "nsRect.h"
class nsTableColFrame;
class nsTableCellFrame;
class nsIPresContext;
@ -58,10 +60,27 @@ struct nsColInfo
PRInt32 aNumCellsSpan);
};
enum Corner
{
eTopLeft = 0,
eTopRight = 1,
eBottomRight = 2,
eBottomLeft = 3
};
struct BCInfo
{
nsVoidArray mRightBorders;
nsVoidArray mBottomBorders;
BCData mLowerRightCorner;
};
class nsTableCellMap
{
public:
nsTableCellMap(nsIPresContext* aPresContext, nsTableFrame& aTableFrame);
nsTableCellMap(nsIPresContext* aPresContext,
nsTableFrame& aTableFrame,
PRBool aBorderCollapse);
/** destructor
* NOT VIRTUAL BECAUSE THIS CLASS SHOULD **NEVER** BE SUBCLASSED
@ -69,43 +88,52 @@ public:
~nsTableCellMap();
void RemoveGroupCellMap(nsTableRowGroupFrame* aRowGroup);
void InsertGroupCellMap(nsTableRowGroupFrame& aNewRowGroup,
nsTableRowGroupFrame*& aPrevRowGroup);
nsCellMap* GetMapFor(nsTableRowGroupFrame& aRowGroup);
nsTableCellFrame* GetCellFrame(PRInt32 aRowIndex,
PRInt32 aColIndex,
CellData& aData,
PRBool aUseRowIfOverlap) const;
/** return the CellData for the cell at (aTableRowIndex, aTableColIndex) */
CellData* GetCellAt(PRInt32 aRowIndex,
PRInt32 aColIndex);
CellData* GetDataAt(PRInt32 aRowIndex,
PRInt32 aColIndex,
PRBool aUpdateZeroSpan = PR_TRUE);
nsColInfo* GetColInfoAt(PRInt32 aColIndex);
/** append the cellFrame at the end of the row at aRowIndex and return the col index
*/
PRInt32 AppendCell(nsTableCellFrame& aCellFrame,
PRInt32 aRowIndex,
PRBool aRebuildIfNecessary);
CellData* AppendCell(nsTableCellFrame& aCellFrame,
PRInt32 aRowIndex,
PRBool aRebuildIfNecessary,
nsRect& aDamageArea);
void InsertCells(nsVoidArray& aCellFrames,
PRInt32 aRowIndex,
PRInt32 aColIndexBefore);
PRInt32 aColIndexBefore,
nsRect& aDamageArea);
void RemoveCell(nsTableCellFrame* aCellFrame,
PRInt32 aRowIndex);
PRInt32 aRowIndex,
nsRect& aDamageArea);
void InsertRows(nsIPresContext* aPresContext,
nsTableRowGroupFrame& aRowGroup,
nsVoidArray& aRows,
PRInt32 aFirstRowIndex,
PRBool aConsiderSpans);
PRBool aConsiderSpans,
nsRect& aDamageArea);
void RemoveRows(nsIPresContext* aPresContext,
PRInt32 aFirstRowIndex,
PRInt32 aNumRowsToRemove,
PRBool aConsiderSpans);
PRBool aConsiderSpans,
nsRect& aDamageArea);
PRInt32 GetNumCellsOriginatingInRow(PRInt32 aRowIndex);
PRInt32 GetNumCellsOriginatingInCol(PRInt32 aColIndex) const;
@ -134,6 +162,32 @@ public:
PRBool ColIsSpannedInto(PRInt32 aColIndex);
PRBool ColHasSpanningCells(PRInt32 aColIndex);
BCData* GetBCData(PRUint8 aSide,
nsCellMap& aCellMap,
PRUint32 aYPos,
PRUint32 aXPos,
PRBool aIsLowerRight = PR_FALSE);
void SetBCBorderEdge(PRUint8 aEdge,
nsCellMap& aCellMap,
PRUint32 aCellMapStart,
PRUint32 aYPos,
PRUint32 aXPos,
PRUint32 aLength,
BCBorderOwner aOwner,
nscoord aSize,
PRBool aChanged);
void SetBCBorderCorner(Corner aCorner,
nsCellMap& aCellMap,
PRUint32 aCellMapStart,
PRUint32 aYPos,
PRUint32 aXPos,
PRUint8 aOwner,
nscoord aSubSize,
PRBool aBevel,
PRBool aIsBottomRight = PR_FALSE);
/** dump a representation of the cell map to stdout for debugging */
#ifdef NS_DEBUG
void Dump(char* aString = nsnull) const;
@ -144,13 +198,21 @@ public:
#endif
protected:
BCData* GetRightMostBorder(PRInt32 aRowIndex);
BCData* GetBottomMostBorder(PRInt32 aColIndex);
friend class nsCellMap;
friend class BCMapCellIterator;
friend class BCMapBorderIterator;
void InsertGroupCellMap(nsCellMap* aPrevMap,
nsCellMap& aNewMap);
void DeleteRightBottomBorders();
nsTableFrame& mTableFrame;
nsTableFrame& mTableFrame;
nsAutoVoidArray mCols;
nsCellMap* mFirstMap;
nsCellMap* mFirstMap;
// border collapsing info
BCInfo* mBCInfo;
};
/** nsCellMap is a support class for nsTablePart.
@ -190,40 +252,38 @@ public:
CellData& aData,
PRBool aUseRowSpanIfOverlap) const;
/** return the CellData for the cell at (aTableRowIndex, aTableColIndex) */
CellData* GetCellAt(nsTableCellMap& aMap,
PRInt32 aRowIndex,
PRInt32 aColIndex);
/** append the cellFrame at the end of the row at aRowIndex and return the col index
*/
PRInt32 AppendCell(nsTableCellMap& aMap,
nsTableCellFrame& aCellFrame,
PRInt32 aRowIndex,
PRBool aRebuildIfNecessary);
CellData* AppendCell(nsTableCellMap& aMap,
nsTableCellFrame* aCellFrame,
PRInt32 aRowIndex,
PRBool aRebuildIfNecessary,
nsRect& aDamageArea);
void InsertCells(nsTableCellMap& aMap,
nsVoidArray& aCellFrames,
PRInt32 aRowIndex,
PRInt32 aColIndexBefore);
PRInt32 aColIndexBefore,
nsRect& aDamageArea);
void RemoveCell(nsTableCellMap& aMap,
nsTableCellFrame* aCellFrame,
PRInt32 aRowIndex);
void RemoveCol(PRInt32 aColIndex);
PRInt32 aRowIndex,
nsRect& aDamageArea);
void InsertRows(nsIPresContext* aPresContext,
nsTableCellMap& aMap,
nsVoidArray& aRows,
PRInt32 aFirstRowIndex,
PRBool aConsiderSpans);
PRBool aConsiderSpans,
nsRect& aDamageArea);
void RemoveRows(nsIPresContext* aPresContext,
nsTableCellMap& aMap,
PRInt32 aFirstRowIndex,
PRInt32 aNumRowsToRemove,
PRBool aConsiderSpans);
PRBool aConsiderSpans,
nsRect& aDamageArea);
PRInt32 GetNumCellsOriginatingInRow(PRInt32 aRowIndex) const;
PRInt32 GetNumCellsOriginatingInCol(PRInt32 aColIndex) const;
@ -246,9 +306,20 @@ public:
PRBool ColHasSpanningCells(nsTableCellMap& aMap,
PRInt32 aColIndex);
PRInt32 GetRowSpan(nsTableCellMap& aMap,
PRInt32 aRowIndex,
PRInt32 aColIndex,
PRBool aGetEffective,
PRBool& aIsZeroRowSpan);
PRInt32 GetEffectiveColSpan(nsTableCellMap& aMap,
PRInt32 aRowIndex,
PRInt32 aColIndex,
PRBool& aIsZeroColSpan);
/** dump a representation of the cell map to stdout for debugging */
#ifdef NS_DEBUG
void Dump() const;
void Dump(PRBool aIsBorderCollapse) const;
#endif
#ifdef DEBUG
@ -257,6 +328,9 @@ public:
protected:
friend class nsTableCellMap;
friend class BCMapCellIterator;
friend class BCMapBorderIterator;
friend class nsTableFrame;
PRBool Grow(nsTableCellMap& aMap,
PRInt32 aNumRows,
@ -266,51 +340,57 @@ protected:
PRInt32 aNumCols);
/** assign aCellData to the cell at (aRow,aColumn) */
void SetMapCellAt(nsTableCellMap& aMap,
CellData& aCellData,
PRInt32 aMapRowIndex,
PRInt32 aColIndex,
PRBool aCountZeroSpanAsSpan);
void SetDataAt(nsTableCellMap& aMap,
CellData& aCellData,
PRInt32 aMapRowIndex,
PRInt32 aColIndex,
PRBool aCountZeroSpanAsSpan);
CellData* GetMapCellAt(nsTableCellMap& aMap,
PRInt32 aMapRowIndex,
PRInt32 aColIndex,
PRBool aUpdateZeroSpan);
CellData* GetDataAt(nsTableCellMap& aMap,
PRInt32 aMapRowIndex,
PRInt32 aColIndex,
PRBool aUpdateZeroSpan);
PRInt32 GetNumCellsIn(PRInt32 aColIndex) const;
void ExpandWithRows(nsIPresContext* aPresContext,
nsTableCellMap& aMap,
nsVoidArray& aRowFrames,
PRInt32 aStartRowIndex);
PRInt32 aStartRowIndex,
nsRect& aDamageArea);
void ExpandWithCells(nsTableCellMap& aMap,
nsVoidArray& aCellFrames,
PRInt32 aRowIndex,
PRInt32 aColIndex,
PRInt32 aRowSpan,
PRBool aRowSpanIsZero);
PRBool aRowSpanIsZero,
nsRect& aDamageArea);
void ShrinkWithoutRows(nsTableCellMap& aMap,
PRInt32 aFirstRowIndex,
PRInt32 aNumRowsToRemove);
PRInt32 aNumRowsToRemove,
nsRect& aDamageArea);
void ShrinkWithoutCell(nsTableCellMap& aMap,
nsTableCellFrame& aCellFrame,
PRInt32 aRowIndex,
PRInt32 aColIndex);
PRInt32 aColIndex,
nsRect& aDamageArea);
void RebuildConsideringRows(nsIPresContext* aPresContext,
nsTableCellMap& aMap,
PRInt32 aStartRowIndex,
nsVoidArray* aRowsToInsert,
PRInt32 aNumRowsToRemove = 0);
PRInt32 aNumRowsToRemove,
nsRect& aDamageArea);
void RebuildConsideringCells(nsTableCellMap& aMap,
nsVoidArray* aCellFrames,
PRInt32 aRowIndex,
PRInt32 aColIndex,
PRBool aInsert);
PRBool aInsert,
nsRect& aDamageArea);
PRBool CellsSpanOut(nsIPresContext* aPresContext,
nsVoidArray& aNewRows);
@ -327,21 +407,10 @@ protected:
PRBool CreateEmptyRow(PRInt32 aRowIndex,
PRInt32 aNumCols);
PRInt32 GetRowSpan(nsTableCellMap& aMap,
PRInt32 aRowIndex,
PRInt32 aColIndex,
PRBool aGetEffective,
PRBool& aIsZeroRowSpan);
PRInt32 GetRowSpanForNewCell(nsTableCellFrame& aCellFrameToAdd,
PRInt32 aRowIndex,
PRBool& aIsZeroRowSpan);
PRInt32 GetEffectiveColSpan(nsTableCellMap& aMap,
PRInt32 aRowIndex,
PRInt32 aColIndex,
PRBool& aIsZeroColSpan);
PRInt32 GetColSpanForNewCell(nsTableCellFrame& aCellFrameToAdd,
PRInt32 aColIndex,
PRInt32 aNumColsInTable,

View File

@ -76,7 +76,8 @@ public:
* @param aPixelToTwips - the number of twips in a pixel.
* @return - the basis for percent calculations
*/
virtual nscoord CalcPctAdjTableWidth(const nsHTMLReflowState& aReflowState,
virtual nscoord CalcPctAdjTableWidth(nsIPresContext& aPresContext,
const nsHTMLReflowState& aReflowState,
nscoord aAvailWidth,
float aPixelToTwips)=0;

View File

@ -100,7 +100,7 @@ nsTableCellFrame::GetNextCell() const
while (childFrame) {
nsCOMPtr<nsIAtom> frameType;
childFrame->GetFrameType(getter_AddRefs(frameType));
if (nsLayoutAtoms::tableCellFrame == frameType.get()) {
if (IS_TABLE_CELL(frameType.get())) {
return (nsTableCellFrame*)childFrame;
}
childFrame->GetNextSibling(&childFrame);
@ -439,7 +439,7 @@ nsTableCellFrame::Paint(nsIPresContext* aPresContext,
if ((NS_SUCCEEDED(rv)) && tableFrame) {
const nsStyleTableBorder* tableStyle;
tableFrame->GetStyleData(eStyleStruct_TableBorder, ((const nsStyleStruct *&)tableStyle));
if (NS_STYLE_BORDER_SEPARATE == tableFrame->GetBorderCollapseStyle()) {
if (!tableFrame->IsBorderCollapse()) {
nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this,
aDirtyRect, rect, *myBorder, mStyleContext, skipSides);
}
@ -582,10 +582,9 @@ void nsTableCellFrame::VerticallyAlignChild(nsIPresContext* aPresContex
const nsStyleTextReset* textStyle =
(const nsStyleTextReset*)mStyleContext->GetStyleData(eStyleStruct_TextReset);
/* XXX: remove tableFrame when border-collapse inherits */
nsTableFrame* tableFrame = nsnull;
(void) nsTableFrame::GetTableFrame(this, tableFrame);
GET_PIXELS_TO_TWIPS(aPresContext, p2t);
nsMargin borderPadding;
GetCellBorder (borderPadding, tableFrame);
GetBorderWidth (p2t, borderPadding);
nsMargin padding = nsTableFrame::GetPadding(aReflowState, this);
borderPadding += padding;
@ -822,13 +821,13 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext,
PRBool contentEmptyBeforeReflow = GetContentEmpty();
/* XXX: remove tableFrame when border-collapse inherits */
nsTableFrame* tableFrame=nsnull;
rv = nsTableFrame::GetTableFrame(this, tableFrame);
nsTableFrame* tableFrame = nsnull;
rv = nsTableFrame::GetTableFrame(this, tableFrame); if (!tableFrame) ABORT1(NS_ERROR_NULL_POINTER);
nsTableFrame* tableFrameFirstInFlow = (nsTableFrame*)tableFrame->GetFirstInFlow();
nsMargin borderPadding = aReflowState.mComputedPadding;
nsMargin border;
GetCellBorder(border, tableFrame);
GetBorderWidth(p2t, border);
if ((NS_UNCONSTRAINEDSIZE == availSize.width) || !contentEmptyBeforeReflow) {
borderPadding += border;
}
@ -1130,51 +1129,6 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext,
return NS_OK;
}
/**
*
* Update the border style to map to the HTML border style
*
*/
void nsTableCellFrame::MapHTMLBorderStyle(nsIPresContext* aPresContext,
nsStyleBorder& aBorderStyle,
nsTableFrame* aTableFrame)
{
//adjust the border style based on the table rules attribute
/* The RULES code below has been disabled because collapsing borders have been disabled
and RULES depend on collapsing borders
const nsStyleTable* tableStyle;
aTableFrame->GetStyleData(eStyleStruct_Table, (const nsStyleStruct *&)tableStyle);
switch (tableStyle->mRules)
{
case NS_STYLE_TABLE_RULES_NONE:
aBorderStyle.SetBorderStyle(NS_SIDE_TOP, NS_STYLE_BORDER_STYLE_NONE);
aBorderStyle.SetBorderStyle(NS_SIDE_LEFT, NS_STYLE_BORDER_STYLE_NONE);
aBorderStyle.SetBorderStyle(NS_SIDE_BOTTOM, NS_STYLE_BORDER_STYLE_NONE);
aBorderStyle.SetBorderStyle(NS_SIDE_RIGHT, NS_STYLE_BORDER_STYLE_NONE);
break;
case NS_STYLE_TABLE_RULES_COLS:
aBorderStyle.SetBorderStyle(NS_SIDE_TOP, NS_STYLE_BORDER_STYLE_NONE);
aBorderStyle.SetBorderStyle(NS_SIDE_BOTTOM, NS_STYLE_BORDER_STYLE_NONE);
break;
case NS_STYLE_TABLE_RULES_ROWS:
aBorderStyle.SetBorderStyle(NS_SIDE_LEFT, NS_STYLE_BORDER_STYLE_NONE);
aBorderStyle.SetBorderStyle(NS_SIDE_RIGHT, NS_STYLE_BORDER_STYLE_NONE);
break;
default:
// do nothing for "GROUPS" or "ALL" or for any illegal value
// "GROUPS" will be handled in nsTableFrame::ProcessGroupRules
break;
}
*/
}
PRBool nsTableCellFrame::ConvertToPixelValue(nsHTMLValue& aValue, PRInt32 aDefault, PRInt32& aResult)
{
if (aValue.GetUnit() == eHTMLUnit_Pixel)
@ -1401,13 +1355,16 @@ nsTableCellFrame::GetNextCellInColumn(nsITableCellLayout **aCellLayout)
}
nsresult
NS_NewTableCellFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
NS_NewTableCellFrame(nsIPresShell* aPresShell,
PRBool aIsBorderCollapse,
nsIFrame** aNewFrame)
{
NS_PRECONDITION(aNewFrame, "null OUT ptr");
if (nsnull == aNewFrame) {
return NS_ERROR_NULL_POINTER;
}
nsTableCellFrame* it = new (aPresShell) nsTableCellFrame;
nsTableCellFrame* it = (aIsBorderCollapse) ? new (aPresShell) nsBCTableCellFrame
: new (aPresShell) nsTableCellFrame;
if (nsnull == it) {
return NS_ERROR_OUT_OF_MEMORY;
}
@ -1415,27 +1372,16 @@ NS_NewTableCellFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
return NS_OK;
}
/* ----- methods from CellLayoutData ----- */
void
nsTableCellFrame::GetCellBorder(nsMargin& aBorder,
nsTableFrame* aTableFrame)
nsMargin*
nsTableCellFrame::GetBorderWidth(float aPixelsToTwips,
nsMargin& aBorder) const
{
aBorder.left = aBorder.right = aBorder.top = aBorder.bottom = 0;
if (nsnull==aTableFrame) {
return;
}
if (NS_STYLE_BORDER_SEPARATE == aTableFrame->GetBorderCollapseStyle()) {
const nsStyleBorder* borderData;
GetStyleData(eStyleStruct_Border, (const nsStyleStruct*&)borderData);
borderData->GetBorder(aBorder);
}
else {
NS_ASSERTION(PR_FALSE, "not implemented");
}
const nsStyleBorder* borderData;
GetStyleData(eStyleStruct_Border, (const nsStyleStruct*&)borderData);
borderData->GetBorder(aBorder);
return &aBorder;
}
NS_IMETHODIMP
@ -1502,3 +1448,100 @@ nsTableCellFrame::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const
return NS_OK;
}
#endif
// nsBCTableCellFrame
nsBCTableCellFrame::nsBCTableCellFrame()
:nsTableCellFrame()
{
mTopBorder = mRightBorder = mBottomBorder = mLeftBorder = 0;
}
nsBCTableCellFrame::~nsBCTableCellFrame()
{
}
NS_IMETHODIMP
nsBCTableCellFrame::GetFrameType(nsIAtom** aType) const
{
NS_PRECONDITION(nsnull != aType, "null OUT parameter pointer");
*aType = nsLayoutAtoms::bcTableCellFrame;
NS_ADDREF(*aType);
return NS_OK;
}
#ifdef DEBUG
NS_IMETHODIMP
nsBCTableCellFrame::GetFrameName(nsAString& aResult) const
{
return MakeFrameName(NS_LITERAL_STRING("BCTableCell"), aResult);
}
#endif
void
nsBCTableCellFrame::SetBorderWidth(const nsMargin& aBorder)
{
mTopBorder = aBorder.top;
mRightBorder = aBorder.right;
mBottomBorder = aBorder.bottom;
mLeftBorder = aBorder.left;
}
nsMargin*
nsBCTableCellFrame::GetBorderWidth(float aPixelsToTwips,
nsMargin& aBorder) const
{
aBorder.top = (aPixelsToTwips) ? NSToCoordRound(aPixelsToTwips * mTopBorder) : mTopBorder;
aBorder.right = (aPixelsToTwips) ? NSToCoordRound(aPixelsToTwips * mRightBorder) : mRightBorder;
aBorder.bottom = (aPixelsToTwips) ? NSToCoordRound(aPixelsToTwips * mBottomBorder): mBottomBorder;
aBorder.left = (aPixelsToTwips) ? NSToCoordRound(aPixelsToTwips * mLeftBorder): mLeftBorder;
return &aBorder;
}
nscoord
nsBCTableCellFrame::GetBorderWidth(PRUint8 aSide) const
{
switch(aSide) {
case NS_SIDE_TOP:
return (PRUint8)mTopBorder;
case NS_SIDE_RIGHT:
return (PRUint8)mRightBorder;
case NS_SIDE_BOTTOM:
return (PRUint8)mBottomBorder;
default:
return (PRUint8)mLeftBorder;
}
}
void
nsBCTableCellFrame::SetBorderWidth(PRUint8 aSide,
nscoord aValue)
{
switch(aSide) {
case NS_SIDE_TOP:
mTopBorder = aValue;
break;
case NS_SIDE_RIGHT:
mRightBorder = aValue;
break;
case NS_SIDE_BOTTOM:
mBottomBorder = aValue;
break;
default:
mLeftBorder = aValue;
}
}
#ifdef DEBUG
NS_IMETHODIMP
nsBCTableCellFrame::SizeOf(nsISizeOfHandler* aHandler,
PRUint32* aResult) const
{
if (!aResult) {
return NS_ERROR_NULL_POINTER;
}
PRUint32 sum = sizeof(*this);
*aResult = sum;
return NS_OK;
}
#endif

View File

@ -43,6 +43,7 @@
#include "nsTableRowFrame.h" // need to actually include this here to inline GetRowIndex
#include "nsIStyleContext.h"
#include "nsIPercentHeightObserver.h"
#include "nsLayoutAtoms.h"
class nsTableFrame;
class nsHTMLValue;
@ -266,6 +267,9 @@ public:
nsTableCellFrame* GetNextCell() const;
virtual nsMargin* GetBorderWidth(float aPixelsToTwips,
nsMargin& aBorder) const;
protected:
/** implement abstract method on nsHTMLContainerFrame */
virtual PRIntn GetSkipSides() const;
@ -277,18 +281,11 @@ private:
// All these methods are support methods for RecalcLayoutData
nsIFrame* GetFrameAt(nsVoidArray* aList, PRInt32 aIndex);
//XXX: aTableFrame can be removed as soon as border-collapse inherits correctly
void GetCellBorder(nsMargin &aBorder, nsTableFrame *aTableFrame);
protected:
friend class nsTableRowFrame;
void MapBorderPadding(nsIPresContext* aPresContext);
void MapHTMLBorderStyle(nsIPresContext* aPresContext,
nsStyleBorder& aBorderStyle,
nsTableFrame* aTableFrame);
void MapVAlignAttribute(nsIPresContext* aPresContext, nsTableFrame *aTableFrame);
void MapHAlignAttribute(nsIPresContext* aPresContext, nsTableFrame *aTableFrame);
@ -421,6 +418,41 @@ inline void nsTableCellFrame::SetLastBlockHeight(nscoord aValue)
{
mBits.mLastBlockHeight = aValue;
}
// nsBCTableCellFrame
class nsBCTableCellFrame : public nsTableCellFrame
{
public:
nsBCTableCellFrame();
~nsBCTableCellFrame();
NS_IMETHOD GetFrameType(nsIAtom** aType) const;
virtual nsMargin* GetBorderWidth(float aPixelsToTwips,
nsMargin& aBorder) const;
nscoord GetBorderWidth(PRUint8 aSide) const;
void SetBorderWidth(const nsMargin& aBorder);
void SetBorderWidth(PRUint8 aSide, nscoord aPixelValue);
#ifdef DEBUG
NS_IMETHOD GetFrameName(nsAString& aResult) const;
NS_IMETHOD SizeOf(nsISizeOfHandler* aSizer, PRUint32* aResult) const;
#endif
private:
PRUint32 mTopBorder: 8;
PRUint32 mRightBorder: 8;
PRUint32 mBottomBorder: 8;
PRUint32 mLeftBorder: 8;
};
#define IS_TABLE_CELL(frameType)\
((nsLayoutAtoms::tableCellFrame == frameType) || (nsLayoutAtoms::bcTableCellFrame == frameType))
#endif

View File

@ -113,7 +113,8 @@ nsStyleCoord nsTableColFrame::GetStyleWidth() const
nsStyleCoord styleWidth = position->mWidth;
// the following should not be necessary since html.css defines table-col and
// :table-col to inherit. However, :table-col is not inheriting properly
if (eStyleUnit_Auto == styleWidth.GetUnit()) {
if (eStyleUnit_Auto == styleWidth.GetUnit() ||
eStyleUnit_Inherit == styleWidth.GetUnit()) {
nsIFrame* parent;
GetParent(&parent);
nsCOMPtr<nsIStyleContext> styleContext;
@ -305,6 +306,22 @@ nsTableColFrame::Init(nsIPresContext* aPresContext,
return rv;
}
nsTableColFrame*
nsTableColFrame::GetNextCol() const
{
nsIFrame* childFrame;
GetNextSibling(&childFrame);
while (childFrame) {
nsCOMPtr<nsIAtom> frameType;
childFrame->GetFrameType(getter_AddRefs(frameType));
if (nsLayoutAtoms::tableColFrame == frameType.get()) {
return (nsTableColFrame*)childFrame;
}
childFrame->GetNextSibling(&childFrame);
}
return nsnull;
}
NS_IMETHODIMP
nsTableColFrame::GetFrameType(nsIAtom** aType) const
{

View File

@ -102,6 +102,8 @@ public:
void SetColIndex (PRInt32 aColIndex);
nsTableColFrame* GetNextCol() const;
NS_IMETHOD Init(nsIPresContext* aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
@ -164,6 +166,11 @@ public:
void ResetSizingInfo();
nscoord GetLeftBorderWidth(float* aPixelsToTwips = nsnull);
void SetLeftBorderWidth(nscoord aWidth);
nscoord GetRightBorderWidth(float* aPixelsToTwips = nsnull);
void SetRightBorderWidth(nscoord aWidth);
void Dump(PRInt32 aIndent);
protected:
@ -172,17 +179,46 @@ protected:
~nsTableColFrame();
// the starting index of the column (starting at 0) that this col object represents //
PRInt32 mColIndex;
PRUint32 mColIndex: 16;
PRUint32 mLeftBorderWidth: 8; // stored as pixels
PRUint32 mRightBorderWidth: 8; // stored as pixels
// 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.
nscoord mWidths[NUM_WIDTHS];
};
inline PRInt32 nsTableColFrame::GetColIndex() const
{ return mColIndex; }
{
return mColIndex;
}
inline void nsTableColFrame::SetColIndex (PRInt32 aColIndex)
{ mColIndex = aColIndex; }
{
mColIndex = aColIndex;
}
inline nscoord nsTableColFrame::GetLeftBorderWidth(float* aPixelsToTwips)
{
nscoord width = (aPixelsToTwips) ? NSToCoordRound(*aPixelsToTwips * mLeftBorderWidth) : mLeftBorderWidth;
return width;
}
inline void nsTableColFrame::SetLeftBorderWidth(nscoord aWidth)
{
mLeftBorderWidth = aWidth;
}
inline nscoord nsTableColFrame::GetRightBorderWidth(float* aPixelsToTwips)
{
nscoord width = (aPixelsToTwips) ? NSToCoordRound(*aPixelsToTwips * mRightBorderWidth) : mRightBorderWidth;
return width;
}
inline void nsTableColFrame::SetRightBorderWidth(nscoord aWidth)
{
mRightBorderWidth = aWidth;
}
#endif

View File

@ -250,29 +250,6 @@ nsTableColGroupFrame::SetInitialChildList(nsIPresContext* aPresContext,
return NS_OK;
}
nsIFrame* kidFrame = aChildList;
while (kidFrame) {
nsIAtom* kidType;
kidFrame->GetFrameType(&kidType);
if (nsLayoutAtoms::tableColFrame == kidType) {
// Set the preliminary values for the column frame
PRInt32 span = ((nsTableColFrame*)kidFrame)->GetSpan();
if (span > 1) {
nsTableColFrame* firstSpannedCol;
tableFrame->CreateAnonymousColFrames(*aPresContext, *this, span - 1, eColAnonymousCol,
PR_FALSE, (nsTableColFrame*)kidFrame, (nsIFrame **)&firstSpannedCol);
nsIFrame* spanner = kidFrame;
kidFrame->GetNextSibling(&kidFrame); // need to do this before we insert the new frames
nsFrameList newChildren(aChildList); // used as a convience to hook up siblings
newChildren.InsertFrames(this, (nsTableColFrame*)spanner, (nsIFrame *)firstSpannedCol);
NS_RELEASE(kidType);
continue;
}
}
NS_IF_RELEASE(kidType);
kidFrame->GetNextSibling(&kidFrame);
}
mFrames.AppendFrames(this, aChildList);
return NS_OK;
}

File diff suppressed because it is too large Load Diff

View File

@ -53,7 +53,6 @@ class nsTableColFrame;
class nsTableRowGroupFrame;
class nsTableRowFrame;
class nsTableColGroupFrame;
class nsTableBorderCollapser;
class nsITableLayoutStrategy;
class nsHTMLValue;
@ -208,6 +207,8 @@ public:
nsIAtom* aPropertyName,
PRBool aCreateIfNecessary = PR_FALSE);
static float GetTwipsToPixels(nsIPresContext* aPresContext);
static nscoord RoundToPixel(nscoord aValue,
float aPixelToTwips,
nsPixelRound aRound= eAlwaysRoundUp);
@ -249,7 +250,13 @@ public:
nsIAtom* aListName,
nsIFrame* aOldFrame);
nsMargin GetBorderPadding(const nsHTMLReflowState& aReflowState) const;
// Get the offset from the border box to the area where the row groups fit
nsMargin GetChildAreaOffset(nsIPresContext& aPresContext,
const nsHTMLReflowState* aReflowState) const;
// Get the offset from the border box to the area where the content fits
nsMargin GetContentAreaOffset(nsIPresContext& aPresContext,
const nsHTMLReflowState* aReflowState) const;
/** helper method to find the table parent of any table frame object */
// TODO: today, this depends on display types. This should be changed to rely
@ -297,6 +304,17 @@ public:
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags = 0);
nsMargin* GetBCBorder(nsIPresContext& aPresContext,
PRBool aInnerBorderOnly,
nsMargin& aBorder) const;
void SetBCDamageArea(nsIPresContext& aPresContext,
const nsRect& aValue);
void PaintBCBorders(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect);
NS_IMETHOD GetFrameForPoint(nsIPresContext* aPresContext,
const nsPoint& aPoint,
nsFramePaintLayer aWhichLayer,
@ -371,15 +389,12 @@ public:
/** set the width of the column at aColIndex to aWidth */
virtual void SetColumnWidth(PRInt32 aColIndex, nscoord aWidth);
/** helper to get the border collapse style value */
virtual PRUint8 GetBorderCollapseStyle();
/** helper to get the cell spacing X style value */
virtual nscoord GetCellSpacingX();
/** helper to get the cell spacing Y style value */
virtual nscoord GetCellSpacingY();
/** return the row span of a cell, taking into account row span magic at the bottom
* of a table. The row span equals the number of rows spanned by aCell starting at
* aStartRowIndex, and can be smaller if aStartRowIndex is greater than the row
@ -440,9 +455,9 @@ public:
/** empty the column frame cache */
void ClearColCache();
virtual PRInt32 AppendCell(nsIPresContext& aPresContext,
nsTableCellFrame& aCellFrame,
PRInt32 aRowIndex);
virtual void AppendCell(nsIPresContext& aPresContext,
nsTableCellFrame& aCellFrame,
PRInt32 aRowIndex);
virtual void InsertCells(nsIPresContext& aPresContext,
nsVoidArray& aCellFrames,
@ -522,6 +537,9 @@ protected:
/** destructor, responsible for mColumnLayoutData */
virtual ~nsTableFrame();
void InitChildReflowState(nsIPresContext& aPresContext,
nsHTMLReflowState& aReflowState);
/** implement abstract method on nsHTMLContainerFrame */
virtual PRIntn GetSkipSides() const;
@ -619,7 +637,8 @@ protected:
nsIFrame* aKidFrame,
nscoord aDeltaY);
nsresult RecoverState(nsTableReflowState& aReflowState,
nsresult RecoverState(nsIPresContext& aPresContext,
nsTableReflowState& aReflowState,
nsIFrame* aKidFrame);
NS_METHOD CollapseRowGroupIfNecessary(nsIPresContext* aPresContext,
@ -646,10 +665,11 @@ public:
// calculate the computed height of aFrame including its border and padding given
// its reflow state.
nscoord CalcBorderBoxHeight(const nsHTMLReflowState& aReflowState);
nscoord CalcBorderBoxHeight(nsIPresContext* aPresContext,
const nsHTMLReflowState& aReflowState);
// calculate the minimum width to layout aFrame and its desired width
// including border and padding given its reflow state and column width information
void CalcMinAndPreferredWidths(nsIPresContext* aPresContextconst,
void CalcMinAndPreferredWidths(nsIPresContext* aPresContext,
const nsHTMLReflowState& aReflowState,
PRBool aCalcPrefWidthIfAutoWithPctCol,
nscoord& aMinWidth,
@ -657,7 +677,8 @@ public:
protected:
// calcs the width of the table according to the computed widths of each column.
virtual PRInt32 CalcDesiredWidth(const nsHTMLReflowState& aReflowState);
virtual PRInt32 CalcDesiredWidth(nsIPresContext& aPresContext,
const nsHTMLReflowState& aReflowState);
// return the desired height of this table accounting for the current
// reflow state, and for the table attributes and parent
@ -699,7 +720,7 @@ public:
PRUint32& aNumRowGroups,
nsIFrame** aFirstBody = nsnull,
nsTableRowGroupFrame** aHead = nsnull,
nsTableRowGroupFrame** aFoot = nsnull);
nsTableRowGroupFrame** aFoot = nsnull) const;
// Returns PR_TRUE if there are any cells above the row at
// aRowIndex and spanning into the row at aRowIndex
@ -735,9 +756,6 @@ protected:
PRBool DidResizeReflow() const;
void SetResizeReflow(PRBool aValue);
/** Support methods for DidSetStyleContext */
void MapBorderMarginPadding(nsIPresContext* aPresContext);
void MapHTMLBorderStyle(nsStyleBorder& aBorderStyle, nscoord aBorderWidth);
PRBool ConvertToPixelValue(nsHTMLValue& aValue,
PRInt32 aDefault,
PRInt32& aResult);
@ -749,6 +767,11 @@ public:
PRBool NeedStrategyBalance() const;
void SetNeedStrategyBalance(PRBool aValue);
PRBool IsBorderCollapse() const;
PRBool NeedToCalcBCBorders() const;
void SetNeedToCalcBCBorders(PRBool aValue);
/** Get the cell map for this table frame. It is not always mCellMap.
* Only the firstInFlow has a legit cell map
*/
@ -763,9 +786,6 @@ public:
PRInt32 aRowIndex,
PRInt32 anAdjustment);
// Return PR_TRUE if rules=groups is set for the table content
PRBool HasGroupRules() const;
// Remove cell borders which aren't bordering row and/or col groups
void ProcessGroupRules(nsIPresContext* aPresContext);
@ -775,10 +795,16 @@ public:
* Return aFrame's child if aFrame is an nsScrollFrame, otherwise return aFrame
*/
nsTableRowGroupFrame* GetRowGroupFrame(nsIFrame* aFrame,
nsIAtom* aFrameTypeIn = nsnull);
nsIAtom* aFrameTypeIn = nsnull) const;
protected:
void SetBorderCollapse(PRBool aValue);
void CalcBCBorders(nsIPresContext& aPresContext);
void ExpandBCDamageArea(nsRect& aRect) const;
PRBool HadInitialReflow() const;
void SetHadInitialReflow(PRBool aValue);
@ -809,8 +835,8 @@ public: /* ----- Cell Map public methods ----- */
/** returns the number of columns in this table after redundant columns have been removed
*/
virtual PRInt32 GetEffectiveColCount();
virtual PRInt32 GetColCount();
virtual PRInt32 GetEffectiveColCount() const;
virtual PRInt32 GetColCount() const;
/** return the column frame at colIndex.
* returns nsnull if the col frame has not yet been allocated, or if aColIndex is out of range
@ -886,6 +912,7 @@ protected:
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
// true if a descendant was reflowed normally since the last time we reflowed.
// We will likely need a timeout reflow (targeted either at us or below)
unsigned mDescendantReflowedNotTimeout:1;
@ -896,7 +923,8 @@ protected:
unsigned mRowInserted:1;
unsigned mNeedSpecialReflow:1;
unsigned mNeedToInitiateSpecialReflow:1;
unsigned : 20; // unused
unsigned mNeedToCalcBCBorders:1;
unsigned : 18; // unused
} mBits;
nsTableCellMap* mCellMap; // maintains the relationships between rows, cols, and cells
@ -1054,8 +1082,26 @@ inline void nsTableFrame::SetPreferredWidth(nscoord aWidth)
mPreferredWidth = aWidth;
}
inline PRBool nsTableFrame::IsBorderCollapse() const
{
return (PRBool)mBits.mIsBorderCollapse;
}
inline void nsTableFrame::SetBorderCollapse(PRBool aValue)
{
mBits.mIsBorderCollapse = aValue;
}
inline PRBool nsTableFrame::NeedToCalcBCBorders() const
{
return (PRBool)mBits.mNeedToCalcBCBorders;
}
inline void nsTableFrame::SetNeedToCalcBCBorders(PRBool aValue)
{
mBits.mNeedToCalcBCBorders = (unsigned)aValue;
}
enum nsTableIteration {
eTableLTR = 0,
eTableRTL = 1,
@ -1085,6 +1131,23 @@ protected:
PRInt32 mCount;
};
#define ABORT0() \
{NS_ASSERTION(PR_FALSE, "CellIterator program error"); \
return;}
#define ABORT1(aReturn) \
{NS_ASSERTION(PR_FALSE, "CellIterator program error"); \
return aReturn;}
#define GET_PIXELS_TO_TWIPS(presContext,var) \
float var; \
(presContext)->GetScaledPixelsToTwips(&var);
#define GET_TWIPS_TO_PIXELS(presContext,var) \
float var; \
(presContext)->GetScaledPixelsToTwips(&var); \
var = 1.0f / var;
#endif

View File

@ -232,7 +232,14 @@ nsTableOuterFrame::SetInitialChildList(nsIPresContext* aPresContext,
}
else {
mFrames.SetFrames(aChildList);
mInnerTableFrame = aChildList;
mInnerTableFrame = nsnull;
if (aChildList) {
nsCOMPtr<nsIAtom> fType;
aChildList->GetFrameType(getter_AddRefs(fType));
if (nsLayoutAtoms::tableFrame == fType.get()) {
mInnerTableFrame = (nsTableFrame*)aChildList;
}
}
}
return NS_OK;
@ -466,21 +473,46 @@ FixAutoMargins(nscoord aAvailWidth,
}
}
void
nsTableOuterFrame::InitChildReflowState(nsIPresContext& aPresContext,
nsHTMLReflowState& aReflowState)
{
nsMargin collapseBorder;
nsMargin collapsePadding(0,0,0,0);
nsMargin* pCollapseBorder = nsnull;
nsMargin* pCollapsePadding = nsnull;
if ((aReflowState.frame == mInnerTableFrame) && (mInnerTableFrame->IsBorderCollapse())) {
if (mInnerTableFrame->NeedToCalcBCBorders()) {
mInnerTableFrame->CalcBCBorders(aPresContext);
}
pCollapseBorder = mInnerTableFrame->GetBCBorder(aPresContext, PR_FALSE, collapseBorder);
pCollapsePadding = &collapsePadding;
}
aReflowState.Init(&aPresContext, -1, -1, pCollapseBorder, pCollapsePadding);
}
// get the margin and padding data. nsHTMLReflowState doesn't handle the
// case of auto margins
void
GetMarginPadding(nsIPresContext* aPresContext,
const nsHTMLReflowState& aOuterRS,
nsIFrame* aChildFrame,
nsMargin& aMargin,
nsMargin& aMarginNoAuto,
nsMargin& aPadding)
nsTableOuterFrame::GetMarginPadding(nsIPresContext* aPresContext,
const nsHTMLReflowState& aOuterRS,
nsIFrame* aChildFrame,
nsMargin& aMargin,
nsMargin& aMarginNoAuto,
nsMargin& aPadding)
{
if (!aPresContext) ABORT0();
GET_PIXELS_TO_TWIPS(aPresContext, p2t);
// construct a reflow state to compute margin and padding. Auto margins
// will not be computed at this time.
// create an init the child reflow state
nsHTMLReflowState childRS(aPresContext, aOuterRS, aChildFrame,
nsSize(aOuterRS.availableWidth, aOuterRS.availableHeight),
eReflowReason_Resize);
eReflowReason_Resize, PR_FALSE);
InitChildReflowState(*aPresContext, childRS);
nsRect childRect;
aChildFrame->GetRect(childRect);
FixAutoMargins(aOuterRS.availableWidth, childRect.width, childRS);
@ -931,6 +963,7 @@ nsTableOuterFrame::OuterReflowChild(nsIPresContext* aPresContext,
nsReflowReason aReflowReason,
nsReflowStatus& aStatus)
{
if (!aPresContext) ABORT1(NS_ERROR_NULL_POINTER);
aMargin = aPadding = nsMargin(0,0,0,0);
nscoord availWidth = GetChildAvailWidth(aPresContext, aChildFrame, aOuterRS,
@ -946,9 +979,10 @@ nsTableOuterFrame::OuterReflowChild(nsIPresContext* aPresContext,
availHeight = nsTableFrame::RoundToPixel(availHeight, p2t, eAlwaysRoundDown);
}
nsHTMLReflowState childRS(aPresContext, aOuterRS, aChildFrame,
nsSize(availWidth, availHeight));
childRS.reason = aReflowReason;
// create and init the child reflow state
nsHTMLReflowState childRS(aPresContext, aOuterRS, aChildFrame, nsSize(availWidth, availHeight),
aReflowReason);
InitChildReflowState(*aPresContext, childRS);
childRS.mPercentHeightObserver = nsnull; // the observer is for non table related frames inside cells

View File

@ -47,6 +47,7 @@ class nsReflowTimer;
#endif
struct nsStyleTable;
class nsTableFrame;
class nsTableCaptionFrame : public nsBlockFrame
{
@ -201,6 +202,9 @@ protected:
nsTableOuterFrame();
virtual ~nsTableOuterFrame();
void InitChildReflowState(nsIPresContext& aPresContext,
nsHTMLReflowState& aReflowState);
/** Always returns 0, since the outer table frame has no border of its own
* The inner table frame can answer this question in a meaningful way.
* @see nsHTMLContainerFrame::GetSkipSides */
@ -362,11 +366,17 @@ protected:
PRBool aInnerChanged,
PRBool aCaptionChanged);
void GetMarginPadding(nsIPresContext* aPresContext,
const nsHTMLReflowState& aOuterRS,
nsIFrame* aChildFrame,
nsMargin& aMargin,
nsMargin& aMarginNoAuto,
nsMargin& aPadding);
private:
// used to keep track of this frame's children. They are redundant with mFrames, but more convient
nsIFrame* mInnerTableFrame;
nsIFrame* mCaptionFrame;
nsTableFrame* mInnerTableFrame;
nsIFrame* mCaptionFrame;
// used to track caption max element size
PRInt32 mMinCaptionWidth;

View File

@ -68,11 +68,6 @@ struct nsTableCellReflowState : public nsHTMLReflowState
const nsSize& aAvailableSpace,
nsReflowReason aReason);
nsTableCellReflowState(nsIPresContext* aPresContext,
const nsHTMLReflowState& aParentReflowState,
nsIFrame* aFrame,
const nsSize& aAvailableSpace);
void FixUp(const nsSize& aAvailSpace);
};
@ -83,16 +78,43 @@ nsTableCellReflowState::nsTableCellReflowState(nsIPresContext* aPresCon
nsReflowReason aReason)
:nsHTMLReflowState(aPresContext, aParentRS, aFrame, aAvailSpace, aReason)
{
FixUp(aAvailSpace);
}
nsTableCellReflowState::nsTableCellReflowState(nsIPresContext* aPresContext,
const nsHTMLReflowState& aParentRS,
nsIFrame* aFrame,
const nsSize& aAvailSpace)
:nsHTMLReflowState(aPresContext, aParentRS, aFrame, aAvailSpace)
void nsTableCellReflowState::FixUp(const nsSize& aAvailSpace)
{
FixUp(aAvailSpace);
// fix the mComputed values during a pass 2 reflow since the cell can be a percentage base
if (NS_UNCONSTRAINEDSIZE != aAvailSpace.width) {
if (NS_UNCONSTRAINEDSIZE != mComputedWidth) {
mComputedWidth = aAvailSpace.width - mComputedBorderPadding.left - mComputedBorderPadding.right;
mComputedWidth = PR_MAX(0, mComputedWidth);
}
if (NS_UNCONSTRAINEDSIZE != mComputedHeight) {
if (NS_UNCONSTRAINEDSIZE != aAvailSpace.height) {
mComputedHeight = aAvailSpace.height - mComputedBorderPadding.top - mComputedBorderPadding.bottom;
mComputedHeight = PR_MAX(0, mComputedHeight);
}
}
}
}
void
nsTableRowFrame::InitChildReflowState(nsIPresContext& aPresContext,
const nsSize& aAvailSize,
PRBool aBorderCollapse,
float aPixelsToTwips,
nsTableCellReflowState& aReflowState)
{
nsMargin collapseBorder;
nsMargin* pCollapseBorder = nsnull;
if (aBorderCollapse) {
// we only reflow cells, so don't need to check frame type
nsBCTableCellFrame* bcCellFrame = (nsBCTableCellFrame*)aReflowState.frame;
if (bcCellFrame) {
pCollapseBorder = bcCellFrame->GetBorderWidth(aPixelsToTwips, collapseBorder);
}
}
aReflowState.Init(&aPresContext, -1, -1, pCollapseBorder);
aReflowState.FixUp(aAvailSize);
}
void
@ -132,23 +154,6 @@ nsTableRowFrame::SetPctHeight(float aPctValue,
}
}
void nsTableCellReflowState::FixUp(const nsSize& aAvailSpace)
{
// fix the mComputed values during a pass 2 reflow since the cell can be a percentage base
if (NS_UNCONSTRAINEDSIZE != aAvailSpace.width) {
if (NS_UNCONSTRAINEDSIZE != mComputedWidth) {
mComputedWidth = aAvailSpace.width - mComputedBorderPadding.left - mComputedBorderPadding.right;
mComputedWidth = PR_MAX(0, mComputedWidth);
}
if (NS_UNCONSTRAINEDSIZE != mComputedHeight) {
if (NS_UNCONSTRAINEDSIZE != aAvailSpace.height) {
mComputedHeight = aAvailSpace.height - mComputedBorderPadding.top - mComputedBorderPadding.bottom;
mComputedHeight = PR_MAX(0, mComputedHeight);
}
}
}
}
// 'old' is old cached cell's desired size
// 'new' is new cell's size including style constraints
static PRBool
@ -217,7 +222,7 @@ nsTableRowFrame::SetInitialChildList(nsIPresContext* aPresContext,
kidFrame->GetNextSibling(&kidFrame)) {
nsCOMPtr<nsIAtom> frameType;
kidFrame->GetFrameType(getter_AddRefs(frameType));
if (nsLayoutAtoms::tableCellFrame == frameType.get()) {
if (IS_TABLE_CELL(frameType.get())) {
if (((nsTableCellFrame*)kidFrame)->GetRowSpan() > 1) {
mState |= NS_FRAME_OUTSIDE_CHILDREN;
}
@ -241,7 +246,7 @@ nsTableRowFrame::AppendFrames(nsIPresContext* aPresContext,
for (nsIFrame* childFrame = aFrameList; childFrame; childFrame->GetNextSibling(&childFrame)) {
nsCOMPtr<nsIAtom> frameType;
childFrame->GetFrameType(getter_AddRefs(frameType));
if (nsLayoutAtoms::tableCellFrame == frameType.get()) {
if (IS_TABLE_CELL(frameType.get())) {
// Add the cell to the cell map
tableFrame->AppendCell(*aPresContext, (nsTableCellFrame&)*childFrame, GetRowIndex());
// XXX this could be optimized with some effort
@ -272,12 +277,13 @@ nsTableRowFrame::InsertFrames(nsIPresContext* aPresContext,
nsTableFrame::GetTableFrame(this, tableFrame);
// gather the new frames (only those which are cells) into an array
nsTableCellFrame* prevCellFrame = (nsTableCellFrame *)nsTableFrame::GetFrameAtOrBefore(aPresContext, this, aPrevFrame, nsLayoutAtoms::tableCellFrame);
nsIAtom* cellFrameType = (tableFrame->IsBorderCollapse()) ? nsLayoutAtoms::bcTableCellFrame : nsLayoutAtoms::tableCellFrame;
nsTableCellFrame* prevCellFrame = (nsTableCellFrame *)nsTableFrame::GetFrameAtOrBefore(aPresContext, this, aPrevFrame, cellFrameType);
nsVoidArray cellChildren;
for (nsIFrame* childFrame = aFrameList; childFrame; childFrame->GetNextSibling(&childFrame)) {
nsCOMPtr<nsIAtom> frameType;
childFrame->GetFrameType(getter_AddRefs(frameType));
if (nsLayoutAtoms::tableCellFrame == frameType.get()) {
if (IS_TABLE_CELL(frameType.get())) {
cellChildren.AppendElement(childFrame);
// XXX this could be optimized with some effort
tableFrame->SetNeedStrategyInit(PR_TRUE);
@ -315,7 +321,7 @@ nsTableRowFrame::RemoveFrame(nsIPresContext* aPresContext,
if (tableFrame) {
nsCOMPtr<nsIAtom> frameType;
aOldFrame->GetFrameType(getter_AddRefs(frameType));
if (nsLayoutAtoms::tableCellFrame == frameType.get()) {
if (IS_TABLE_CELL(frameType.get())) {
nsTableCellFrame* cellFrame = (nsTableCellFrame*)aOldFrame;
PRInt32 colIndex;
cellFrame->GetColIndex(colIndex);
@ -372,7 +378,7 @@ nsTableRowFrame::GetFirstCell()
while (childFrame) {
nsCOMPtr<nsIAtom> frameType;
childFrame->GetFrameType(getter_AddRefs(frameType));
if (nsLayoutAtoms::tableCellFrame == frameType.get()) {
if (IS_TABLE_CELL(frameType.get())) {
return (nsTableCellFrame*)childFrame;
}
childFrame->GetNextSibling(&childFrame);
@ -398,7 +404,7 @@ nsTableRowFrame::DidResize(nsIPresContext* aPresContext,
while (childFrame) {
nsCOMPtr<nsIAtom> frameType;
childFrame->GetFrameType(getter_AddRefs(frameType));
if (nsLayoutAtoms::tableCellFrame == frameType.get()) {
if (IS_TABLE_CELL(frameType.get())) {
nsTableCellFrame* cellFrame = (nsTableCellFrame*)childFrame;
nscoord cellHeight = mRect.height + GetHeightOfRowsSpannedBelowFirst(*cellFrame, *tableFrame);
@ -534,7 +540,7 @@ nsTableRowFrame::CalcHeight(const nsHTMLReflowState& aReflowState)
for (nsIFrame* kidFrame = mFrames.FirstChild(); kidFrame; kidFrame->GetNextSibling(&kidFrame)) {
nsCOMPtr<nsIAtom> frameType;
kidFrame->GetFrameType(getter_AddRefs(frameType));
if (nsLayoutAtoms::tableCellFrame == frameType.get()) {
if (IS_TABLE_CELL(frameType.get())) {
nscoord availWidth = ((nsTableCellFrame *)kidFrame)->GetPriorAvailWidth();
nsSize desSize = ((nsTableCellFrame *)kidFrame)->GetDesiredSize();
if ((NS_UNCONSTRAINEDSIZE == aReflowState.availableHeight) && !mPrevInFlow) {
@ -888,28 +894,29 @@ nsTableRowFrame::ReflowChildren(nsIPresContext* aPresContext,
aStatus = NS_FRAME_COMPLETE;
if (!mFrames.FirstChild()) return NS_OK;
nsTableFrame* tableFrame = &aTableFrame;
if (!tableFrame) return NS_ERROR_NULL_POINTER;
GET_PIXELS_TO_TWIPS(aPresContext, p2t);
PRBool borderCollapse = (((nsTableFrame*)aTableFrame.GetFirstInFlow())->IsBorderCollapse());
nsIFrame* tablePrevInFlow;
tableFrame->GetPrevInFlow(&tablePrevInFlow);
aTableFrame.GetPrevInFlow(&tablePrevInFlow);
PRBool isPaginated;
aPresContext->IsPaginated(&isPaginated);
nsresult rv = NS_OK;
nscoord cellSpacingX = tableFrame->GetCellSpacingX();
nscoord cellSpacingX = aTableFrame.GetCellSpacingX();
PRInt32 cellColSpan = 1; // must be defined here so it's set properly for non-cell kids
nsTableIteration dir = (aReflowState.availableWidth == NS_UNCONSTRAINEDSIZE)
? eTableLTR : eTableDIR;
nsTableIterator iter(aPresContext, *this, dir);
// remember the col index of the previous cell to handle rowspans into this row
PRInt32 firstPrevColIndex = (iter.IsLeftToRight()) ? -1 : tableFrame->GetColCount();
PRInt32 firstPrevColIndex = (iter.IsLeftToRight()) ? -1 : aTableFrame.GetColCount();
PRInt32 prevColIndex = firstPrevColIndex;
nscoord x = 0; // running total of children x offset
nsTableFrame* tableFirstInFlow = (nsTableFrame*)tableFrame->GetFirstInFlow();
PRBool isAutoLayout = tableFrame->IsAutoLayout();
nsTableFrame* tableFirstInFlow = (nsTableFrame*)aTableFrame.GetFirstInFlow();
PRBool isAutoLayout = aTableFrame.IsAutoLayout();
PRBool needToNotifyTable = PR_TRUE;
nscoord paginatedHeight = 0;
// If the incremental reflow command is a StyleChanged reflow and
@ -945,7 +952,7 @@ nsTableRowFrame::ReflowChildren(nsIPresContext* aPresContext,
doReflowChild = PR_FALSE;
}
if (aReflowState.mFlags.mSpecialHeightReflow) {
if (!isPaginated && (nsLayoutAtoms::tableCellFrame == frameType.get() &&
if (!isPaginated && (IS_TABLE_CELL(frameType.get()) &&
!((nsTableCellFrame*)kidFrame)->NeedSpecialReflow())) {
kidFrame = iter.Next();
continue;
@ -954,22 +961,22 @@ nsTableRowFrame::ReflowChildren(nsIPresContext* aPresContext,
// Reflow the child frame
if (doReflowChild) {
if (nsLayoutAtoms::tableCellFrame == frameType.get()) {
if (IS_TABLE_CELL(frameType.get())) {
nsTableCellFrame* cellFrame = (nsTableCellFrame*)kidFrame;
PRInt32 cellColIndex;
cellFrame->GetColIndex(cellColIndex);
cellColSpan = tableFrame->GetEffectiveColSpan(*cellFrame);
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))) {
x += GetSpaceBetween(prevColIndex, cellColIndex, cellColSpan, *tableFrame,
x += GetSpaceBetween(prevColIndex, cellColIndex, cellColSpan, aTableFrame,
cellSpacingX, iter.IsLeftToRight());
}
// Calculate the available width for the table cell using the known column widths
nscoord availColWidth, availCellWidth;
CalcAvailWidth(*tableFrame, GetComputedWidth(aReflowState, *tableFrame),
CalcAvailWidth(aTableFrame, GetComputedWidth(aReflowState, aTableFrame),
*cellFrame, cellSpacingX, availColWidth, availCellWidth);
if (0 == availColWidth) availColWidth = NS_UNCONSTRAINEDSIZE;
if (0 == availCellWidth) availCellWidth = NS_UNCONSTRAINEDSIZE;
@ -1032,6 +1039,8 @@ nsTableRowFrame::ReflowChildren(nsIPresContext* aPresContext,
// Reflow the child
nsTableCellReflowState kidReflowState(aPresContext, aReflowState,
kidFrame, kidAvailSize, reason);
InitChildReflowState(*aPresContext, kidAvailSize, borderCollapse, p2t, kidReflowState);
nsReflowStatus status;
rv = ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState,
x, 0, 0, status);
@ -1052,7 +1061,7 @@ nsTableRowFrame::ReflowChildren(nsIPresContext* aPresContext,
// allow the table to determine if/how the table needs to be rebalanced
if (cellToWatch && needToNotifyTable) {
needToNotifyTable = !tableFrame->CellChangedWidth(*cellFrame, oldMaxWidth, oldMaxElemWidth);
needToNotifyTable = !aTableFrame.CellChangedWidth(*cellFrame, oldMaxWidth, oldMaxElemWidth);
}
// If any of the cells are not complete, then we're not complete
@ -1081,10 +1090,10 @@ nsTableRowFrame::ReflowChildren(nsIPresContext* aPresContext,
// height may have changed, adjust descent to absorb any excess difference
nscoord ascent = cellFrame->GetDesiredAscent();
nscoord descent = desiredSize.height - ascent;
UpdateHeight(desiredSize.height, ascent, descent, tableFrame, cellFrame);
UpdateHeight(desiredSize.height, ascent, descent, &aTableFrame, cellFrame);
}
else {
PRInt32 rowSpan = tableFrame->GetEffectiveRowSpan((nsTableCellFrame&)*kidFrame);
PRInt32 rowSpan = aTableFrame.GetEffectiveRowSpan((nsTableCellFrame&)*kidFrame);
if ((1 == rowSpan) && (desiredSize.height > paginatedHeight)) {
paginatedHeight = desiredSize.height;
SetContentHeight(paginatedHeight);
@ -1102,13 +1111,14 @@ nsTableRowFrame::ReflowChildren(nsIPresContext* aPresContext,
else {// it's an unknown frame type, give it a generic reflow and ignore the results
nsTableCellReflowState kidReflowState(aPresContext, aReflowState,
kidFrame, nsSize(0,0), eReflowReason_Resize);
InitChildReflowState(*aPresContext, nsSize(0,0), PR_FALSE, p2t, kidReflowState);
nsHTMLReflowMetrics desiredSize(nsnull);
nsReflowStatus status;
ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState, 0, 0, 0, status);
kidFrame->DidReflow(aPresContext, nsnull, NS_FRAME_REFLOW_FINISHED);
}
}
else if (nsLayoutAtoms::tableCellFrame == frameType.get()) {
else if (IS_TABLE_CELL(frameType.get())) {
// we need to account for the cell's width even if it isn't reflowed
nsRect rect;
kidFrame->GetRect(rect);
@ -1244,7 +1254,10 @@ nsTableRowFrame::IR_TargetIsChild(nsIPresContext* aPresContext,
// update its maximum width.
nsHTMLReflowMetrics cellMet(&kidMaxElementSize, isAutoLayout ?
NS_REFLOW_CALC_MAX_WIDTH : 0);
nsTableCellReflowState kidRS(aPresContext, aReflowState, aNextFrame, cellAvailSize);
GET_PIXELS_TO_TWIPS(aPresContext, p2t);
nsTableCellReflowState kidRS(aPresContext, aReflowState, aNextFrame, cellAvailSize,
aReflowState.reason);
InitChildReflowState(*aPresContext, cellAvailSize, aTableFrame.IsBorderCollapse(), p2t, kidRS);
// Remember the current desired size, we'll need it later
nscoord oldCellMinWidth = cellFrame->GetPass1MaxElementWidth();
@ -1492,13 +1505,20 @@ nsTableRowFrame::ReflowCellFrame(nsIPresContext* aPresContext,
nscoord aAvailableHeight,
nsReflowStatus& aStatus)
{
nsTableFrame* tableFrame = nsnull;
nsTableFrame::GetTableFrame(this, tableFrame); if (!tableFrame) ABORT1(0);
// Reflow the cell frame with the specified height. Use the existing width
nsSize cellSize;
aCellFrame->GetSize(cellSize);
nsSize availSize(cellSize.width, aAvailableHeight);
PRBool borderCollapse = ((nsTableFrame*)tableFrame->GetFirstInFlow())->IsBorderCollapse();
GET_PIXELS_TO_TWIPS(aPresContext, p2t);
nsTableCellReflowState cellReflowState(aPresContext, aReflowState, aCellFrame, availSize,
eReflowReason_Resize);
InitChildReflowState(*aPresContext, availSize, borderCollapse, p2t, cellReflowState);
nsHTMLReflowMetrics desiredSize(nsnull);
ReflowChild(aCellFrame, aPresContext, desiredSize, cellReflowState,
@ -1534,7 +1554,7 @@ nsTableRowFrame::InsertCellFrame(nsTableCellFrame* aFrame,
for (nsIFrame* child = mFrames.FirstChild(); child; child->GetNextSibling(&child)) {
nsCOMPtr<nsIAtom> frameType;
child->GetFrameType(getter_AddRefs(frameType));
if (nsLayoutAtoms::tableCellFrame != frameType.get()) {
if (!IS_TABLE_CELL(frameType.get())) {
nsTableCellFrame* cellFrame = (nsTableCellFrame*)child;
PRInt32 colIndex;
cellFrame->GetColIndex(colIndex);

View File

@ -42,6 +42,7 @@
class nsTableFrame;
class nsTableCellFrame;
struct nsTableCellReflowState;
#ifdef DEBUG_TABLE_REFLOW_TIMING
class nsReflowTimer;
@ -240,6 +241,12 @@ public:
nscoord GetUnpaginatedHeight(nsIPresContext* aPresContext);
void SetUnpaginatedHeight(nsIPresContext* aPresContext, nscoord aValue);
nscoord GetTopBCBorderWidth(float* aPixelsToTwips = nsnull);
void SetTopBCBorderWidth(nscoord aWidth);
nscoord GetBottomBCBorderWidth(float* aPixelsToTwips = nsnull);
void SetBottomBCBorderWidth(nscoord aWidth);
nsMargin* GetBCBorderWidth(float aPixelsToTwips,
nsMargin& aBorder);
protected:
/** protected constructor.
@ -247,6 +254,12 @@ protected:
*/
nsTableRowFrame();
void InitChildReflowState(nsIPresContext& aPresContext,
const nsSize& aAvailSize,
PRBool aBorderCollapse,
float aPixelsToTwips,
nsTableCellReflowState& aReflowState);
/** implement abstract method on nsHTMLContainerFrame */
virtual PRIntn GetSkipSides() const;
@ -315,6 +328,10 @@ private:
nscoord mMaxCellAscent; // does include cells with rowspan > 1
nscoord mMaxCellDescent; // does *not* include cells with rowspan > 1
// border widths in pixels in the collapsing border model
unsigned mTopBorderWidth:8;
unsigned mBottomBorderWidth:8;
#ifdef DEBUG_TABLE_REFLOW_TIMING
public:
nsReflowTimer* mTimer;
@ -421,4 +438,37 @@ inline void nsTableRowFrame::SetHasUnpaginatedHeight(PRBool aValue)
}
}
inline nscoord nsTableRowFrame::GetTopBCBorderWidth(float* aPixelsToTwips)
{
nscoord width = (aPixelsToTwips) ? NSToCoordRound(*aPixelsToTwips * mTopBorderWidth) : mTopBorderWidth;
return width;
}
inline void nsTableRowFrame::SetTopBCBorderWidth(nscoord aWidth)
{
mTopBorderWidth = aWidth;
}
inline nscoord nsTableRowFrame::GetBottomBCBorderWidth(float* aPixelsToTwips)
{
nscoord width = (aPixelsToTwips) ? NSToCoordRound(*aPixelsToTwips * mBottomBorderWidth) : mBottomBorderWidth;
return width;
}
inline void nsTableRowFrame::SetBottomBCBorderWidth(nscoord aWidth)
{
mBottomBorderWidth = aWidth;
}
inline nsMargin* nsTableRowFrame::GetBCBorderWidth(float aPixelsToTwips,
nsMargin& aBorder)
{
aBorder.left = aBorder.right = 0;
aBorder.top = NSToCoordRound(aPixelsToTwips * mTopBorderWidth);
aBorder.bottom = NSToCoordRound(aPixelsToTwips * mBottomBorderWidth);
return &aBorder;
}
#endif

View File

@ -180,7 +180,7 @@ nsTableRowGroupFrame::InitRepeatedFrame(nsIPresContext* aPresContext,
nsIAtom* frameType;
copyCellFrame->GetFrameType(&frameType);
if (nsLayoutAtoms::tableCellFrame == frameType) {
if (IS_TABLE_CELL(frameType)) {
#ifdef NS_DEBUG
nsIContent* content1;
nsIContent* content2;
@ -360,6 +360,28 @@ nsTableRowGroupFrame::PlaceChild(nsIPresContext* aPresContext,
}
}
void
nsTableRowGroupFrame::InitChildReflowState(nsIPresContext& aPresContext,
PRBool aBorderCollapse,
float aPixelsToTwips,
nsHTMLReflowState& aReflowState)
{
nsMargin collapseBorder;
nsMargin padding(0,0,0,0);
nsMargin* pCollapseBorder = nsnull;
if (aBorderCollapse) {
if (aReflowState.frame) {
nsCOMPtr<nsIAtom> fType;
aReflowState.frame->GetFrameType(getter_AddRefs(fType));
if (nsLayoutAtoms::tableRowFrame == fType.get()) {
nsTableRowFrame* rowFrame = (nsTableRowFrame*)aReflowState.frame;
pCollapseBorder = rowFrame->GetBCBorderWidth(aPixelsToTwips, collapseBorder);
}
}
}
aReflowState.Init(&aPresContext, -1, -1, pCollapseBorder, &padding);
}
// Reflow the frames we've already created. If aDirtyOnly is set then only
// reflow dirty frames. This assumes that all of the dirty frames are contiguous.
NS_METHOD
@ -372,8 +394,10 @@ nsTableRowGroupFrame::ReflowChildren(nsIPresContext* aPresContext,
nsTableRowFrame** aFirstRowReflowed)
{
nsTableFrame* tableFrame = nsnull;
nsresult rv = nsTableFrame::GetTableFrame(this, tableFrame);
if (NS_FAILED(rv) || !tableFrame) return rv;
nsresult rv = nsTableFrame::GetTableFrame(this, tableFrame); if (!tableFrame) ABORT1(rv);
PRBool borderCollapse = tableFrame->IsBorderCollapse();
GET_PIXELS_TO_TWIPS(aPresContext, p2t);
nscoord cellSpacingY = tableFrame->GetCellSpacingY();
@ -439,6 +463,7 @@ nsTableRowGroupFrame::ReflowChildren(nsIPresContext* aPresContext,
}
nsHTMLReflowState kidReflowState(aPresContext, aReflowState.reflowState, kidFrame,
kidAvailSize, reason);
InitChildReflowState(*aPresContext, borderCollapse, p2t, kidReflowState);
// If this isn't the first row frame, then we can't be at the top of
// the page anymore...
@ -555,7 +580,7 @@ HasMoreThanOneCell(nsTableCellMap* aCellMap,
PRInt32 colIndex = 0;
PRInt32 count = 0;
do {
cellData = aCellMap->GetCellAt(aRowIndex, colIndex);
cellData = aCellMap->GetDataAt(aRowIndex, colIndex);
if (cellData && (cellData->GetCellFrame() || cellData->IsRowSpan()))
count++;
if (count > 1)
@ -998,8 +1023,8 @@ nsTableRowGroupFrame::SplitRowGroup(nsIPresContext* aPresContext,
presShell->GetStyleSet(getter_AddRefs(styleSet));
if (!styleSet) {NS_ASSERTION(PR_FALSE, "no style set"); return NS_ERROR_NULL_POINTER;}
float p2t;
aPresContext->GetPixelsToTwips(&p2t);
GET_PIXELS_TO_TWIPS(aPresContext, p2t);
PRBool borderCollapse = ((nsTableFrame*)aTableFrame->GetFirstInFlow())->IsBorderCollapse();
nscoord availWidth = nsTableFrame::RoundToPixel(aReflowState.availableWidth, p2t);
nscoord availHeight = nsTableFrame::RoundToPixel(aReflowState.availableHeight, p2t);
@ -1022,9 +1047,11 @@ nsTableRowGroupFrame::SplitRowGroup(nsIPresContext* aPresContext,
// row or there is at least 5% of the current page available
if (!prevRowFrame || (availHeight - aDesiredSize.height > pageHeight / 20)) {
// Reflow the row in the available space and have it split
nsSize availSize(availWidth, availHeight - bounds.y);
nsHTMLReflowState rowReflowState(aPresContext, aReflowState, rowFrame,
availSize, eReflowReason_Resize);
nsSize availSize(availWidth, availHeight - bounds.y);
nsHTMLReflowState rowReflowState(aPresContext, aReflowState, rowFrame, availSize,
eReflowReason_Resize);
InitChildReflowState(*aPresContext, borderCollapse, p2t, rowReflowState);
nsHTMLReflowMetrics desiredSize(nsnull);
rv = ReflowChild(rowFrame, aPresContext, desiredSize, rowReflowState,
@ -1530,6 +1557,10 @@ nsTableRowGroupFrame::IR_TargetIsChild(nsIPresContext* aPresContext,
{
nsresult rv;
nsTableFrame* tableFrame = nsnull;
nsTableFrame::GetTableFrame(this, tableFrame); if (!tableFrame) ABORT1(NS_ERROR_NULL_POINTER);
GET_PIXELS_TO_TWIPS(aPresContext, p2t);
// Recover the state as if aNextFrame is about to be reflowed
RecoverState(aReflowState, aNextFrame);
@ -1540,9 +1571,11 @@ nsTableRowGroupFrame::IR_TargetIsChild(nsIPresContext* aPresContext,
// Reflow the child giving it as much room as it wants. We'll deal with
// splitting later after final determination of rows heights taking into
// account cells with row spans...
nsSize kidAvailSize(aReflowState.availSize.width, NS_UNCONSTRAINEDSIZE);
nsHTMLReflowState kidReflowState(aPresContext, aReflowState.reflowState,
aNextFrame, kidAvailSize);
nsSize kidAvailSize(aReflowState.availSize.width, NS_UNCONSTRAINEDSIZE);
nsHTMLReflowState kidReflowState(aPresContext, aReflowState.reflowState, aNextFrame,
kidAvailSize, aReflowState.reason);
InitChildReflowState(*aPresContext, tableFrame->IsBorderCollapse(), p2t, kidReflowState);
nsSize kidMaxElementSize;
nsHTMLReflowMetrics desiredSize(aDesiredSize.maxElementSize ? &kidMaxElementSize : nsnull,
aDesiredSize.mFlags);
@ -1715,6 +1748,28 @@ nsTableRowGroupFrame::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) cons
}
#endif
nsMargin*
nsTableRowGroupFrame::GetBCBorderWidth(float aPixelsToTwips,
nsMargin& aBorder)
{
aBorder.left = aBorder.right = 0;
nsTableRowFrame* firstRowFrame = nsnull;
nsTableRowFrame* lastRowFrame = nsnull;
for (nsTableRowFrame* rowFrame = GetFirstRow(); rowFrame; rowFrame = rowFrame->GetNextRow()) {
if(!firstRowFrame) {
firstRowFrame = rowFrame;
}
lastRowFrame = rowFrame;
}
if (firstRowFrame) {
aBorder.top = firstRowFrame->GetTopBCBorderWidth(&aPixelsToTwips);
aBorder.bottom = lastRowFrame->GetBottomBCBorderWidth(&aPixelsToTwips);
}
return &aBorder;
}
//nsILineIterator methods for nsTableFrame
NS_IMETHODIMP
nsTableRowGroupFrame::GetNumLines(PRInt32* aResult)
@ -1757,7 +1812,7 @@ nsTableRowGroupFrame::GetLine(PRInt32 aLineNumber,
*aLineFlags = 0;/// should we fill these in later?
// not gonna touch aLineBounds right now
CellData* firstCellData = cellMap->GetCellAt(aLineNumber, 0);
CellData* firstCellData = cellMap->GetDataAt(aLineNumber, 0);
if(!firstCellData)
return NS_ERROR_FAILURE;
@ -1767,7 +1822,7 @@ nsTableRowGroupFrame::GetLine(PRInt32 aLineNumber,
while((aLineNumber > 0)&&(!(*aFirstFrameOnLine)))
{
aLineNumber--;
firstCellData = cellMap->GetCellAt(aLineNumber, 0);
firstCellData = cellMap->GetDataAt(aLineNumber, 0);
*aFirstFrameOnLine = (nsIFrame*)firstCellData->GetCellFrame();
}
}
@ -1847,7 +1902,7 @@ nsTableRowGroupFrame::FindFrameAt(PRInt32 aLineNumber,
PRBool gotParentRect = PR_FALSE;
for(int i =0;i < cellCount; i++)
{
cellData = cellMap->GetCellAt(aLineNumber, i);
cellData = cellMap->GetDataAt(aLineNumber, i);
tempFrame = (nsIFrame*)cellData->GetCellFrame();
if(!tempFrame)
@ -1919,11 +1974,11 @@ nsTableRowGroupFrame::GetNextSiblingOnLine(nsIFrame*& aFrame,
PRInt32& colIndexRef = colIndex;
cellFrame->GetColIndex(colIndexRef);
CellData* cellData = cellMap->GetCellAt(aLineNumber, colIndex + 1);
CellData* cellData = cellMap->GetDataAt(aLineNumber, colIndex + 1);
if(!cellData)// if this isnt a valid cell, drop down and check the next line
{
cellData = cellMap->GetCellAt(aLineNumber + 1, 0);
cellData = cellMap->GetDataAt(aLineNumber + 1, 0);
if(!cellData)
{
//*aFrame = nsnull;
@ -1940,14 +1995,14 @@ nsTableRowGroupFrame::GetNextSiblingOnLine(nsIFrame*& aFrame,
while((tempCol > 0) && (!aFrame))
{
tempCol--;
cellData = cellMap->GetCellAt(aLineNumber, tempCol);
cellData = cellMap->GetDataAt(aLineNumber, tempCol);
aFrame = (nsIFrame*)cellData->GetCellFrame();
if(!aFrame && (tempCol==0))
{
while((tempRow > 0) && (!aFrame))
{
tempRow--;
cellData = cellMap->GetCellAt(tempRow, 0);
cellData = cellMap->GetDataAt(tempRow, 0);
aFrame = (nsIFrame*)cellData->GetCellFrame();
}
}

View File

@ -216,6 +216,8 @@ public:
nscoord GetHeightOfRows(nsIPresContext* aPresContext);
nscoord GetHeightBasis(const nsHTMLReflowState& aReflowState);
nsMargin* GetBCBorderWidth(float aPixelsToTwips,
nsMargin& aBorder);
// nsILineIterator methods
public:
NS_IMETHOD GetNumLines(PRInt32* aResult);
@ -251,6 +253,11 @@ public:
protected:
nsTableRowGroupFrame();
void InitChildReflowState(nsIPresContext& aPresContext,
PRBool aBorderCollapse,
float aPixelsToTwips,
nsHTMLReflowState& aReflowState);
/** implement abstract method on nsHTMLContainerFrame */
virtual PRIntn GetSkipSides() const;