[not part of default build] * Added recursion to search an attribute all the way up into the <mstyle> hierarchy. * Added support for MathML 2.0 'namedspace' values like: thickmathspace, thinmathspace, verythinmathspace, verythinmathspace, veryverythinmathspace, ... * Added some placeholders for incremental reflows

git-svn-id: svn://10.0.0.236/trunk@70041 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
rbs%maths.uq.edu.au 2000-05-16 13:15:15 +00:00
parent 968dd1d4b3
commit ef6cbd27a0
6 changed files with 255 additions and 32 deletions

View File

@ -24,7 +24,6 @@
struct nsPresentationData;
struct nsEmbellishData;
struct nsStretchMetrics;
typedef PRInt32 nsStretchDirection;
#define NS_STRETCH_DIRECTION_UNSUPPORTED -1
@ -94,7 +93,7 @@ public:
NS_IMETHOD
GetDesiredStretchSize(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
nsStretchMetrics& aDesiredStretchSize) = 0;
nsBoundingMetrics& aDesiredStretchSize) = 0;
#endif
/* Place :
* This method is used before returning from Reflow(), or when a MathML frame

View File

@ -126,7 +126,7 @@ nsMathMLContainerFrame::IsOnlyWhitespace(nsIFrame* aFrame)
return rv;
}
// helper to get an attribute from the content or the surrounding <mstyle>
// helper to get an attribute from the content or the surrounding <mstyle> hierarchy
nsresult
nsMathMLContainerFrame::GetAttribute(nsIContent* aContent,
nsIFrame* aMathMLmstyleFrame,
@ -136,16 +136,37 @@ nsMathMLContainerFrame::GetAttribute(nsIContent* aContent,
nsresult rv = NS_CONTENT_ATTR_NOT_THERE;
// see if we can get the attribute from the content
if (aContent) {
if (aContent)
{
rv = aContent->GetAttribute(kNameSpaceID_None, aAttributeAtom, aValue);
}
if (NS_CONTENT_ATTR_NOT_THERE == rv) {
if (NS_CONTENT_ATTR_NOT_THERE == rv)
{
// see if we can get the attribute from the mstyle frame
if (aMathMLmstyleFrame) {
if (aMathMLmstyleFrame)
{
nsCOMPtr<nsIContent> mstyleContent;
aMathMLmstyleFrame->GetContent(getter_AddRefs(mstyleContent));
rv = mstyleContent->GetAttribute(kNameSpaceID_None, aAttributeAtom, aValue);
aMathMLmstyleFrame->GetContent(getter_AddRefs(mstyleContent));
nsIFrame* mstyleParent;
aMathMLmstyleFrame->GetParent(&mstyleParent);
nsPresentationData mstyleParentData;
mstyleParentData.mstyle = nsnull;
if (mstyleParent)
{
nsIMathMLFrame* aMathMLFrame = nsnull;
rv = mstyleParent->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&aMathMLFrame);
if (NS_SUCCEEDED(rv) && nsnull != aMathMLFrame)
{
aMathMLFrame->GetPresentationData(mstyleParentData);
}
}
// recurse all the way up into the <mstyle> hierarchy
rv = GetAttribute(mstyleContent, mstyleParentData.mstyle, aAttributeAtom, aValue);
}
}
return rv;
@ -318,25 +339,25 @@ printf("String:%s, Number:%s, Unit:%s\n", s1, s2, s3);
nscoord
nsMathMLContainerFrame::CalcLength(nsIPresContext* aPresContext,
nsIStyleContext* aStyleContext,
const nsCSSValue& aValue)
const nsCSSValue& aCSSValue)
{
NS_ASSERTION(aValue.IsLengthUnit(), "not a length unit");
NS_ASSERTION(aCSSValue.IsLengthUnit(), "not a length unit");
if (aValue.IsFixedLengthUnit()) {
return aValue.GetLengthTwips();
if (aCSSValue.IsFixedLengthUnit()) {
return aCSSValue.GetLengthTwips();
}
nsCSSUnit unit = aValue.GetUnit();
nsCSSUnit unit = aCSSValue.GetUnit();
if (eCSSUnit_Pixel == unit) {
float p2t;
aPresContext->GetScaledPixelsToTwips(&p2t);
return NSFloatPixelsToTwips(aValue.GetFloatValue(), p2t);
return NSFloatPixelsToTwips(aCSSValue.GetFloatValue(), p2t);
}
else if (eCSSUnit_EM == unit) {
nsStyleFont font;
aStyleContext->GetStyle(eStyleStruct_Font, font);
return NSToCoordRound(aValue.GetFloatValue() * (float)font.mFont.size);
return NSToCoordRound(aCSSValue.GetFloatValue() * (float)font.mFont.size);
}
else if (eCSSUnit_XHeight == unit) {
nscoord xHeight;
@ -345,12 +366,86 @@ nsMathMLContainerFrame::CalcLength(nsIPresContext* aPresContext,
nsCOMPtr<nsIFontMetrics> fm;
aPresContext->GetMetricsFor(font.mFont, getter_AddRefs(fm));
fm->GetXHeight(xHeight);
return NSToCoordRound(aValue.GetFloatValue() * (float)xHeight);
return NSToCoordRound(aCSSValue.GetFloatValue() * (float)xHeight);
}
return 0;
}
PRBool
nsMathMLContainerFrame::ParseNamedSpaceValue(nsIFrame* aMathMLmstyleFrame,
nsString& aString,
nsCSSValue& aCSSValue)
{
aCSSValue.Reset();
aString.CompressWhitespace(); // aString is not a const in this code...
if (!aString.Length()) return PR_FALSE;
// See if it is one of the 'namedspace' (ranging 1/18em...7/18em)
PRInt32 i = 0;
nsIAtom* namedspaceAtom;
if (aString.EqualsWithConversion("veryverythinmathspace"))
{
i = 1;
namedspaceAtom = nsMathMLAtoms::veryverythinmathspace_;
}
else if (aString.EqualsWithConversion("verythinmathspace"))
{
i = 2;
namedspaceAtom = nsMathMLAtoms::verythinmathspace_;
}
else if (aString.EqualsWithConversion("thinmathspace"))
{
i = 3;
namedspaceAtom = nsMathMLAtoms::thinmathspace_;
}
else if (aString.EqualsWithConversion("mediummathspace"))
{
i = 4;
namedspaceAtom = nsMathMLAtoms::mediummathspace_;
}
else if (aString.EqualsWithConversion("thickmathspace"))
{
i = 5;
namedspaceAtom = nsMathMLAtoms::thickmathspace_;
}
else if (aString.EqualsWithConversion("verythickmathspace"))
{
i = 6;
namedspaceAtom = nsMathMLAtoms::verythickmathspace_;
}
else if (aString.EqualsWithConversion("veryverythickmathspace"))
{
i = 7;
namedspaceAtom = nsMathMLAtoms::veryverythickmathspace_;
}
if (0 != i)
{
if (aMathMLmstyleFrame)
{
// see if there is a <mstyle> that has overriden the default value
// GetAttribute() will recurse all the way up into the <mstyle> hierarchy
nsAutoString value;
if (NS_CONTENT_ATTR_HAS_VALUE ==
GetAttribute(nsnull, aMathMLmstyleFrame, namedspaceAtom, value))
{
if (ParseNumericValue(value, aCSSValue) &&
aCSSValue.IsLengthUnit())
{
return PR_TRUE;
}
}
}
// fall back to the default value
aCSSValue.SetFloatValue(float(i)/float(18), eCSSUnit_EM);
return PR_TRUE;
}
return PR_FALSE;
}
// -------------------------
// error handlers
// by default show the Unicode REPLACEMENT CHARACTER U+FFFD
@ -1253,6 +1348,26 @@ nsMathMLContainerFrame::ReflowTokenFor(nsIFrame* aFrame,
NS_PRECONDITION(aFrame, "null arg");
nsresult rv = NS_OK;
// See if this is an incremental reflow
if (aReflowState.reason == eReflowReason_Incremental) {
nsIFrame* targetFrame;
aReflowState.reflowCommand->GetTarget(targetFrame);
#ifdef MATHML_NOISY_INCREMENTAL_REFLOW
printf("nsMathMLContainerFrame::ReflowTokenFor:IncrementalReflow received by: ");
nsFrame::ListTag(stdout, aFrame);
printf("for target: ");
nsFrame::ListTag(stdout, targetFrame);
printf("\n");
#endif
if (aFrame == targetFrame) {
}
else {
// Remove the next frame from the reflow path
nsIFrame* nextFrame;
aReflowState.reflowCommand->GetNext(nextFrame);
}
}
// initializations needed for empty markup like <mtag></mtag>
aDesiredSize.width = aDesiredSize.height = 0;
aDesiredSize.ascent = aDesiredSize.descent = 0;
@ -1357,6 +1472,31 @@ nsMathMLContainerFrame::PlaceTokenFor(nsIFrame* aFrame,
return NS_OK;
}
// We are an inline frame, so we handle dirty request like nsInlineFrame
NS_IMETHODIMP
nsMathMLContainerFrame::ReflowDirtyChild(nsIPresShell* aPresShell, nsIFrame* aChild)
{
// The inline container frame does not handle the reflow
// request. It passes it up to its parent container.
// If you don't already have dirty children,
if (!(mState & NS_FRAME_HAS_DIRTY_CHILDREN)) {
if (mParent) {
// Record that you are dirty and have dirty children
mState |= NS_FRAME_IS_DIRTY;
mState |= NS_FRAME_HAS_DIRTY_CHILDREN;
// Pass the reflow request up to the parent
mParent->ReflowDirtyChild(aPresShell, (nsIFrame*) this);
}
else {
NS_ASSERTION(0, "No parent to pass the reflow request up to.");
}
}
return NS_OK;
}
NS_IMETHODIMP
nsMathMLContainerFrame::Reflow(nsIPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
@ -1368,6 +1508,29 @@ nsMathMLContainerFrame::Reflow(nsIPresContext* aPresContext,
aDesiredSize.ascent = aDesiredSize.descent = 0;
aDesiredSize.mBoundingMetrics.Clear();
// See if this is an incremental reflow
if (aReflowState.reason == eReflowReason_Incremental) {
nsIFrame* targetFrame;
aReflowState.reflowCommand->GetTarget(targetFrame);
#ifdef MATHML_NOISY_INCREMENTAL_REFLOW
printf("nsMathMLContainerFrame::Reflow:IncrementalReflow received by: ");
nsFrame::ListTag(stdout, this);
printf("for target: ");
nsFrame::ListTag(stdout, targetFrame);
printf("\n");
#endif
if (this == targetFrame) {
// XXX We are the target of the incremental reflow.
// Rather than reflowing everything, see if we can speedup things
// by just doing the minimal work needed to update ourselves
}
else {
// Remove the next frame from the reflow path
nsIFrame* nextFrame;
aReflowState.reflowCommand->GetNext(nextFrame);
}
}
/////////////
// Reflow children
// Asking each child to cache its bounding metrics
@ -1571,6 +1734,27 @@ nsMathMLWrapperFrame::Reflow(nsIPresContext* aPresContext,
nsresult rv = NS_OK;
aStatus = NS_FRAME_COMPLETE;
aDesiredSize.width = aDesiredSize.height = aDesiredSize.ascent = aDesiredSize.descent = 0;
// See if this is an incremental reflow
if (aReflowState.reason == eReflowReason_Incremental) {
nsIFrame* targetFrame;
aReflowState.reflowCommand->GetTarget(targetFrame);
#ifdef MATHML_NOISY_INCREMENTAL_REFLOW
printf("nsMathMLWrapperFrame::Reflow:IncrementalReflow received by: ");
nsFrame::ListTag(stdout, this);
printf("for target: ");
nsFrame::ListTag(stdout, targetFrame);
printf("\n");
#endif
if (this == targetFrame) {
}
else {
// Remove the next frame from the reflow path
nsIFrame* nextFrame;
aReflowState.reflowCommand->GetNext(nextFrame);
}
}
nsIFrame* childFrame = mFrames.FirstChild();
if (childFrame) {
nsReflowStatus childStatus;

View File

@ -423,7 +423,11 @@ nsMathMLmactionFrame::MouseClick(nsIDOMEvent* aMouseEvent)
mContent->SetAttribute(kNameSpaceID_None, nsMathMLAtoms::selection_, value, notify);
// Now trigger a content-changed reflow...
ContentChanged(mPresContext, mContent, nsnull);
// ContentChanged(mPresContext, mContent, nsnull);
nsCOMPtr<nsIPresShell> presShell;
mPresContext->GetShell(getter_AddRefs(presShell));
ReflowDirtyChild(presShell, mSelectedFrame);
}
}
else if (NS_MATHML_ACTION_TYPE_RESTYLE == mActionType)

View File

@ -472,11 +472,12 @@ nsMathMLmoFrame::InitData(nsIPresContext* aPresContext)
mStyleContext->GetStyle(eStyleStruct_Font, font);
float em = float(font.mFont.size);
// lspace = number h-unit
// lspace = number h-unit | namedspace
if (NS_CONTENT_ATTR_HAS_VALUE == GetAttribute(mContent, mPresentationData.mstyle,
nsMathMLAtoms::lspace_, value)) {
nsCSSValue cssValue;
if (ParseNumericValue(value, cssValue))
if (ParseNumericValue(value, cssValue) ||
ParseNamedSpaceValue(mPresentationData.mstyle, value, cssValue))
{
if ((eCSSUnit_Number == cssValue.GetUnit()) &&
(0.0f == cssValue.GetFloatValue()))
@ -489,11 +490,12 @@ nsMathMLmoFrame::InitData(nsIPresContext* aPresContext)
mLeftSpace = 0.0f;
}
// rspace = number h-unit
// rspace = number h-unit | namedspace
if (NS_CONTENT_ATTR_HAS_VALUE == GetAttribute(mContent, mPresentationData.mstyle,
nsMathMLAtoms::rspace_, value)) {
nsCSSValue cssValue;
if (ParseNumericValue(value, cssValue))
if (ParseNumericValue(value, cssValue) ||
ParseNamedSpaceValue(mPresentationData.mstyle, value, cssValue))
{
if ((eCSSUnit_Number == cssValue.GetUnit()) &&
(0.0f == cssValue.GetFloatValue()))
@ -506,11 +508,13 @@ nsMathMLmoFrame::InitData(nsIPresContext* aPresContext)
mRightSpace = 0.0f;
}
// minsize = number [ v-unit | h-unit ]
// minsize = number [ v-unit | h-unit ] | namedspace
if (NS_CONTENT_ATTR_HAS_VALUE == GetAttribute(mContent, mPresentationData.mstyle,
nsMathMLAtoms::minsize_, value)) {
nsCSSValue cssValue;
if (ParseNumericValue(value, cssValue)) {
if (ParseNumericValue(value, cssValue) ||
ParseNamedSpaceValue(mPresentationData.mstyle, value, cssValue))
{
nsCSSUnit unit = cssValue.GetUnit();
if (eCSSUnit_Number == unit)
mMinSize = cssValue.GetFloatValue();
@ -536,11 +540,13 @@ nsMathMLmoFrame::InitData(nsIPresContext* aPresContext)
}
}
// maxsize = number [ v-unit | h-unit ] | infinity
// maxsize = number [ v-unit | h-unit ] | namedspace | infinity
if (NS_CONTENT_ATTR_HAS_VALUE == GetAttribute(mContent, mPresentationData.mstyle,
nsMathMLAtoms::maxsize_, value)) {
nsCSSValue cssValue;
if (ParseNumericValue(value, cssValue)) {
if (ParseNumericValue(value, cssValue) ||
ParseNamedSpaceValue(mPresentationData.mstyle, value, cssValue))
{
nsCSSUnit unit = cssValue.GetUnit();
if (eCSSUnit_Number == unit)
mMaxSize = cssValue.GetFloatValue();

View File

@ -56,6 +56,7 @@
#define NS_MATHML_PSEUDO_UNIT_HEIGHT 3
#define NS_MATHML_PSEUDO_UNIT_DEPTH 4
#define NS_MATHML_PSEUDO_UNIT_LSPACE 5
#define NS_MATHML_PSEUDO_UNIT_NAMEDSPACE 6
nsresult
NS_NewMathMLmpaddedFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
@ -94,7 +95,7 @@ nsMathMLmpaddedFrame::Init(nsIPresContext* aPresContext,
/*
parse the attributes
width = [+|-] unsigned-number (% [pseudo-unit] | pseudo-unit | h-unit)
width = [+|-] unsigned-number (% [pseudo-unit] | pseudo-unit | h-unit | namedspace)
height= [+|-] unsigned-number (% [pseudo-unit] | pseudo-unit | v-unit)
depth = [+|-] unsigned-number (% [pseudo-unit] | pseudo-unit | v-unit)
lspace= [+|-] unsigned-number (% [pseudo-unit] | pseudo-unit | h-unit)
@ -234,13 +235,36 @@ nsMathMLmpaddedFrame::ParseAttribute(nsString& aString,
return PR_TRUE;
}
aString.Right(value, stringLength - i);
if (value.EqualsWithConversion("width")) aPseudoUnit = NS_MATHML_PSEUDO_UNIT_WIDTH;
if (value.EqualsWithConversion("width")) aPseudoUnit = NS_MATHML_PSEUDO_UNIT_WIDTH;
else if (value.EqualsWithConversion("height")) aPseudoUnit = NS_MATHML_PSEUDO_UNIT_HEIGHT;
else if (value.EqualsWithConversion("depth")) aPseudoUnit = NS_MATHML_PSEUDO_UNIT_DEPTH;
else if (value.EqualsWithConversion("lspace")) aPseudoUnit = NS_MATHML_PSEUDO_UNIT_LSPACE;
else // unexpected pseudo-unit
else
{
nsCSSValue aCSSNamedSpaceValue;
if (!aCSSValue.IsLengthUnit() &&
ParseNamedSpaceValue(nsnull, value, aCSSNamedSpaceValue))
{ // XXX nsnull in ParseNamedSpacedValue()? don't access mstyle?
aPseudoUnit = NS_MATHML_PSEUDO_UNIT_NAMEDSPACE;
float namedspace = aCSSNamedSpaceValue.GetFloatValue();
// combine aCSSNamedSpaceValue and aCSSValue since
// we know that the unit of aCSSNamedSpaceValue is 'em'
nsCSSUnit unit = aCSSValue.GetUnit();
if (eCSSUnit_Number == unit) {
float scaler = aCSSValue.GetFloatValue();
aCSSValue.SetFloatValue(scaler*namedspace, eCSSUnit_EM);
return PR_TRUE;
}
else if (eCSSUnit_Percent == unit) {
float scaler = aCSSValue.GetPercentValue();
aCSSValue.SetFloatValue(scaler*namedspace, eCSSUnit_EM);
return PR_TRUE;
}
}
// if we reach here, it means we encounter an unexpected pseudo-unit
aCSSValue.Reset();
aSign = NS_MATHML_SIGN_INVALID;
return PR_FALSE;

View File

@ -95,7 +95,9 @@ nsMathMLmspaceFrame::Init(nsIPresContext* aPresContext,
mWidth = 0;
if (NS_CONTENT_ATTR_HAS_VALUE == GetAttribute(mContent, mPresentationData.mstyle,
nsMathMLAtoms::width_, value)) {
if (ParseNumericValue(value, cssValue) && cssValue.IsLengthUnit()) {
if ((ParseNumericValue(value, cssValue) ||
ParseNamedSpaceValue(mPresentationData.mstyle, value, cssValue)) &&
cssValue.IsLengthUnit()) {
mWidth = CalcLength(aPresContext, mStyleContext, cssValue);
}
}
@ -104,7 +106,9 @@ nsMathMLmspaceFrame::Init(nsIPresContext* aPresContext,
mHeight = 0;
if (NS_CONTENT_ATTR_HAS_VALUE == GetAttribute(mContent, mPresentationData.mstyle,
nsMathMLAtoms::height_, value)) {
if (ParseNumericValue(value, cssValue) && cssValue.IsLengthUnit()) {
if ((ParseNumericValue(value, cssValue) ||
ParseNamedSpaceValue(mPresentationData.mstyle, value, cssValue)) &&
cssValue.IsLengthUnit()) {
mHeight = CalcLength(aPresContext, mStyleContext, cssValue);
}
}
@ -113,7 +117,9 @@ nsMathMLmspaceFrame::Init(nsIPresContext* aPresContext,
mDepth = 0;
if (NS_CONTENT_ATTR_HAS_VALUE == GetAttribute(mContent, mPresentationData.mstyle,
nsMathMLAtoms::depth_, value)) {
if (ParseNumericValue(value, cssValue) && cssValue.IsLengthUnit()) {
if ((ParseNumericValue(value, cssValue) ||
ParseNamedSpaceValue(mPresentationData.mstyle, value, cssValue)) &&
cssValue.IsLengthUnit()) {
mDepth = CalcLength(aPresContext, mStyleContext, cssValue);
}
}