Bug 330964 - Add rowspacing/columnspacing/framespacing to MathML mtable. r=fredw
This commit is contained in:
@@ -153,11 +153,10 @@ mlabeledtr > mtd:first-child {
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
/* rules to achieve the default spacing between cells. The back-end code
|
||||
/* rules to achieve the default spacing between cells. When rowspacing,
|
||||
columnspacing and framespacing aren't set on mtable. The back-end code
|
||||
will set the internal attributes depending on the cell's position.
|
||||
These rules are hard-coded, the comments indicate what would be
|
||||
desirable if the style data could be changed on the fly to pick
|
||||
the values that users may set with the attributes of <mtable> */
|
||||
When they are set, the spacing behaviour is handled outside of CSS */
|
||||
mtd {
|
||||
padding-right: 0.4em; /* half of columnspacing[colindex] */
|
||||
padding-left: 0.4em; /* half of columnspacing[colindex-1] */
|
||||
@@ -195,6 +194,13 @@ mtable[frame="dashed"] > mtr > mtd:last-child {
|
||||
-moz-padding-end: 0.4em; /* framespacing.right (or left in rtl)*/
|
||||
}
|
||||
|
||||
mtable[rowspacing] > mtr > mtd,
|
||||
mtable[columnspacing] > mtr > mtd,
|
||||
mtable[framespacing] > mtr > mtd {
|
||||
/* Spacing handled outside of CSS */
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/* This rule is used to give a style context suitable for nsMathMLChars.
|
||||
We don't actually style -moz-math-anonymous by default. */
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "nsNameSpaceManager.h"
|
||||
#include "nsRenderingContext.h"
|
||||
#include "nsCSSRendering.h"
|
||||
#include "nsMathMLElement.h"
|
||||
|
||||
#include "nsTArray.h"
|
||||
#include "nsTableFrame.h"
|
||||
@@ -229,6 +230,38 @@ ApplyBorderToStyle(const nsMathMLmtdFrame* aFrame,
|
||||
}
|
||||
}
|
||||
|
||||
static nsMargin
|
||||
ComputeBorderOverflow(nsMathMLmtdFrame* aFrame, nsStyleBorder aStyleBorder)
|
||||
{
|
||||
nsMargin overflow;
|
||||
int32_t rowIndex;
|
||||
int32_t columnIndex;
|
||||
nsMathMLmtableFrame* mathMLmtableFrame =
|
||||
static_cast<nsMathMLmtableFrame*>(nsTableFrame::GetTableFrame(aFrame));
|
||||
aFrame->GetCellIndexes(rowIndex, columnIndex);
|
||||
if (!columnIndex) {
|
||||
overflow.left = mathMLmtableFrame->GetCellSpacingX(-1);
|
||||
overflow.right = mathMLmtableFrame->GetCellSpacingX(0) / 2;
|
||||
} else if (columnIndex == mathMLmtableFrame->GetColCount() - 1) {
|
||||
overflow.left = mathMLmtableFrame->GetCellSpacingX(columnIndex - 1) / 2;
|
||||
overflow.right = mathMLmtableFrame->GetCellSpacingX(columnIndex + 1);
|
||||
} else {
|
||||
overflow.left = mathMLmtableFrame->GetCellSpacingX(columnIndex - 1) / 2;
|
||||
overflow.right = mathMLmtableFrame->GetCellSpacingX(columnIndex) / 2;
|
||||
}
|
||||
if (!rowIndex) {
|
||||
overflow.top = mathMLmtableFrame->GetCellSpacingY(-1);
|
||||
overflow.bottom = mathMLmtableFrame->GetCellSpacingY(0) / 2;
|
||||
} else if (rowIndex == mathMLmtableFrame->GetRowCount() - 1) {
|
||||
overflow.top = mathMLmtableFrame->GetCellSpacingY(rowIndex - 1) / 2;
|
||||
overflow.bottom = mathMLmtableFrame->GetCellSpacingY(rowIndex + 1);
|
||||
} else {
|
||||
overflow.top = mathMLmtableFrame->GetCellSpacingY(rowIndex - 1) / 2;
|
||||
overflow.bottom = mathMLmtableFrame->GetCellSpacingY(rowIndex) / 2;
|
||||
}
|
||||
return overflow;
|
||||
}
|
||||
|
||||
/*
|
||||
* A variant of the nsDisplayBorder contains special code to render a border
|
||||
* around a nsMathMLmtdFrame based on the rowline and columnline properties
|
||||
@@ -244,20 +277,27 @@ public:
|
||||
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE
|
||||
{
|
||||
nsStyleBorder styleBorder = *mFrame->StyleBorder();
|
||||
ApplyBorderToStyle(static_cast<nsMathMLmtdFrame*>(mFrame), styleBorder);
|
||||
return CalculateBounds(styleBorder);
|
||||
nsMathMLmtdFrame* frame = static_cast<nsMathMLmtdFrame*>(mFrame);
|
||||
ApplyBorderToStyle(frame, styleBorder);
|
||||
nsRect bounds = CalculateBounds(styleBorder);
|
||||
nsMargin overflow = ComputeBorderOverflow(frame, styleBorder);
|
||||
bounds.Inflate(overflow);
|
||||
return bounds;
|
||||
}
|
||||
|
||||
virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE
|
||||
{
|
||||
nsStyleBorder styleBorder = *mFrame->StyleBorder();
|
||||
ApplyBorderToStyle(static_cast<nsMathMLmtdFrame*>(mFrame), styleBorder);
|
||||
nsMathMLmtdFrame* frame = static_cast<nsMathMLmtdFrame*>(mFrame);
|
||||
ApplyBorderToStyle(frame, styleBorder);
|
||||
|
||||
nsRect bounds = nsRect(ToReferenceFrame(), mFrame->GetSize());
|
||||
nsMargin overflow = ComputeBorderOverflow(frame, styleBorder);
|
||||
bounds.Inflate(overflow);
|
||||
|
||||
nsPoint offset = ToReferenceFrame();
|
||||
nsCSSRendering::PaintBorderWithStyleBorder(mFrame->PresContext(), *aCtx,
|
||||
mFrame, mVisibleRect,
|
||||
nsRect(offset,
|
||||
mFrame->GetSize()),
|
||||
bounds,
|
||||
styleBorder,
|
||||
mFrame->StyleContext(),
|
||||
mFrame->GetSkipSides());
|
||||
@@ -297,10 +337,204 @@ ParseFrameAttribute(nsIFrame* aFrame, nsIAtom* aAttribute,
|
||||
}
|
||||
}
|
||||
|
||||
// rowspacing
|
||||
//
|
||||
// Specifies the distance between successive rows in an mtable. Multiple
|
||||
// lengths can be specified, each corresponding to its respective position
|
||||
// between rows. For example:
|
||||
//
|
||||
// [ROW_0]
|
||||
// rowspace_0
|
||||
// [ROW_1]
|
||||
// rowspace_1
|
||||
// [ROW_2]
|
||||
//
|
||||
// If the number of row gaps exceeds the number of lengths specified, the final
|
||||
// specified length is repeated. Additional lengths are ignored.
|
||||
//
|
||||
// values: (length)+
|
||||
// default: 1.0ex
|
||||
//
|
||||
// Unitless values are permitted and provide a multiple of the default value
|
||||
// Negative values are forbidden.
|
||||
//
|
||||
|
||||
// columnspacing
|
||||
//
|
||||
// Specifies the distance between successive columns in an mtable. Multiple
|
||||
// lengths can be specified, each corresponding to its respective position
|
||||
// between columns. For example:
|
||||
//
|
||||
// [COLUMN_0] columnspace_0 [COLUMN_1] columnspace_1 [COLUMN_2]
|
||||
//
|
||||
// If the number of column gaps exceeds the number of lengths specified, the
|
||||
// final specified length is repeated. Additional lengths are ignored.
|
||||
//
|
||||
// values: (length)+
|
||||
// default: 0.8em
|
||||
//
|
||||
// Unitless values are permitted and provide a multiple of the default value
|
||||
// Negative values are forbidden.
|
||||
//
|
||||
|
||||
// framespacing
|
||||
//
|
||||
// Specifies the distance between the mtable and its frame (if any). The
|
||||
// first value specified provides the spacing between the left and right edge
|
||||
// of the table and the frame, the second value determines the spacing between
|
||||
// the top and bottom edges and the frame.
|
||||
//
|
||||
// An error is reported if only one length is passed. Any additional lengths
|
||||
// are ignored
|
||||
//
|
||||
// values: length length
|
||||
// default: 0em 0ex If frame attribute is "none" or not specified,
|
||||
// 0.4em 0.5ex otherwise
|
||||
//
|
||||
// Unitless values are permitted and provide a multiple of the default value
|
||||
// Negative values are forbidden.
|
||||
//
|
||||
|
||||
static const float kDefaultRowspacingEx = 1.0f;
|
||||
static const float kDefaultColumnspacingEm = 0.8f;
|
||||
static const float kDefaultFramespacingArg0Em = 0.4f;
|
||||
static const float kDefaultFramespacingArg1Ex = 0.5f;
|
||||
|
||||
static void
|
||||
ExtractSpacingValues(const nsAString& aString,
|
||||
nsIAtom* aAttribute,
|
||||
nsTArray<nscoord>& aSpacingArray,
|
||||
nsIFrame* aFrame,
|
||||
nscoord aDefaultValue0,
|
||||
nscoord aDefaultValue1)
|
||||
{
|
||||
nsPresContext* presContext = aFrame->PresContext();
|
||||
nsStyleContext* styleContext = aFrame->StyleContext();
|
||||
|
||||
const char16_t* start = aString.BeginReading();
|
||||
const char16_t* end = aString.EndReading();
|
||||
|
||||
int32_t startIndex = 0;
|
||||
int32_t count = 0;
|
||||
int32_t elementNum = 0;
|
||||
|
||||
while (start < end) {
|
||||
// Skip leading spaces.
|
||||
while ((start < end) && nsCRT::IsAsciiSpace(*start)) {
|
||||
start++;
|
||||
startIndex++;
|
||||
}
|
||||
|
||||
// Look for the end of the string, or another space.
|
||||
while ((start < end) && !nsCRT::IsAsciiSpace(*start)) {
|
||||
start++;
|
||||
count++;
|
||||
}
|
||||
|
||||
// Grab the value found and process it.
|
||||
if (count > 0) {
|
||||
const nsAString& str = Substring(aString, startIndex, count);
|
||||
nsAutoString valueString;
|
||||
valueString.Assign(str);
|
||||
nscoord newValue;
|
||||
if (aAttribute == nsGkAtoms::framespacing_ && elementNum) {
|
||||
newValue = aDefaultValue1;
|
||||
} else {
|
||||
newValue = aDefaultValue0;
|
||||
}
|
||||
nsMathMLFrame::ParseNumericValue(valueString, &newValue,
|
||||
nsMathMLElement::PARSE_ALLOW_UNITLESS,
|
||||
presContext, styleContext);
|
||||
aSpacingArray.AppendElement(newValue);
|
||||
|
||||
startIndex += count;
|
||||
count = 0;
|
||||
elementNum++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ParseSpacingAttribute(nsMathMLmtableFrame* aFrame, nsIAtom* aAttribute)
|
||||
{
|
||||
NS_ASSERTION(aAttribute == nsGkAtoms::rowspacing_ ||
|
||||
aAttribute == nsGkAtoms::columnspacing_ ||
|
||||
aAttribute == nsGkAtoms::framespacing_,
|
||||
"Non spacing attribute passed");
|
||||
|
||||
nsAutoString attrValue;
|
||||
nsIContent* frameContent = aFrame->GetContent();
|
||||
frameContent->GetAttr(kNameSpaceID_None, aAttribute, attrValue);
|
||||
|
||||
if (nsGkAtoms::framespacing_ == aAttribute) {
|
||||
nsAutoString frame;
|
||||
frameContent->GetAttr(kNameSpaceID_None, nsGkAtoms::frame, frame);
|
||||
if (frame.IsEmpty() || frame.EqualsLiteral("none")) {
|
||||
aFrame->SetFrameSpacing(0, 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
nscoord value;
|
||||
nscoord value2;
|
||||
// Set defaults
|
||||
nsRefPtr<nsFontMetrics> fm;
|
||||
nsLayoutUtils::GetFontMetricsForFrame(aFrame, getter_AddRefs(fm));
|
||||
if (nsGkAtoms::rowspacing_ == aAttribute) {
|
||||
value = kDefaultRowspacingEx * fm->XHeight();
|
||||
value2 = 0;
|
||||
} else if (nsGkAtoms::columnspacing_ == aAttribute) {
|
||||
value = kDefaultColumnspacingEm * fm->EmHeight();
|
||||
value2 = 0;
|
||||
} else {
|
||||
value = kDefaultFramespacingArg0Em * fm->EmHeight();
|
||||
value2 = kDefaultFramespacingArg1Ex * fm->XHeight();
|
||||
}
|
||||
|
||||
nsTArray<nscoord> valueList;
|
||||
ExtractSpacingValues(attrValue, aAttribute, valueList, aFrame, value, value2);
|
||||
if (valueList.Length() == 0) {
|
||||
if (frameContent->HasAttr(kNameSpaceID_None, aAttribute)) {
|
||||
ReportParseError(aFrame, aAttribute->GetUTF16String(),
|
||||
attrValue.get());
|
||||
}
|
||||
valueList.AppendElement(value);
|
||||
}
|
||||
if (aAttribute == nsGkAtoms::framespacing_) {
|
||||
if (valueList.Length() == 1) {
|
||||
if(frameContent->HasAttr(kNameSpaceID_None, aAttribute)) {
|
||||
ReportParseError(aFrame, aAttribute->GetUTF16String(),
|
||||
attrValue.get());
|
||||
}
|
||||
valueList.AppendElement(value2);
|
||||
} else if (valueList.Length() != 2) {
|
||||
ReportParseError(aFrame, aAttribute->GetUTF16String(),
|
||||
attrValue.get());
|
||||
}
|
||||
}
|
||||
|
||||
if (aAttribute == nsGkAtoms::rowspacing_) {
|
||||
aFrame->SetRowSpacingArray(valueList);
|
||||
} else if (aAttribute == nsGkAtoms::columnspacing_) {
|
||||
aFrame->SetColSpacingArray(valueList);
|
||||
} else {
|
||||
aFrame->SetFrameSpacing(valueList.ElementAt(0),
|
||||
valueList.ElementAt(1));
|
||||
}
|
||||
}
|
||||
|
||||
static void ParseSpacingAttributes(nsMathMLmtableFrame* aTableFrame)
|
||||
{
|
||||
ParseSpacingAttribute(aTableFrame, nsGkAtoms::rowspacing_);
|
||||
ParseSpacingAttribute(aTableFrame, nsGkAtoms::columnspacing_);
|
||||
ParseSpacingAttribute(aTableFrame, nsGkAtoms::framespacing_);
|
||||
aTableFrame->SetUseCSSSpacing();
|
||||
}
|
||||
|
||||
// map all attribues within a table -- requires the indices of rows and cells.
|
||||
// so it can only happen after they are made ready by the table base class.
|
||||
static void
|
||||
MapAllAttributesIntoCSS(nsIFrame* aTableFrame)
|
||||
MapAllAttributesIntoCSS(nsMathMLmtableFrame* aTableFrame)
|
||||
{
|
||||
// Map mtable rowalign & rowlines.
|
||||
ParseFrameAttribute(aTableFrame, nsGkAtoms::rowalign_, true);
|
||||
@@ -310,6 +544,9 @@ MapAllAttributesIntoCSS(nsIFrame* aTableFrame)
|
||||
ParseFrameAttribute(aTableFrame, nsGkAtoms::columnalign_, true);
|
||||
ParseFrameAttribute(aTableFrame, nsGkAtoms::columnlines_, true);
|
||||
|
||||
// Map mtable rowspacing, columnspacing & framespacing
|
||||
ParseSpacingAttributes(aTableFrame);
|
||||
|
||||
// mtable is simple and only has one (pseudo) row-group
|
||||
nsIFrame* rgFrame = aTableFrame->GetFirstPrincipalChild();
|
||||
if (!rgFrame || rgFrame->GetType() != nsGkAtoms::tableRowGroupFrame)
|
||||
@@ -441,7 +678,7 @@ nsMathMLmtableOuterFrame::AttributeChanged(int32_t aNameSpaceID,
|
||||
{
|
||||
// Attributes specific to <mtable>:
|
||||
// frame : in mathml.css
|
||||
// framespacing : not yet supported
|
||||
// framespacing : here
|
||||
// groupalign : not yet supported
|
||||
// equalrows : not yet supported
|
||||
// equalcolumns : not yet supported
|
||||
@@ -449,10 +686,10 @@ nsMathMLmtableOuterFrame::AttributeChanged(int32_t aNameSpaceID,
|
||||
// align : in reflow
|
||||
// rowalign : here
|
||||
// rowlines : here
|
||||
// rowspacing : not yet supported
|
||||
// rowspacing : here
|
||||
// columnalign : here
|
||||
// columnlines : here
|
||||
// columnspacing : not yet supported
|
||||
// columnspacing : here
|
||||
|
||||
// mtable is simple and only has one (pseudo) row-group inside our inner-table
|
||||
nsIFrame* tableFrame = mFrames.FirstChild();
|
||||
@@ -483,23 +720,29 @@ nsMathMLmtableOuterFrame::AttributeChanged(int32_t aNameSpaceID,
|
||||
|
||||
// ...and the other attributes affect rows or columns in one way or another
|
||||
|
||||
// Ignore attributes that do not affect layout.
|
||||
if (aAttribute != nsGkAtoms::rowalign_ &&
|
||||
aAttribute != nsGkAtoms::rowlines_ &&
|
||||
aAttribute != nsGkAtoms::columnalign_ &&
|
||||
aAttribute != nsGkAtoms::columnlines_) {
|
||||
nsPresContext* presContext = tableFrame->PresContext();
|
||||
if (aAttribute == nsGkAtoms::rowspacing_ ||
|
||||
aAttribute == nsGkAtoms::columnspacing_ ||
|
||||
aAttribute == nsGkAtoms::framespacing_ ) {
|
||||
nsMathMLmtableFrame* mathMLmtableFrame = do_QueryFrame(tableFrame);
|
||||
if (mathMLmtableFrame) {
|
||||
ParseSpacingAttribute(mathMLmtableFrame, aAttribute);
|
||||
mathMLmtableFrame->SetUseCSSSpacing();
|
||||
}
|
||||
} else if (aAttribute == nsGkAtoms::rowalign_ ||
|
||||
aAttribute == nsGkAtoms::rowlines_ ||
|
||||
aAttribute == nsGkAtoms::columnalign_ ||
|
||||
aAttribute == nsGkAtoms::columnlines_) {
|
||||
// clear any cached property list for this table
|
||||
presContext->PropertyTable()->
|
||||
Delete(tableFrame, AttributeToProperty(aAttribute));
|
||||
// Reparse the new attribute on the table.
|
||||
ParseFrameAttribute(tableFrame, aAttribute, true);
|
||||
} else {
|
||||
// Ignore attributes that do not affect layout.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsPresContext* presContext = tableFrame->PresContext();
|
||||
|
||||
// clear any cached property list for this table
|
||||
presContext->PropertyTable()->
|
||||
Delete(tableFrame, AttributeToProperty(aAttribute));
|
||||
|
||||
// Reparse the new attribute on the table.
|
||||
ParseFrameAttribute(tableFrame, aAttribute, true);
|
||||
|
||||
// Explicitly request a reflow in our subtree to pick up any changes
|
||||
presContext->PresShell()->
|
||||
FrameNeedsReflow(this, nsIPresShell::eStyleChange, NS_FRAME_IS_DIRTY);
|
||||
@@ -682,6 +925,139 @@ nsMathMLmtableFrame::RestyleTable()
|
||||
nsChangeHint_AllReflowHints);
|
||||
}
|
||||
|
||||
nscoord
|
||||
nsMathMLmtableFrame::GetCellSpacingX(int32_t aColIndex)
|
||||
{
|
||||
if (mUseCSSSpacing) {
|
||||
return nsTableFrame::GetCellSpacingX(aColIndex);
|
||||
}
|
||||
if (!mColSpacing.Length()) {
|
||||
NS_ERROR("mColSpacing should not be empty");
|
||||
return 0;
|
||||
}
|
||||
if (aColIndex < 0 || aColIndex >= GetColCount()) {
|
||||
NS_ASSERTION(aColIndex == -1 || aColIndex == GetColCount(),
|
||||
"Desired column beyond bounds of table and border");
|
||||
return mFrameSpacingX;
|
||||
}
|
||||
if ((uint32_t) aColIndex >= mColSpacing.Length()) {
|
||||
return mColSpacing.LastElement();
|
||||
}
|
||||
return mColSpacing.ElementAt(aColIndex);
|
||||
}
|
||||
|
||||
nscoord
|
||||
nsMathMLmtableFrame::GetCellSpacingX(int32_t aStartColIndex,
|
||||
int32_t aEndColIndex)
|
||||
{
|
||||
if (mUseCSSSpacing) {
|
||||
return nsTableFrame::GetCellSpacingX(aStartColIndex, aEndColIndex);
|
||||
}
|
||||
if (aStartColIndex == aEndColIndex) {
|
||||
return 0;
|
||||
}
|
||||
if (!mColSpacing.Length()) {
|
||||
NS_ERROR("mColSpacing should not be empty");
|
||||
return 0;
|
||||
}
|
||||
nscoord space = 0;
|
||||
if (aStartColIndex < 0) {
|
||||
NS_ASSERTION(aStartColIndex == -1,
|
||||
"Desired column beyond bounds of table and border");
|
||||
space += mFrameSpacingX;
|
||||
aStartColIndex = 0;
|
||||
}
|
||||
if (aEndColIndex >= GetColCount()) {
|
||||
NS_ASSERTION(aEndColIndex == GetColCount(),
|
||||
"Desired column beyond bounds of table and border");
|
||||
space += mFrameSpacingX;
|
||||
aEndColIndex = GetColCount();
|
||||
}
|
||||
// Only iterate over column spacing when there is the potential to vary
|
||||
int32_t min = std::min(aEndColIndex, (int32_t) mColSpacing.Length());
|
||||
for (int32_t i = aStartColIndex; i < min; i++) {
|
||||
space += mColSpacing.ElementAt(i);
|
||||
}
|
||||
// The remaining values are constant. Note that if there are more
|
||||
// column spacings specified than there are columns, LastElement() will be
|
||||
// multiplied by 0, so it is still safe to use.
|
||||
space += (aEndColIndex - min) * mColSpacing.LastElement();
|
||||
return space;
|
||||
}
|
||||
|
||||
nscoord
|
||||
nsMathMLmtableFrame::GetCellSpacingY(int32_t aRowIndex)
|
||||
{
|
||||
if (mUseCSSSpacing) {
|
||||
return nsTableFrame::GetCellSpacingY(aRowIndex);
|
||||
}
|
||||
if (!mRowSpacing.Length()) {
|
||||
NS_ERROR("mRowSpacing should not be empty");
|
||||
return 0;
|
||||
}
|
||||
if (aRowIndex < 0 || aRowIndex >= GetRowCount()) {
|
||||
NS_ASSERTION(aRowIndex == -1 || aRowIndex == GetRowCount(),
|
||||
"Desired row beyond bounds of table and border");
|
||||
return mFrameSpacingY;
|
||||
}
|
||||
if ((uint32_t) aRowIndex >= mRowSpacing.Length()) {
|
||||
return mRowSpacing.LastElement();
|
||||
}
|
||||
return mRowSpacing.ElementAt(aRowIndex);
|
||||
}
|
||||
|
||||
nscoord
|
||||
nsMathMLmtableFrame::GetCellSpacingY(int32_t aStartRowIndex,
|
||||
int32_t aEndRowIndex)
|
||||
{
|
||||
if (mUseCSSSpacing) {
|
||||
return nsTableFrame::GetCellSpacingY(aStartRowIndex, aEndRowIndex);
|
||||
}
|
||||
if (aStartRowIndex == aEndRowIndex) {
|
||||
return 0;
|
||||
}
|
||||
if (!mRowSpacing.Length()) {
|
||||
NS_ERROR("mRowSpacing should not be empty");
|
||||
return 0;
|
||||
}
|
||||
nscoord space = 0;
|
||||
if (aStartRowIndex < 0) {
|
||||
NS_ASSERTION(aStartRowIndex == -1,
|
||||
"Desired row beyond bounds of table and border");
|
||||
space += mFrameSpacingY;
|
||||
aStartRowIndex = 0;
|
||||
}
|
||||
if (aEndRowIndex >= GetRowCount()) {
|
||||
NS_ASSERTION(aEndRowIndex == GetRowCount(),
|
||||
"Desired row beyond bounds of table and border");
|
||||
space += mFrameSpacingY;
|
||||
aEndRowIndex = GetRowCount();
|
||||
}
|
||||
// Only iterate over row spacing when there is the potential to vary
|
||||
int32_t min = std::min(aEndRowIndex, (int32_t) mRowSpacing.Length());
|
||||
for (int32_t i = aStartRowIndex; i < min; i++) {
|
||||
space += mRowSpacing.ElementAt(i);
|
||||
}
|
||||
// The remaining values are constant. Note that if there are more
|
||||
// row spacings specified than there are row, LastElement() will be
|
||||
// multiplied by 0, so it is still safe to use.
|
||||
space += (aEndRowIndex - min) * mRowSpacing.LastElement();
|
||||
return space;
|
||||
}
|
||||
|
||||
void
|
||||
nsMathMLmtableFrame::SetUseCSSSpacing()
|
||||
{
|
||||
mUseCSSSpacing =
|
||||
!(mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::rowspacing_) ||
|
||||
mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::columnspacing_) ||
|
||||
mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::framespacing_));
|
||||
}
|
||||
|
||||
NS_QUERYFRAME_HEAD(nsMathMLmtableFrame)
|
||||
NS_QUERYFRAME_ENTRY(nsMathMLmtableFrame)
|
||||
NS_QUERYFRAME_TAIL_INHERITING(nsTableFrame)
|
||||
|
||||
// --------
|
||||
// implementation of nsMathMLmtrFrame
|
||||
|
||||
@@ -858,6 +1234,15 @@ nsMathMLmtdFrame::GetBorderWidth(nsMargin& aBorder) const
|
||||
return &aBorder;
|
||||
}
|
||||
|
||||
nsMargin
|
||||
nsMathMLmtdFrame::GetBorderOverflow()
|
||||
{
|
||||
nsStyleBorder styleBorder = *StyleBorder();
|
||||
ApplyBorderToStyle(this, styleBorder);
|
||||
nsMargin overflow = ComputeBorderOverflow(this, styleBorder);
|
||||
return overflow;
|
||||
}
|
||||
|
||||
// --------
|
||||
// implementation of nsMathMLmtdInnerFrame
|
||||
|
||||
|
||||
@@ -62,6 +62,8 @@ protected:
|
||||
class nsMathMLmtableFrame : public nsTableFrame
|
||||
{
|
||||
public:
|
||||
NS_DECL_QUERYFRAME_TARGET(nsMathMLmtableFrame)
|
||||
NS_DECL_QUERYFRAME
|
||||
NS_DECL_FRAMEARENA_HELPERS
|
||||
|
||||
friend nsContainerFrame* NS_NewMathMLmtableFrame(nsIPresShell* aPresShell,
|
||||
@@ -108,9 +110,62 @@ public:
|
||||
// safer (albeit grossly suboptimal) to just relayout the whole thing.
|
||||
void RestyleTable();
|
||||
|
||||
/** helper to get the cell spacing X style value */
|
||||
nscoord GetCellSpacingX(int32_t aColIndex) MOZ_OVERRIDE;
|
||||
|
||||
/** Sums the combined cell spacing between the columns aStartColIndex to
|
||||
* aEndColIndex.
|
||||
*/
|
||||
nscoord GetCellSpacingX(int32_t aStartColIndex,
|
||||
int32_t aEndColIndex) MOZ_OVERRIDE;
|
||||
|
||||
/** helper to get the cell spacing Y style value */
|
||||
nscoord GetCellSpacingY(int32_t aRowIndex) MOZ_OVERRIDE;
|
||||
|
||||
/** Sums the combined cell spacing between the rows aStartRowIndex to
|
||||
* aEndRowIndex.
|
||||
*/
|
||||
nscoord GetCellSpacingY(int32_t aStartRowIndex,
|
||||
int32_t aEndRowIndex) MOZ_OVERRIDE;
|
||||
|
||||
void SetColSpacingArray(const nsTArray<nscoord>& aColSpacing)
|
||||
{
|
||||
mColSpacing = aColSpacing;
|
||||
}
|
||||
|
||||
void SetRowSpacingArray(const nsTArray<nscoord>& aRowSpacing)
|
||||
{
|
||||
mRowSpacing = aRowSpacing;
|
||||
}
|
||||
|
||||
void SetFrameSpacing(nscoord aSpacingX, nscoord aSpacingY)
|
||||
{
|
||||
mFrameSpacingX = aSpacingX;
|
||||
mFrameSpacingY = aSpacingY;
|
||||
}
|
||||
|
||||
/** Determines whether the placement of table cells is determined by CSS
|
||||
* spacing based on padding and border-spacing, or one based upon the
|
||||
* rowspacing, columnspacing and framespacing attributes. The second
|
||||
* approach is used if the user specifies at least one of those attributes.
|
||||
*/
|
||||
void SetUseCSSSpacing();
|
||||
|
||||
bool GetUseCSSSpacing()
|
||||
{
|
||||
return mUseCSSSpacing;
|
||||
}
|
||||
|
||||
protected:
|
||||
nsMathMLmtableFrame(nsStyleContext* aContext) : nsTableFrame(aContext) {}
|
||||
virtual ~nsMathMLmtableFrame();
|
||||
|
||||
private:
|
||||
nsTArray<nscoord> mColSpacing;
|
||||
nsTArray<nscoord> mRowSpacing;
|
||||
nscoord mFrameSpacingX;
|
||||
nscoord mFrameSpacingY;
|
||||
bool mUseCSSSpacing;
|
||||
}; // class nsMathMLmtableFrame
|
||||
|
||||
// --------------
|
||||
@@ -206,6 +261,8 @@ public:
|
||||
|
||||
virtual nsMargin* GetBorderWidth(nsMargin& aBorder) const MOZ_OVERRIDE;
|
||||
|
||||
virtual nsMargin GetBorderOverflow() MOZ_OVERRIDE;
|
||||
|
||||
protected:
|
||||
nsMathMLmtdFrame(nsStyleContext* aContext) : nsTableCellFrame(aContext) {}
|
||||
virtual ~nsMathMLmtdFrame();
|
||||
|
||||
Reference in New Issue
Block a user