зеркало из https://github.com/mozilla/gecko-dev.git
Improvements to <mtable>
This commit is contained in:
Родитель
c0c66c4dbc
Коммит
a1a725e6af
|
@ -44,7 +44,13 @@ extern nsresult NS_NewMathMLmoverFrame ( nsIPresShell* aPresShell, nsIFrame** aN
|
|||
extern nsresult NS_NewMathMLmunderoverFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame );
|
||||
extern nsresult NS_NewMathMLmmultiscriptsFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame );
|
||||
extern nsresult NS_NewMathMLmstyleFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame );
|
||||
|
||||
extern nsresult NS_NewMathMLmtableOuterFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame );
|
||||
inline nsresult NS_NewMathMLmtableFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame )
|
||||
{ return NS_NewTableFrame(aPresShell, aNewFrame); }
|
||||
inline nsresult NS_NewMathMLmtrFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame )
|
||||
{ return NS_NewTableRowFrame(aPresShell, aNewFrame); }
|
||||
extern nsresult NS_NewMathMLmtdFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame );
|
||||
extern nsresult NS_NewMathMLmtdInnerFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame );
|
||||
extern nsresult NS_NewMathMLmsqrtFrame( nsIPresShell* aPresShell, nsIFrame** aNewFrame );
|
||||
extern nsresult NS_NewMathMLmrootFrame( nsIPresShell* aPresShell, nsIFrame** aNewFrame );
|
||||
|
|
|
@ -3,19 +3,19 @@
|
|||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
*
|
||||
* The Original Code is Mozilla MathML Project.
|
||||
*
|
||||
* The Initial Developer of the Original Code is The University Of
|
||||
*
|
||||
* The Initial Developer of the Original Code is The University Of
|
||||
* Queensland. Portions created by The University Of Queensland are
|
||||
* Copyright (C) 1999 The University Of Queensland. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Contributor(s):
|
||||
* Roger B. Sidje <rbs@maths.uq.edu.au>
|
||||
*/
|
||||
|
||||
|
@ -37,9 +37,10 @@
|
|||
#include "nsStyleUtil.h"
|
||||
|
||||
#include "nsVoidArray.h"
|
||||
#include "nsLayoutAtoms.h"
|
||||
#include "nsIFrameManager.h"
|
||||
#include "nsStyleChangeList.h"
|
||||
#include "nsTableOuterFrame.h"
|
||||
#include "nsTableFrame.h"
|
||||
#include "nsTableCellFrame.h"
|
||||
|
||||
#include "nsMathMLmtableFrame.h"
|
||||
|
@ -98,9 +99,7 @@ struct nsValueList
|
|||
// stored in the frame manager. Cell frames query the frame manager
|
||||
// to see what values apply to them.
|
||||
|
||||
// XXX these are essentially temporary hacks until the content model
|
||||
// caters for MathML and the Style System has some provisions for MathML.
|
||||
// See bug 69409 - MathML attributes are not mapped to style.
|
||||
// XXX See bug 69409 - MathML attributes are not mapped to style.
|
||||
// This code is not suitable for dynamic updates, for example when the
|
||||
// rowalign and columalign attributes are changed with JavaScript.
|
||||
// The code doesn't include hooks for AttributeChanged() notifications.
|
||||
|
@ -115,10 +114,10 @@ DestroyValueListFunc(nsIPresContext* aPresContext,
|
|||
}
|
||||
|
||||
static PRUnichar*
|
||||
GetAlignValueAt(nsIPresContext* aPresContext,
|
||||
nsIFrame* aTableOrRowFrame,
|
||||
nsIAtom* aAttributeAtom,
|
||||
PRInt32 aIndex)
|
||||
GetValueAt(nsIPresContext* aPresContext,
|
||||
nsIFrame* aTableOrRowFrame,
|
||||
nsIAtom* aAttributeAtom,
|
||||
PRInt32 aRowOrColIndex)
|
||||
{
|
||||
PRUnichar* result = nsnull;
|
||||
nsValueList* valueList = nsnull;
|
||||
|
@ -149,25 +148,37 @@ GetAlignValueAt(nsIPresContext* aPresContext,
|
|||
|
||||
if (valueList) {
|
||||
PRInt32 count = valueList->mArray.Count();
|
||||
result = (aIndex < count)
|
||||
? (PRUnichar*)(valueList->mArray[aIndex])
|
||||
result = (aRowOrColIndex < count)
|
||||
? (PRUnichar*)(valueList->mArray[aRowOrColIndex])
|
||||
: (PRUnichar*)(valueList->mArray[count-1]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
MapAlignAttributesInto(nsIPresContext* aPresContext,
|
||||
nsIContent* aCellContent,
|
||||
nsIFrame* aCellFrame,
|
||||
nsIFrame* aCellInnerFrame)
|
||||
{
|
||||
nsresult rv;
|
||||
PRInt32 index;
|
||||
nsAutoString value;
|
||||
#ifdef NS_DEBUG
|
||||
#define DEBUG_VERIFY_THAT_FRAME_IS(_frame, _expected) \
|
||||
PR_BEGIN_MACRO \
|
||||
const nsStyleDisplay* display; \
|
||||
_frame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct *&)display); \
|
||||
NS_ASSERTION(NS_STYLE_DISPLAY_##_expected == display->mDisplay, "internal error"); \
|
||||
PR_END_MACRO
|
||||
#else
|
||||
#define DEBUG_VERIFY_THAT_FRAME_IS(_frame, _expected)
|
||||
#endif
|
||||
|
||||
nsTableCellFrame* cellFrame;
|
||||
cellFrame = NS_STATIC_CAST(nsTableCellFrame*, aCellFrame);
|
||||
static void
|
||||
MapAttributesInto(nsIPresContext* aPresContext,
|
||||
nsIContent* aCellContent,
|
||||
nsIFrame* aCellFrame,
|
||||
nsIFrame* aCellInnerFrame)
|
||||
{
|
||||
nsTableCellFrame* cellFrame = NS_STATIC_CAST(nsTableCellFrame*, aCellFrame);
|
||||
nsTableCellFrame* sibling;
|
||||
|
||||
PRInt32 rowIndex, colIndex;
|
||||
nsresult rv = cellFrame->GetCellIndexes(rowIndex, colIndex);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "cannot find the position of the cell frame");
|
||||
if (NS_FAILED(rv)) return;
|
||||
|
||||
nsIFrame* tableFrame;
|
||||
nsIFrame* rowgroupFrame;
|
||||
|
@ -176,69 +187,169 @@ MapAlignAttributesInto(nsIPresContext* aPresContext,
|
|||
cellFrame->GetParent(&rowFrame);
|
||||
rowFrame->GetParent(&rowgroupFrame);
|
||||
rowgroupFrame->GetParent(&tableFrame);
|
||||
DEBUG_VERIFY_THAT_FRAME_IS(rowFrame, TABLE_ROW);
|
||||
DEBUG_VERIFY_THAT_FRAME_IS(rowgroupFrame, TABLE_ROW_GROUP);
|
||||
DEBUG_VERIFY_THAT_FRAME_IS(tableFrame, TABLE);
|
||||
|
||||
nsIAtom* atom;
|
||||
PRUnichar* attr;
|
||||
nsAutoString value;
|
||||
PRBool hasChanged = PR_FALSE;
|
||||
NS_NAMED_LITERAL_STRING(trueStr, "true");
|
||||
|
||||
//////////////////////////////////////
|
||||
// update rowalign on the cell
|
||||
// process attributes that depend on the index of the row
|
||||
// rowalign, rowlines
|
||||
|
||||
PRUnichar* rowalign = nsnull;
|
||||
rv = cellFrame->GetRowIndex(index);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// see if the rowalign attribute is not already set
|
||||
nsIAtom* atom = nsMathMLAtoms::rowalign_;
|
||||
rv = aCellContent->GetAttr(kNameSpaceID_None, atom, value);
|
||||
if (NS_CONTENT_ATTR_NOT_THERE == rv) {
|
||||
// see if the rowalign attribute is specified on the row
|
||||
rowalign = GetAlignValueAt(aPresContext, rowFrame, atom, index);
|
||||
if (!rowalign) {
|
||||
// see if the rowalign attribute is specified on the table
|
||||
rowalign = GetAlignValueAt(aPresContext, tableFrame, atom, index);
|
||||
}
|
||||
// see if the rowalign attribute is not already set
|
||||
atom = nsMathMLAtoms::rowalign_;
|
||||
rv = aCellContent->GetAttr(kNameSpaceID_None, atom, value);
|
||||
if (NS_CONTENT_ATTR_NOT_THERE == rv) {
|
||||
// see if the rowalign attribute was specified on the row
|
||||
attr = GetValueAt(aPresContext, rowFrame, atom, rowIndex);
|
||||
if (!attr) {
|
||||
// see if the rowalign attribute was specified on the table
|
||||
attr = GetValueAt(aPresContext, tableFrame, atom, rowIndex);
|
||||
}
|
||||
// set the attribute without notifying that we want a reflow
|
||||
if (attr) {
|
||||
hasChanged = PR_TRUE;
|
||||
aCellContent->SetAttr(kNameSpaceID_None, atom, nsDependentString(attr), PR_FALSE);
|
||||
}
|
||||
}
|
||||
// if we are not on the first row, see if |rowlines| was specified on the table.
|
||||
// Note that we pass 'rowIndex-1' because the CSS rule in mathml.css is associated
|
||||
// to 'border-top', and it as if we draw the line on behalf of the previous row.
|
||||
// This way of doing so allows us to handle selective lines, [row]\hline[row][row]',
|
||||
// and cases of spanning cells without further complications.
|
||||
if (rowIndex > 0) {
|
||||
attr = GetValueAt(aPresContext, tableFrame, nsMathMLAtoms::rowlines_, rowIndex-1);
|
||||
// set the special -moz-math-rowline without notifying that we want a reflow
|
||||
if (attr) {
|
||||
hasChanged = PR_TRUE;
|
||||
aCellContent->SetAttr(kNameSpaceID_None, nsMathMLAtoms::rowline, nsDependentString(attr), PR_FALSE);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// set the special -moz-math-rowindex to annotate that we are on the first row
|
||||
hasChanged = PR_TRUE;
|
||||
aCellContent->SetAttr(kNameSpaceID_None, nsMathMLAtoms::firstrow, trueStr, PR_FALSE);
|
||||
}
|
||||
// if we are on the last row, set the special -moz-math-rowindex
|
||||
sibling = ((nsTableFrame*)tableFrame)->GetCellFrameAt(rowIndex+1, colIndex);
|
||||
if (!sibling) {
|
||||
hasChanged = PR_TRUE;
|
||||
aCellContent->SetAttr(kNameSpaceID_None, nsMathMLAtoms::lastrow, trueStr, PR_FALSE);
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
// update column on the cell
|
||||
// process attributes that depend on the index of the column
|
||||
// columnalign, columnlines, XXX need columnwidth too
|
||||
|
||||
PRUnichar* columnalign = nsnull;
|
||||
rv = cellFrame->GetColIndex(index);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// see if the columnalign attribute is not already set
|
||||
nsIAtom* atom = nsMathMLAtoms::columnalign_;
|
||||
rv = aCellContent->GetAttr(kNameSpaceID_None, atom, value);
|
||||
if (NS_CONTENT_ATTR_NOT_THERE == rv) {
|
||||
// see if the columnalign attribute is specified on the row
|
||||
columnalign = GetAlignValueAt(aPresContext, rowFrame, atom, index);
|
||||
if (!columnalign) {
|
||||
// see if the columnalign attribute is specified on the table
|
||||
columnalign = GetAlignValueAt(aPresContext, tableFrame, atom, index);
|
||||
// see if the columnalign attribute is not already set
|
||||
atom = nsMathMLAtoms::columnalign_;
|
||||
rv = aCellContent->GetAttr(kNameSpaceID_None, atom, value);
|
||||
if (NS_CONTENT_ATTR_NOT_THERE == rv) {
|
||||
// see if the columnalign attribute was specified on the row
|
||||
attr = GetValueAt(aPresContext, rowFrame, atom, colIndex);
|
||||
if (!attr) {
|
||||
// see if the columnalign attribute was specified on the table
|
||||
attr = GetValueAt(aPresContext, tableFrame, atom, colIndex);
|
||||
}
|
||||
if (attr) {
|
||||
hasChanged = PR_TRUE;
|
||||
aCellContent->SetAttr(kNameSpaceID_None, atom, nsDependentString(attr), PR_FALSE);
|
||||
}
|
||||
}
|
||||
// if we are not on the first column, see if |columnlines| was specified on
|
||||
// the table. Note that we pass 'colIndex-1' because the CSS rule in mathml.css
|
||||
// is associated to 'border-left', and it as if we draw the line on behalf
|
||||
// of the previous cell. This way of doing so allows us to handle selective lines,
|
||||
// e.g., 'r|cl', and cases of spanning cells without further complications.
|
||||
if (colIndex > 0) {
|
||||
attr = GetValueAt(aPresContext, tableFrame, nsMathMLAtoms::columnlines_, colIndex-1);
|
||||
// set the special -moz-math-columnline without notifying that we want a reflow
|
||||
if (attr) {
|
||||
hasChanged = PR_TRUE;
|
||||
aCellContent->SetAttr(kNameSpaceID_None, nsMathMLAtoms::columnline, nsDependentString(attr), PR_FALSE);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// set the special -moz-math-columnindex to annotate that we are on the first column
|
||||
hasChanged = PR_TRUE;
|
||||
aCellContent->SetAttr(kNameSpaceID_None, nsMathMLAtoms::firstcolumn, trueStr, PR_FALSE);
|
||||
}
|
||||
// if we are on the last column, set the special -moz-math-columnindex
|
||||
sibling = ((nsTableFrame*)tableFrame)->GetCellFrameAt(rowIndex, colIndex+1);
|
||||
if (!sibling) {
|
||||
hasChanged = PR_TRUE;
|
||||
aCellContent->SetAttr(kNameSpaceID_None, nsMathMLAtoms::lastcolumn, trueStr, PR_FALSE);
|
||||
}
|
||||
|
||||
// now, re-resolve the style contexts in our subtree to pick up any changes
|
||||
if (hasChanged) {
|
||||
nsCOMPtr<nsIPresShell> presShell;
|
||||
aPresContext->GetShell(getter_AddRefs(presShell));
|
||||
if (presShell) {
|
||||
nsCOMPtr<nsIFrameManager> fm;
|
||||
presShell->GetFrameManager(getter_AddRefs(fm));
|
||||
if (fm) {
|
||||
PRInt32 maxChange, minChange = NS_STYLE_HINT_NONE;
|
||||
nsStyleChangeList changeList;
|
||||
fm->ComputeStyleChangeFor(aPresContext, aCellFrame, kNameSpaceID_None, nsnull,
|
||||
changeList, minChange, maxChange);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// set the attributes without notifying that we want a reflow
|
||||
if (rowalign) {
|
||||
value.Assign(rowalign);
|
||||
aCellContent->SetAttr(kNameSpaceID_None, nsMathMLAtoms::rowalign_,
|
||||
value, PR_FALSE);
|
||||
// the align attribute of mtable can have a row number which indicates
|
||||
// from where to anchor the table, e.g., top5 means anchor the table at
|
||||
// the top of the 5th row, axis-1 means anchor the table on the axis of
|
||||
// the last row (could have been nicer if the REC used the '#' separator,
|
||||
// e.g., top#5, or axis#-1)
|
||||
|
||||
enum eAlign {
|
||||
eAlign_top,
|
||||
eAlign_bottom,
|
||||
eAlign_center,
|
||||
eAlign_baseline,
|
||||
eAlign_axis
|
||||
};
|
||||
|
||||
static void
|
||||
ParseAlignAttribute(nsString& aValue, eAlign& aAlign, PRInt32& aRowIndex)
|
||||
{
|
||||
// by default, the table is centered about the axis
|
||||
aRowIndex = 0;
|
||||
aAlign = eAlign_axis;
|
||||
PRInt32 len = 0;
|
||||
if (0 == aValue.Find("top")) {
|
||||
len = 3; // 3 is the length of 'top'
|
||||
aAlign = eAlign_top;
|
||||
}
|
||||
if (columnalign) {
|
||||
value.Assign(columnalign);
|
||||
aCellContent->SetAttr(kNameSpaceID_None, nsMathMLAtoms::columnalign_,
|
||||
value, PR_FALSE);
|
||||
else if (0 == aValue.Find("bottom")) {
|
||||
len = 6; // 6 is the length of 'bottom'
|
||||
aAlign = eAlign_bottom;
|
||||
}
|
||||
// then, re-resolve the style contexts in our subtree
|
||||
if (rowalign || columnalign) {
|
||||
nsCOMPtr<nsIStyleContext> parentContext;
|
||||
nsCOMPtr<nsIStyleContext> newContext;
|
||||
rowFrame->GetStyleContext(getter_AddRefs(parentContext));
|
||||
aPresContext->ResolveStyleContextFor(aCellContent, parentContext,
|
||||
PR_FALSE, getter_AddRefs(newContext));
|
||||
nsCOMPtr<nsIStyleContext> oldContext;
|
||||
aCellFrame->GetStyleContext(getter_AddRefs(oldContext));
|
||||
if (oldContext != newContext) {
|
||||
aCellFrame->SetStyleContext(aPresContext, newContext);
|
||||
aPresContext->ReParentStyleContext(aCellInnerFrame, newContext);
|
||||
}
|
||||
else if (0 == aValue.Find("center")) {
|
||||
len = 6; // 6 is the length of 'center'
|
||||
aAlign = eAlign_center;
|
||||
}
|
||||
else if (0 == aValue.Find("baseline")) {
|
||||
len = 8; // 8 is the length of 'baseline'
|
||||
aAlign = eAlign_baseline;
|
||||
}
|
||||
else if (0 == aValue.Find("axis")) {
|
||||
len = 4; // 4 is the length of 'axis'
|
||||
aAlign = eAlign_axis;
|
||||
}
|
||||
if (len) {
|
||||
PRInt32 error;
|
||||
aValue.Cut(0, len); // aValue is not a const here
|
||||
aRowIndex = aValue.ToInteger(&error);
|
||||
if (error)
|
||||
aRowIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -262,7 +373,6 @@ NS_NewMathMLmtableOuterFrame (nsIPresShell* aPresShell, nsIFrame** aNewFrame)
|
|||
|
||||
*aNewFrame = it;
|
||||
return NS_OK;
|
||||
|
||||
}
|
||||
|
||||
nsMathMLmtableOuterFrame::nsMathMLmtableOuterFrame()
|
||||
|
@ -303,6 +413,40 @@ nsMathMLmtableOuterFrame::Init(nsIPresContext* aPresContext,
|
|||
return rv;
|
||||
}
|
||||
|
||||
nsIFrame*
|
||||
nsMathMLmtableOuterFrame::GetRowFrameAt(nsIPresContext* aPresContext,
|
||||
PRInt32 aRowIndex)
|
||||
{
|
||||
// To find the row at the given index, we will iterate downwards or
|
||||
// upwards depending on the sign of the index
|
||||
nsTableIteration dir = eTableLTR;
|
||||
if (aRowIndex < 0) {
|
||||
aRowIndex = -aRowIndex;
|
||||
dir = eTableRTL;
|
||||
}
|
||||
// if our inner table says that the index is valid, find the row now
|
||||
PRInt32 rowCount, colCount;
|
||||
GetTableSize(rowCount, colCount);
|
||||
if (aRowIndex <= rowCount) {
|
||||
nsIFrame* innerTableFrame = mFrames.FirstChild();
|
||||
nsTableIterator rowgroupIter(aPresContext, *innerTableFrame, dir);
|
||||
nsIFrame* rowgroupFrame = rowgroupIter.First();
|
||||
while (rowgroupFrame) {
|
||||
nsTableIterator rowIter(aPresContext, *rowgroupFrame, dir);
|
||||
nsIFrame* rowFrame = rowIter.First();
|
||||
while (rowFrame) {
|
||||
if (--aRowIndex == 0) {
|
||||
DEBUG_VERIFY_THAT_FRAME_IS(rowFrame, TABLE_ROW);
|
||||
return rowFrame;
|
||||
}
|
||||
rowFrame = rowIter.Next();
|
||||
}
|
||||
rowgroupFrame = rowgroupIter.Next();
|
||||
}
|
||||
}
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMathMLmtableOuterFrame::Reflow(nsIPresContext* aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
|
@ -310,7 +454,8 @@ nsMathMLmtableOuterFrame::Reflow(nsIPresContext* aPresContext,
|
|||
nsReflowStatus& aStatus)
|
||||
{
|
||||
nsresult rv;
|
||||
// we want to return a table that is centered according to the align attribute
|
||||
nsAutoString value;
|
||||
// we want to return a table that is anchored according to the align attribute
|
||||
|
||||
nsHTMLReflowState reflowState(aReflowState);
|
||||
if ((NS_FRAME_FIRST_REFLOW & mState) &&
|
||||
|
@ -320,9 +465,7 @@ nsMathMLmtableOuterFrame::Reflow(nsIPresContext* aPresContext,
|
|||
// size is unconstrained. Skipping the Pass2 messes the MathML vertical
|
||||
// alignments that are resolved during the reflow of cell frames.
|
||||
|
||||
nscoord oldAvailableWidth = reflowState.availableWidth;
|
||||
nscoord oldComputedWidth = reflowState.mComputedWidth;
|
||||
|
||||
reflowState.availableWidth = NS_UNCONSTRAINEDSIZE;
|
||||
reflowState.mComputedWidth = NS_UNCONSTRAINEDSIZE;
|
||||
reflowState.reason = eReflowReason_Initial;
|
||||
|
@ -346,43 +489,84 @@ nsMathMLmtableOuterFrame::Reflow(nsIPresContext* aPresContext,
|
|||
|
||||
// see if the user has set the align attribute on the <mtable>
|
||||
// XXX should we also check <mstyle> ?
|
||||
nsAutoString value;
|
||||
PRBool alignAttribute = PR_FALSE;
|
||||
|
||||
PRInt32 rowIndex = 0;
|
||||
eAlign tableAlign = eAlign_axis;
|
||||
if (NS_CONTENT_ATTR_HAS_VALUE ==
|
||||
GetAttribute(mContent, nsnull, nsMathMLAtoms::align_, value)) {
|
||||
if (value.Equals(NS_LITERAL_STRING("top"))) {
|
||||
aDesiredSize.ascent = 0;
|
||||
aDesiredSize.descent = aDesiredSize.height;
|
||||
alignAttribute = PR_TRUE;
|
||||
}
|
||||
else if (value.Equals(NS_LITERAL_STRING("bottom"))) {
|
||||
aDesiredSize.ascent = aDesiredSize.height;
|
||||
aDesiredSize.descent = 0;
|
||||
alignAttribute = PR_TRUE;
|
||||
}
|
||||
else if (value.Equals(NS_LITERAL_STRING("center")) ||
|
||||
value.Equals(NS_LITERAL_STRING("baseline"))) {
|
||||
aDesiredSize.ascent = aDesiredSize.height/2;
|
||||
aDesiredSize.descent = aDesiredSize.height - aDesiredSize.ascent;
|
||||
alignAttribute = PR_TRUE;
|
||||
ParseAlignAttribute(value, tableAlign, rowIndex);
|
||||
}
|
||||
|
||||
// adjustments if there is a specified row from where to anchor the table
|
||||
// (conceptually: when there is no row of reference, picture the table as if
|
||||
// it is wrapped in a single big fictional row at dy = 0, this way of
|
||||
// doing so allows us to have a single code path for all cases).
|
||||
nscoord dy = 0;
|
||||
nscoord height = aDesiredSize.height;
|
||||
nsIFrame* rowFrame = nsnull;
|
||||
if (rowIndex) {
|
||||
rowFrame = GetRowFrameAt(aPresContext, rowIndex);
|
||||
if (rowFrame) {
|
||||
// translate the coordinates to be relative to us
|
||||
nsRect rect;
|
||||
nsIFrame* frame = rowFrame;
|
||||
frame->GetRect(rect);
|
||||
height = rect.height;
|
||||
do {
|
||||
dy += rect.y;
|
||||
frame->GetParent(&frame);
|
||||
frame->GetRect(rect);
|
||||
} while (frame != this);
|
||||
}
|
||||
}
|
||||
if (!alignAttribute) {
|
||||
// by default, center about the axis
|
||||
|
||||
const nsStyleFont *font = NS_STATIC_CAST(const nsStyleFont*,
|
||||
mStyleContext->GetStyleData(eStyleStruct_Font));
|
||||
aReflowState.rendContext->SetFont(font->mFont);
|
||||
nsCOMPtr<nsIFontMetrics> fm;
|
||||
aReflowState.rendContext->GetFontMetrics(*getter_AddRefs(fm));
|
||||
|
||||
nscoord axisHeight;
|
||||
GetAxisHeight(*aReflowState.rendContext, fm, axisHeight);
|
||||
|
||||
aDesiredSize.ascent = aDesiredSize.height/2 + axisHeight;
|
||||
aDesiredSize.descent = aDesiredSize.height - aDesiredSize.ascent;
|
||||
switch (tableAlign) {
|
||||
case eAlign_top:
|
||||
aDesiredSize.ascent = dy;
|
||||
break;
|
||||
case eAlign_bottom:
|
||||
aDesiredSize.ascent = dy + height;
|
||||
break;
|
||||
case eAlign_center:
|
||||
aDesiredSize.ascent = dy + height/2;
|
||||
break;
|
||||
case eAlign_baseline:
|
||||
if (rowFrame) {
|
||||
// anchor the table on the baseline of the row of reference
|
||||
nscoord rowAscent = ((nsTableRowFrame*)rowFrame)->GetMaxCellAscent();
|
||||
if (rowAscent) { // the row has at least one cell with 'vertical-align: baseline'
|
||||
aDesiredSize.ascent = dy + rowAscent;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// in other situations, fallback to center
|
||||
aDesiredSize.ascent = dy + height/2;
|
||||
break;
|
||||
case eAlign_axis:
|
||||
default: {
|
||||
// XXX should instead use style data from the row of reference here ?
|
||||
const nsStyleFont* font;
|
||||
GetStyleData(eStyleStruct_Font, (const nsStyleStruct *&)font);
|
||||
aReflowState.rendContext->SetFont(font->mFont);
|
||||
nsCOMPtr<nsIFontMetrics> fm;
|
||||
aReflowState.rendContext->GetFontMetrics(*getter_AddRefs(fm));
|
||||
nscoord axisHeight;
|
||||
GetAxisHeight(*aReflowState.rendContext, fm, axisHeight);
|
||||
if (rowFrame) {
|
||||
// anchor the axis of the table on the axis of the row of reference
|
||||
// XXX fallback to baseline because it is a hard problem
|
||||
nscoord rowAscent = ((nsTableRowFrame*)rowFrame)->GetMaxCellAscent();
|
||||
if (rowAscent) { // the row has at least one cell with 'vertical-align: baseline'
|
||||
aDesiredSize.ascent = dy + rowAscent;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// in other situations, fallback to using half of the height
|
||||
aDesiredSize.ascent = dy + height/2 + axisHeight;
|
||||
}
|
||||
}
|
||||
aDesiredSize.descent = aDesiredSize.height - aDesiredSize.ascent;
|
||||
|
||||
mReference.x = 0;
|
||||
mReference.y = aDesiredSize.ascent;
|
||||
|
||||
// just make-up a bounding metrics
|
||||
mBoundingMetrics.Clear();
|
||||
|
@ -397,6 +581,65 @@ nsMathMLmtableOuterFrame::Reflow(nsIPresContext* aPresContext,
|
|||
return rv;
|
||||
}
|
||||
|
||||
// --------
|
||||
// implementation of nsMathMLmtdFrame
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(nsMathMLmtdFrame, nsTableCellFrame)
|
||||
NS_IMPL_RELEASE_INHERITED(nsMathMLmtdFrame, nsTableCellFrame)
|
||||
NS_IMPL_QUERY_INTERFACE_INHERITED0(nsMathMLmtdFrame, nsTableCellFrame)
|
||||
|
||||
nsresult
|
||||
NS_NewMathMLmtdFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
|
||||
{
|
||||
NS_PRECONDITION(aNewFrame, "null OUT ptr");
|
||||
if (nsnull == aNewFrame) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
nsMathMLmtdFrame* it = new (aPresShell) nsMathMLmtdFrame;
|
||||
if (nsnull == it) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
*aNewFrame = it;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsMathMLmtdFrame::nsMathMLmtdFrame()
|
||||
{
|
||||
}
|
||||
|
||||
nsMathMLmtdFrame::~nsMathMLmtdFrame()
|
||||
{
|
||||
}
|
||||
|
||||
PRInt32
|
||||
nsMathMLmtdFrame::GetRowSpan()
|
||||
{
|
||||
PRInt32 rowspan = 1;
|
||||
nsAutoString value;
|
||||
if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttr(kNameSpaceID_None,
|
||||
nsMathMLAtoms::rowspan_, value)) {
|
||||
PRInt32 error;
|
||||
rowspan = value.ToInteger(&error);
|
||||
if (error)
|
||||
rowspan = 1;
|
||||
}
|
||||
return rowspan;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
nsMathMLmtdFrame::GetColSpan()
|
||||
{
|
||||
PRInt32 colspan = 1;
|
||||
nsAutoString value;
|
||||
if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttr(kNameSpaceID_None,
|
||||
nsMathMLAtoms::columnspan_, value)) {
|
||||
PRInt32 error;
|
||||
colspan = value.ToInteger(&error);
|
||||
if (error)
|
||||
colspan = 1;
|
||||
}
|
||||
return colspan;
|
||||
}
|
||||
|
||||
// --------
|
||||
// implementation of nsMathMLmtdInnerFrame
|
||||
|
@ -455,7 +698,7 @@ nsMathMLmtdInnerFrame::Reflow(nsIPresContext* aPresContext,
|
|||
{
|
||||
// Map attributes to style (hopefully, bug 69409 will eventually help here).
|
||||
if (NS_FRAME_FIRST_REFLOW & mState) {
|
||||
MapAlignAttributesInto(aPresContext, mContent, mParent, this);
|
||||
MapAttributesInto(aPresContext, mContent, mParent, this);
|
||||
}
|
||||
|
||||
// Let the base class do the reflow
|
||||
|
|
|
@ -78,8 +78,32 @@ public:
|
|||
protected:
|
||||
nsMathMLmtableOuterFrame();
|
||||
virtual ~nsMathMLmtableOuterFrame();
|
||||
|
||||
// helper to find the row frame at a given index, positive or negative, e.g.,
|
||||
// 1..n means the first row down to the last row, -1..-n means the last row
|
||||
// up to the first row. Used for alignments that are relative to a given row
|
||||
nsIFrame*
|
||||
GetRowFrameAt(nsIPresContext* aPresContext,
|
||||
PRInt32 aRowIndex);
|
||||
}; // class nsMathMLmtableOuterFrame
|
||||
|
||||
// --------------
|
||||
|
||||
class nsMathMLmtdFrame : public nsTableCellFrame
|
||||
{
|
||||
public:
|
||||
friend nsresult NS_NewMathMLmtdFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame);
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// overloaded nsTableCellFrame methods
|
||||
virtual PRInt32 GetRowSpan();
|
||||
virtual PRInt32 GetColSpan();
|
||||
|
||||
protected:
|
||||
nsMathMLmtdFrame();
|
||||
virtual ~nsMathMLmtdFrame();
|
||||
}; // class nsMathMLmtdFrame
|
||||
|
||||
// --------------
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ math {
|
|||
display: inline;
|
||||
font-size: inherit;
|
||||
font-style: normal;
|
||||
font-family: CMSY10, CMEX10, Symbol, Times, Lucida Sans Unicode, MT Extra, Math1, Math2, Math3, Math4, Math5, serif;
|
||||
font-family: CMSY10, Symbol, Times, Lucida Sans Unicode, MT Extra, Math1, Math2, Math3, Math4, Math5, serif;
|
||||
}
|
||||
|
||||
math[mode="inline"], math[display="inline"] {
|
||||
|
@ -137,46 +137,40 @@ merror {
|
|||
/* mtable and its related tags */
|
||||
/*******************************************************/
|
||||
|
||||
:-moz-math-table, mtable {
|
||||
mtable {
|
||||
display: table;
|
||||
text-align: -moz-center;
|
||||
border-spacing: 0.8em 1.0ex; /* horizontal vertical */
|
||||
border-collapse: separate; /* 'collapse' is blocked by bug 49490 */
|
||||
margin-left: -0.4em;
|
||||
margin-right: -0.8em;
|
||||
margin-top: -1.0ex;
|
||||
margin-bottom: -1.0ex;
|
||||
/* margin: 0.5ex 0.4em 0.5ex 0.4em; top right bottom left */
|
||||
-moz-box-sizing: border-box;
|
||||
/* -moz-box-sizing: content-box; */
|
||||
}
|
||||
mtable[frame="none"] {
|
||||
border: none;
|
||||
}
|
||||
mtable[frame="solid"] {
|
||||
border: solid thin;
|
||||
}
|
||||
mtable[frame="dashed"] {
|
||||
border: dashed thin;
|
||||
}
|
||||
|
||||
mtr {
|
||||
display: table-row;
|
||||
text-align: inherit;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
/* must never set padding in td, th */
|
||||
|
||||
mtd {
|
||||
display: table-cell;
|
||||
text-align: inherit;
|
||||
vertical-align: inherit;
|
||||
vertical-align: baseline;
|
||||
text-align: -moz-center;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
|
||||
/***********************/
|
||||
/* -- mtd: columnalign */
|
||||
|
||||
mtd[columnalign="left"] {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
mtd[columnalign="right"] {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
mtd[columnalign="center"] {
|
||||
text-align: -moz-center;
|
||||
}
|
||||
|
@ -187,25 +181,89 @@ mtd[columnalign="center"] {
|
|||
mtd[rowalign="top"] {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
mtd[rowalign="bottom"] {
|
||||
vertical-align: bottom;
|
||||
}
|
||||
|
||||
mtd[rowalign="center"] {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
mtd[rowalign="baseline"] {
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
/* -- not yet supported --
|
||||
mtd[rowalign="axis"] {
|
||||
vertical-align: mathline;
|
||||
}
|
||||
*/
|
||||
|
||||
/**********************************************************************/
|
||||
/* rules to achieve the default spacing between cells. 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> */
|
||||
mtd {
|
||||
padding-right: 0.4em; /* half of columnspacing[colindex] */
|
||||
padding-left: 0.4em; /* half of columnspacing[colindex-1] */
|
||||
padding-bottom: 0.5ex; /* half of rowspacing[rowindex] */
|
||||
padding-top: 0.5ex; /* half of rowspacing[rowindex-1] */
|
||||
}
|
||||
/* turn off the spacing at the periphery of boundary cells */
|
||||
mtd[-moz-math-firstrow="true"] {
|
||||
padding-top: 0ex;
|
||||
}
|
||||
mtd[-moz-math-lastrow="true"] {
|
||||
padding-bottom: 0em;
|
||||
}
|
||||
mtd[-moz-math-firstcolumn="true"] {
|
||||
padding-left: 0ex;
|
||||
}
|
||||
mtd[-moz-math-lastcolumn="true"] {
|
||||
padding-right: 0em;
|
||||
}
|
||||
/* re-instate the spacing if the table has a surrounding frame */
|
||||
mtable[frame="solid"] > mtr > mtd[-moz-math-firstrow="true"],
|
||||
mtable[frame="dashed"] > mtr > mtd[-moz-math-firstrow="true"] {
|
||||
padding-top: 0.5ex; /* framespacing.top */
|
||||
}
|
||||
mtable[frame="solid"] > mtr > mtd[-moz-math-lastrow="true"],
|
||||
mtable[frame="dashed"] > mtr > mtd[-moz-math-lastrow="true"] {
|
||||
padding-bottom: 0.5ex; /* framespacing.bottom */
|
||||
}
|
||||
mtable[frame="solid"] > mtr > mtd[-moz-math-firstcolumn="true"],
|
||||
mtable[frame="dashed"] > mtr > mtd[-moz-math-firstcolumn="true"] {
|
||||
padding-left: 0.4em; /* framespacing.left */
|
||||
}
|
||||
mtable[frame="solid"] > mtr > mtd[-moz-math-lastcolumn="true"],
|
||||
mtable[frame="dashed"] > mtr > mtd[-moz-math-lastcolumn="true"] {
|
||||
padding-right: 0.4em; /* framespacing.right */
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
/* internal settings to support 'rowlines' and 'columnlines'. To
|
||||
achieve the recommended behavior, the back-end code will avoid setting
|
||||
unsuitable rules on the cells on the first row and the the first column.
|
||||
In general, however, authors can use the 'border' property of CSS to
|
||||
achieve varying effects down to the level of the table cell. */
|
||||
mtd[-moz-math-rowline="none"] {
|
||||
border-top: none;
|
||||
}
|
||||
mtd[-moz-math-rowline="solid"] {
|
||||
border-top: solid thin;
|
||||
}
|
||||
mtd[-moz-math-rowline="dashed"] {
|
||||
border-top: dashed thin;
|
||||
}
|
||||
mtd[-moz-math-columnline="none"] {
|
||||
border-left: none;
|
||||
}
|
||||
mtd[-moz-math-columnline="solid"] {
|
||||
border-left: solid thin;
|
||||
}
|
||||
mtd[-moz-math-columnline="dashed"] {
|
||||
border-left: dashed thin;
|
||||
}
|
||||
|
||||
/*******************************************************/
|
||||
/* style switching during frame construction */
|
||||
/*******************************************************/
|
||||
|
|
|
@ -42,8 +42,13 @@ MATHML_ATOM(fontsize, "-moz-math-font-size") // different from fontsize_
|
|||
MATHML_ATOM(fontstyle, "-moz-math-font-style") // different from fontstyle_
|
||||
MATHML_ATOM(fontstyle_stretchy, ":-moz-math-font-style-stretchy")
|
||||
MATHML_ATOM(fontstyle_anonymous, ":-moz-math-font-style-anonymous")
|
||||
MATHML_ATOM(rowline, "-moz-math-rowline") // different from rowlines_
|
||||
MATHML_ATOM(columnline, "-moz-math-columnline") // different from columnlines_
|
||||
MATHML_ATOM(firstrow, "-moz-math-firstrow")
|
||||
MATHML_ATOM(lastrow, "-moz-math-lastrow")
|
||||
MATHML_ATOM(firstcolumn, "-moz-math-firstcolumn")
|
||||
MATHML_ATOM(lastcolumn, "-moz-math-lastcolumn")
|
||||
MATHML_ATOM(mozMathInline, ":-moz-math-inline")
|
||||
MATHML_ATOM(mozMathTable, ":-moz-math-table")
|
||||
|
||||
// Alphabetical list of MathML frame types
|
||||
MATHML_ATOM(ordinaryMathMLFrame, "OrdinaryMathMLFrame")
|
||||
|
@ -74,6 +79,7 @@ MATHML_ATOM(color_, "color")
|
|||
MATHML_ATOM(columnalign_, "columnalign")
|
||||
MATHML_ATOM(columnlines_, "columnlines")
|
||||
MATHML_ATOM(columnspacing_, "columnspacing")
|
||||
MATHML_ATOM(columnspan_, "columnspan")
|
||||
MATHML_ATOM(columnwidth_, "columnwidth")
|
||||
MATHML_ATOM(compose_, "compose")
|
||||
MATHML_ATOM(condition_, "condition")
|
||||
|
@ -206,6 +212,7 @@ MATHML_ATOM(root_, "root")
|
|||
MATHML_ATOM(rowalign_, "rowalign")
|
||||
MATHML_ATOM(rowlines_, "rowlines")
|
||||
MATHML_ATOM(rowspacing_, "rowspacing")
|
||||
MATHML_ATOM(rowspan_, "rowspan")
|
||||
MATHML_ATOM(rquote_, "rquote")
|
||||
MATHML_ATOM(rspace_, "rspace")
|
||||
MATHML_ATOM(scriptlevel_, "scriptlevel")
|
||||
|
|
Загрузка…
Ссылка в новой задаче