diff --git a/layout/mathml/base/src/nsIMathMLFrame.h b/layout/mathml/base/src/nsIMathMLFrame.h index fa76b8d8da0..d5d75711b0b 100644 --- a/layout/mathml/base/src/nsIMathMLFrame.h +++ b/layout/mathml/base/src/nsIMathMLFrame.h @@ -205,9 +205,10 @@ public: * update some flags in the frame, leaving the other flags unchanged. */ NS_IMETHOD - UpdatePresentationData(PRInt32 aScriptLevelIncrement, - PRUint32 aFlagsValues, - PRUint32 aFlagsToUpdate) = 0; + UpdatePresentationData(nsIPresContext* aPresContext, + PRInt32 aScriptLevelIncrement, + PRUint32 aFlagsValues, + PRUint32 aFlagsToUpdate) = 0; /* UpdatePresentationDataFromChildAt : * Increments the scriplevel and sets the displaystyle and compression flags @@ -270,6 +271,10 @@ public: * ReResolveScriptStyle() will walk a subtree to cause this mathml-specific behavior * to happen. The method is recursive and only a top-level parent wishing to reflect * the changes in its children needs to call to the method. + * + * This function is *very* expensive. Unfortunately, there isn't much + * to do about it at the moment. For background on the problem @see + * http://groups.google.com/groups?selm=3A9192B5.D22B6C38%40maths.uq.edu.au */ NS_IMETHOD ReResolveScriptStyle(nsIPresContext* aPresContext, diff --git a/layout/mathml/base/src/nsMathMLContainerFrame.cpp b/layout/mathml/base/src/nsMathMLContainerFrame.cpp index 432973bb6bf..991c290ba96 100644 --- a/layout/mathml/base/src/nsMathMLContainerFrame.cpp +++ b/layout/mathml/base/src/nsMathMLContainerFrame.cpp @@ -42,6 +42,9 @@ #include "nsIDOMText.h" #include "nsITextContent.h" +#include "nsIFrameManager.h" +#include "nsStyleChangeList.h" + #include "nsMathMLAtoms.h" #include "nsMathMLParts.h" #include "nsMathMLChar.h" @@ -60,308 +63,33 @@ NS_IMPL_QUERY_INTERFACE_INHERITED1(nsMathMLContainerFrame, nsHTMLContainerFrame, // ============================================================================= -// helper to get an attribute from the content or the surrounding hierarchy -nsresult -nsMathMLContainerFrame::GetAttribute(nsIContent* aContent, - nsIFrame* aMathMLmstyleFrame, - nsIAtom* aAttributeAtom, - nsString& aValue) +// This is the method used to set the frame as an embellished container. +// It checks if the first (non-empty) child is embellished. Hence, calls +// must be bottom-up. The method must only be called from within frames who are +// entitled to be potential embellished operators as per the MathML REC. +NS_IMETHODIMP +nsMathMLContainerFrame::EmbellishOperator() { - nsresult rv = NS_CONTENT_ATTR_NOT_THERE; - - // see if we can get the attribute from the content - if (aContent) { - rv = aContent->GetAttr(kNameSpaceID_None, aAttributeAtom, aValue); + nsIFrame* firstChild = mFrames.FirstChild(); + if (firstChild && IsEmbellishOperator(firstChild)) { + // Cache the first child + mEmbellishData.flags |= NS_MATHML_EMBELLISH_OPERATOR; + mEmbellishData.firstChild = firstChild; + // Cache also the inner-most embellished frame at the core of the hierarchy + nsIMathMLFrame* mathMLFrame; + firstChild->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame); + nsEmbellishData embellishData; + mathMLFrame->GetEmbellishData(embellishData); + mEmbellishData.core = embellishData.core ? embellishData.core : firstChild; + mEmbellishData.direction = embellishData.direction; } - - if (NS_CONTENT_ATTR_NOT_THERE == rv) { - // see if we can get the attribute from the mstyle frame - if (aMathMLmstyleFrame) { - nsCOMPtr mstyleContent; - aMathMLmstyleFrame->GetContent(getter_AddRefs(mstyleContent)); - - nsIFrame* mstyleParent; - aMathMLmstyleFrame->GetParent(&mstyleParent); - - nsPresentationData mstyleParentData; - mstyleParentData.mstyle = nsnull; - - if (mstyleParent) { - nsIMathMLFrame* mathMLFrame; - rv = mstyleParent->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame); - if (NS_SUCCEEDED(rv) && mathMLFrame) { - mathMLFrame->GetPresentationData(mstyleParentData); - } - } - - // recurse all the way up into the hierarchy - rv = GetAttribute(mstyleContent, mstyleParentData.mstyle, aAttributeAtom, aValue); - } + else { + mEmbellishData.flags &= ~NS_MATHML_EMBELLISH_OPERATOR; + mEmbellishData.firstChild = nsnull; + mEmbellishData.core = nsnull; + mEmbellishData.direction = NS_STRETCH_DIRECTION_UNSUPPORTED; } - return rv; -} - -void -nsMathMLContainerFrame::GetRuleThickness(nsIRenderingContext& aRenderingContext, - nsIFontMetrics* aFontMetrics, - nscoord& aRuleThickness) -{ - // get the bounding metrics of the overbar char, the rendering context - // is assumed to have been set with the font of the current style context - nscoord xHeight; - aFontMetrics->GetXHeight(xHeight); - PRUnichar overBar = 0x00AF; - nsBoundingMetrics bm; - nsresult rv = aRenderingContext.GetBoundingMetrics(&overBar, PRUint32(1), bm); - if (NS_SUCCEEDED(rv)) { - aRuleThickness = bm.ascent + bm.descent; - } - if (NS_FAILED(rv) || aRuleThickness <= 0 || aRuleThickness >= xHeight) { - // fall-back to the other version - GetRuleThickness(aFontMetrics, aRuleThickness); - } - -#if 0 - nscoord oldRuleThickness; - GetRuleThickness(aFontMetrics, oldRuleThickness); - - PRUnichar sqrt = 0xE063; // a sqrt glyph from TeX's CMEX font - rv = aRenderingContext.GetBoundingMetrics(&sqrt, PRUint32(1), bm); - nscoord sqrtrule = bm.ascent; // according to TeX, the ascent should be the rule - - printf("xheight:%4d rule:%4d oldrule:%4d sqrtrule:%4d\n", - xHeight, aRuleThickness, oldRuleThickness, sqrtrule); -#endif -} - -void -nsMathMLContainerFrame::GetAxisHeight(nsIRenderingContext& aRenderingContext, - nsIFontMetrics* aFontMetrics, - nscoord& aAxisHeight) -{ - // get the bounding metrics of the minus sign, the rendering context - // is assumed to have been set with the font of the current style context - nscoord xHeight; - aFontMetrics->GetXHeight(xHeight); - PRUnichar minus = '-'; - nsBoundingMetrics bm; - nsresult rv = aRenderingContext.GetBoundingMetrics(&minus, PRUint32(1), bm); - if (NS_SUCCEEDED(rv)) { - aAxisHeight = bm.ascent - (bm.ascent + bm.descent)/2; - } - if (NS_FAILED(rv) || aAxisHeight <= 0 || aAxisHeight >= xHeight) { - // fall-back to the other version - GetAxisHeight(aFontMetrics, aAxisHeight); - } - -#if 0 - nscoord oldAxis; - GetAxisHeight(aFontMetrics, oldAxis); - - PRUnichar plus = '+'; - rv = aRenderingContext.GetBoundingMetrics(&plus, PRUint32(1), bm); - nscoord plusAxis = bm.ascent - (bm.ascent + bm.descent)/2;; - - printf("xheight:%4d Axis:%4d oldAxis:%4d plusAxis:%4d\n", - xHeight, aAxisHeight, oldAxis, plusAxis); -#endif -} - -// ================ -// Utilities for parsing and retrieving numeric values -// All returned values are in twips. - -/* -The REC says: - An explicit plus sign ('+') is not allowed as part of a numeric value - except when it is specifically listed in the syntax (as a quoted '+' or "+"), - - Units allowed - ID Description - em ems (font-relative unit traditionally used for horizontal lengths) - ex exs (font-relative unit traditionally used for vertical lengths) - px pixels, or pixel size of a "typical computer display" - in inches (1 inch = 2.54 centimeters) - cm centimeters - mm millimeters - pt points (1 point = 1/72 inch) - pc picas (1 pica = 12 points) - % percentage of default value - -Implementation here: - The numeric value is valid only if it is of the form nnn.nnn [h/v-unit] -*/ - -// Adapted from nsCSSScanner.cpp & CSSParser.cpp -PRBool -nsMathMLContainerFrame::ParseNumericValue(nsString& aString, - nsCSSValue& aCSSValue) -{ - aCSSValue.Reset(); - aString.CompressWhitespace(); // aString is not a const in this code... - - PRInt32 stringLength = aString.Length(); - - if (!stringLength) return PR_FALSE; - - nsAutoString number(aString); - number.SetLength(0); - - nsAutoString unit(aString); - unit.SetLength(0); - - // Gather up characters that make up the number - PRBool gotDot = PR_FALSE; - PRUnichar c; - for (PRInt32 i = 0; i < stringLength; i++) { - c = aString[i]; - if (gotDot && c == '.') - return PR_FALSE; // two dots encountered - else if (c == '.') - gotDot = PR_TRUE; - else if (!nsCRT::IsAsciiDigit(c)) { - aString.Right(unit, stringLength - i); - unit.CompressWhitespace(); // some authors leave blanks before the unit - break; - } - number.Append(c); - } - -#if 0 -char s1[50], s2[50], s3[50]; -aString.ToCString(s1, 50); -number.ToCString(s2, 50); -unit.ToCString(s3, 50); -printf("String:%s, Number:%s, Unit:%s\n", s1, s2, s3); -#endif - - // Convert number to floating point - PRInt32 errorCode; - float floatValue = number.ToFloat(&errorCode); - if (NS_FAILED(errorCode)) return PR_FALSE; - - nsCSSUnit cssUnit; - if (0 == unit.Length()) { - cssUnit = eCSSUnit_Number; // no explicit unit, this is a number that will act as a multiplier - } - else if (unit.Equals(NS_LITERAL_STRING("%"))) { - floatValue = floatValue / 100.0f; - aCSSValue.SetPercentValue(floatValue); - return PR_TRUE; - } - else if (unit.Equals(NS_LITERAL_STRING("em"))) cssUnit = eCSSUnit_EM; - else if (unit.Equals(NS_LITERAL_STRING("ex"))) cssUnit = eCSSUnit_XHeight; - else if (unit.Equals(NS_LITERAL_STRING("px"))) cssUnit = eCSSUnit_Pixel; - else if (unit.Equals(NS_LITERAL_STRING("in"))) cssUnit = eCSSUnit_Inch; - else if (unit.Equals(NS_LITERAL_STRING("cm"))) cssUnit = eCSSUnit_Centimeter; - else if (unit.Equals(NS_LITERAL_STRING("mm"))) cssUnit = eCSSUnit_Millimeter; - else if (unit.Equals(NS_LITERAL_STRING("pt"))) cssUnit = eCSSUnit_Point; - else if (unit.Equals(NS_LITERAL_STRING("pc"))) cssUnit = eCSSUnit_Pica; - else // unexpected unit - return PR_FALSE; - - aCSSValue.SetFloatValue(floatValue, cssUnit); - return PR_TRUE; -} - -// Adapted from nsCSSStyleRule.cpp -nscoord -nsMathMLContainerFrame::CalcLength(nsIPresContext* aPresContext, - nsIStyleContext* aStyleContext, - const nsCSSValue& aCSSValue) -{ - NS_ASSERTION(aCSSValue.IsLengthUnit(), "not a length unit"); - - if (aCSSValue.IsFixedLengthUnit()) { - return aCSSValue.GetLengthTwips(); - } - - nsCSSUnit unit = aCSSValue.GetUnit(); - - if (eCSSUnit_Pixel == unit) { - float p2t; - aPresContext->GetScaledPixelsToTwips(&p2t); - return NSFloatPixelsToTwips(aCSSValue.GetFloatValue(), p2t); - } - else if (eCSSUnit_EM == unit) { - const nsStyleFont *font = NS_STATIC_CAST(const nsStyleFont*, - aStyleContext->GetStyleData(eStyleStruct_Font)); - return NSToCoordRound(aCSSValue.GetFloatValue() * (float)font->mFont.size); - } - else if (eCSSUnit_XHeight == unit) { - nscoord xHeight; - const nsStyleFont *font = NS_STATIC_CAST(const nsStyleFont*, - aStyleContext->GetStyleData(eStyleStruct_Font)); - nsCOMPtr fm; - aPresContext->GetMetricsFor(font->mFont, getter_AddRefs(fm)); - fm->GetXHeight(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.Equals(NS_LITERAL_STRING("veryverythinmathspace"))) { - i = 1; - namedspaceAtom = nsMathMLAtoms::veryverythinmathspace_; - } - else if (aString.Equals(NS_LITERAL_STRING("verythinmathspace"))) { - i = 2; - namedspaceAtom = nsMathMLAtoms::verythinmathspace_; - } - else if (aString.Equals(NS_LITERAL_STRING("thinmathspace"))) { - i = 3; - namedspaceAtom = nsMathMLAtoms::thinmathspace_; - } - else if (aString.Equals(NS_LITERAL_STRING("mediummathspace"))) { - i = 4; - namedspaceAtom = nsMathMLAtoms::mediummathspace_; - } - else if (aString.Equals(NS_LITERAL_STRING("thickmathspace"))) { - i = 5; - namedspaceAtom = nsMathMLAtoms::thickmathspace_; - } - else if (aString.Equals(NS_LITERAL_STRING("verythickmathspace"))) { - i = 6; - namedspaceAtom = nsMathMLAtoms::verythickmathspace_; - } - else if (aString.Equals(NS_LITERAL_STRING("veryverythickmathspace"))) { - i = 7; - namedspaceAtom = nsMathMLAtoms::veryverythickmathspace_; - } - - if (0 != i) { - if (aMathMLmstyleFrame) { - // see if there is a that has overriden the default value - // GetAttribute() will recurse all the way up into the 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; + return NS_OK; } // ------------------------- @@ -809,47 +537,6 @@ nsMathMLContainerFrame::FinalizeReflow(nsIPresContext* aPresContext, return NS_OK; } -// This is the method used to set the frame as an embellished container. -// It checks if the first (non-empty) child is embellished. Hence, calls -// must be bottom-up. The method must only be called from within frames who are -// entitled to be potential embellished operators as per the MathML REC. -NS_IMETHODIMP -nsMathMLContainerFrame::EmbellishOperator() -{ - nsIFrame* firstChild = mFrames.FirstChild(); - if (firstChild && IsEmbellishOperator(firstChild)) { - // Cache the first child - mEmbellishData.flags |= NS_MATHML_EMBELLISH_OPERATOR; - mEmbellishData.firstChild = firstChild; - // Cache also the inner-most embellished frame at the core of the hierarchy - nsIMathMLFrame* mathMLFrame; - firstChild->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame); - nsEmbellishData embellishData; - mathMLFrame->GetEmbellishData(embellishData); - mEmbellishData.core = embellishData.core ? embellishData.core : firstChild; - mEmbellishData.direction = embellishData.direction; - } - else { - mEmbellishData.flags &= ~NS_MATHML_EMBELLISH_OPERATOR; - mEmbellishData.firstChild = nsnull; - mEmbellishData.core = nsnull; - mEmbellishData.direction = NS_STRETCH_DIRECTION_UNSUPPORTED; - } - return NS_OK; -} - -PRBool -nsMathMLContainerFrame::IsEmbellishOperator(nsIFrame* aFrame) -{ - NS_PRECONDITION(aFrame, "null arg"); - if (!aFrame) return PR_FALSE; - nsIMathMLFrame* mathMLFrame; - nsresult rv = aFrame->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame); - if (NS_FAILED(rv) || !mathMLFrame) return PR_FALSE; - nsEmbellishData embellishData; - mathMLFrame->GetEmbellishData(embellishData); - return NS_MATHML_IS_EMBELLISH_OPERATOR(embellishData.flags); -} /* ///////////// * nsIMathMLFrame - support methods for scripting elements (nested frames @@ -858,152 +545,145 @@ nsMathMLContainerFrame::IsEmbellishOperator(nsIFrame* aFrame) * ============================================================================= */ -NS_IMETHODIMP -nsMathMLContainerFrame::UpdatePresentationDataFromChildAt(nsIPresContext* aPresContext, - PRInt32 aFirstIndex, - PRInt32 aLastIndex, - PRInt32 aScriptLevelIncrement, - PRUint32 aFlagsValues, - PRUint32 aFlagsToUpdate) +// helper to let the update of presentation data pass through +// a subtree that may contain non-mathml container frames +/* static */ void +nsMathMLContainerFrame::PropagatePresentationDataFor(nsIPresContext* aPresContext, + nsIFrame* aFrame, + PRInt32 aScriptLevelIncrement, + PRUint32 aFlagsValues, + PRUint32 aFlagsToUpdate) { - PRInt32 index = 0; - nsIFrame* childFrame = mFrames.FirstChild(); + nsIMathMLFrame* mathMLFrame; + aFrame->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame); + if (mathMLFrame) { + // update + mathMLFrame->UpdatePresentationData(aPresContext, + aScriptLevelIncrement, aFlagsValues, aFlagsToUpdate); + } + // propagate down the subtrees + nsIFrame* childFrame; + aFrame->FirstChild(aPresContext, nsnull, &childFrame); while (childFrame) { - if ((index >= aFirstIndex) && - ((aLastIndex <= 0) || ((aLastIndex > 0) && (index <= aLastIndex)))) { - nsIMathMLFrame* mathMLFrame; - nsresult rv = childFrame->QueryInterface( - NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame); - if (NS_SUCCEEDED(rv) && mathMLFrame) { - // update - mathMLFrame->UpdatePresentationData( - aScriptLevelIncrement, aFlagsValues, aFlagsToUpdate); - // propagate down the subtrees - mathMLFrame->UpdatePresentationDataFromChildAt(aPresContext, 0, -1, - aScriptLevelIncrement, aFlagsValues, aFlagsToUpdate); - } - } - index++; + PropagatePresentationDataFor(aPresContext, childFrame, + aScriptLevelIncrement, aFlagsValues, aFlagsToUpdate); childFrame->GetNextSibling(&childFrame); } - return NS_OK; } -// Helper to give a style context suitable for doing the stretching of -// a MathMLChar. Frame classes that use this should ensure that the -// extra leaf style contexts given to the MathMLChars are acessible to -// the Style System via the Get/Set AdditionalStyleContext() APIs. -PRBool -nsMathMLContainerFrame::ResolveMathMLCharStyle(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIStyleContext* aParentStyleContext, - nsMathMLChar* aMathMLChar) +// helper to let the scriptstyle re-resolution pass through +// a subtree that may contain non-mathml container frames. +// This function is *very* expensive. Unfortunately, there isn't much +// to do about it at the moment. For background on the problem @see +// http://groups.google.com/groups?selm=3A9192B5.D22B6C38%40maths.uq.edu.au +/* static */ void +nsMathMLContainerFrame::PropagateScriptStyleFor(nsIPresContext* aPresContext, + nsIFrame* aFrame, + PRInt32 aParentScriptLevel) { - nsAutoString data; - aMathMLChar->GetData(data); - PRBool isStretchy = nsMathMLOperators::IsMutableOperator(data); - nsIAtom* fontAtom = (isStretchy) ? - nsMathMLAtoms::fontstyle_stretchy : - nsMathMLAtoms::fontstyle_anonymous; - nsCOMPtr newStyleContext; - nsresult rv = aPresContext->ResolvePseudoStyleContextFor(aContent, fontAtom, - aParentStyleContext, PR_FALSE, - getter_AddRefs(newStyleContext)); - if (NS_SUCCEEDED(rv) && newStyleContext) - aMathMLChar->SetStyleContext(newStyleContext); + nsIMathMLFrame* mathMLFrame; + aFrame->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame); + if (mathMLFrame) { + // we will re-resolve our style data based on our current scriptlevel + nsPresentationData presentationData; + mathMLFrame->GetPresentationData(presentationData); + PRInt32 gap = presentationData.scriptLevel - aParentScriptLevel; - return isStretchy; -} + // since we are a MathML frame, our current scriptlevel becomes + // the one to use when we will propagate the recursion + aParentScriptLevel = presentationData.scriptLevel; -NS_IMETHODIMP -nsMathMLContainerFrame::ReResolveScriptStyle(nsIPresContext* aPresContext, - nsIStyleContext* aParentContext, - PRInt32 aParentScriptLevel) -{ - PRInt32 gap = mPresentationData.scriptLevel - aParentScriptLevel; - if (gap) { - // By default scriptminsize=8pt and scriptsizemultiplier=0.71 - nscoord scriptminsize = NSIntPointsToTwips(NS_MATHML_SCRIPTMINSIZE); - float scriptsizemultiplier = NS_MATHML_SCRIPTSIZEMULTIPLIER; -#if 0 - // XXX Bug 44201 - // user-supplied scriptminsize and scriptsizemultiplier that are - // restricted to particular elements are not supported because our - // css rules are fixed in mathml.css and are applicable to all elements. + nsCOMPtr oldStyleContext; + aFrame->GetStyleContext(getter_AddRefs(oldStyleContext)); + nsCOMPtr parentContext(dont_AddRef(oldStyleContext->GetParent())); - // see if there is a scriptminsize attribute on a that wraps us - if (NS_CONTENT_ATTR_HAS_VALUE == - GetAttribute(nsnull, mPresentationData.mstyle, - nsMathMLAtoms::scriptminsize_, fontsize)) { - nsCSSValue cssValue; - if (ParseNumericValue(fontsize, cssValue)) { - nsCSSUnit unit = cssValue.GetUnit(); - if (eCSSUnit_Number == unit) - scriptminsize = nscoord(float(scriptminsize) * cssValue.GetFloatValue()); - else if (eCSSUnit_Percent == unit) - scriptminsize = nscoord(float(scriptminsize) * cssValue.GetPercentValue()); - else if (eCSSUnit_Null != unit) - scriptminsize = CalcLength(aPresContext, mStyleContext, cssValue); - } + nsCOMPtr content; + aFrame->GetContent(getter_AddRefs(content)); + if (0 == gap) { + // unset any -moz-math-font-size attribute without notifying that we want a reflow + content->UnsetAttr(kNameSpaceID_None, nsMathMLAtoms::fontsize, PR_FALSE); } + else { + // By default scriptminsize=8pt and scriptsizemultiplier=0.71 + nscoord scriptminsize = NSIntPointsToTwips(NS_MATHML_SCRIPTMINSIZE); + float scriptsizemultiplier = NS_MATHML_SCRIPTSIZEMULTIPLIER; +#if 0 + // XXX Bug 44201 + // user-supplied scriptminsize and scriptsizemultiplier that are + // restricted to particular elements are not supported because our + // css rules are fixed in mathml.css and are applicable to all elements. + + // see if there is a scriptminsize attribute on a that wraps us + if (NS_CONTENT_ATTR_HAS_VALUE == + GetAttribute(nsnull, presentationData.mstyle, + nsMathMLAtoms::scriptminsize_, fontsize)) { + nsCSSValue cssValue; + if (ParseNumericValue(fontsize, cssValue)) { + nsCSSUnit unit = cssValue.GetUnit(); + if (eCSSUnit_Number == unit) + scriptminsize = nscoord(float(scriptminsize) * cssValue.GetFloatValue()); + else if (eCSSUnit_Percent == unit) + scriptminsize = nscoord(float(scriptminsize) * cssValue.GetPercentValue()); + else if (eCSSUnit_Null != unit) + scriptminsize = CalcLength(aPresContext, mStyleContext, cssValue); + } + } #endif - // get the incremental factor - nsAutoString fontsize; - if (0 > gap) { // the size is going to be increased - if (gap < NS_MATHML_CSS_NEGATIVE_SCRIPTLEVEL_LIMIT) - gap = NS_MATHML_CSS_NEGATIVE_SCRIPTLEVEL_LIMIT; - gap = -gap; - scriptsizemultiplier = 1.0f / scriptsizemultiplier; - fontsize.Assign(NS_LITERAL_STRING("-")); - } - else { // the size is going to be decreased - if (gap > NS_MATHML_CSS_POSITIVE_SCRIPTLEVEL_LIMIT) - gap = NS_MATHML_CSS_POSITIVE_SCRIPTLEVEL_LIMIT; - fontsize.Assign(NS_LITERAL_STRING("+")); - } - fontsize.AppendInt(gap, 10); - // we want to make sure that the size will stay readable - const nsStyleFont *font = NS_STATIC_CAST(const nsStyleFont*, - aParentContext->GetStyleData(eStyleStruct_Font)); - nscoord newFontSize = font->mFont.size; - while (0 < gap--) { - newFontSize = (nscoord)((float)(newFontSize) * scriptsizemultiplier); - } - if (newFontSize <= scriptminsize) { - fontsize.Assign(NS_LITERAL_STRING("scriptminsize")); + // figure out the incremental factor + nsAutoString fontsize; + if (0 > gap) { // the size is going to be increased + if (gap < NS_MATHML_CSS_NEGATIVE_SCRIPTLEVEL_LIMIT) + gap = NS_MATHML_CSS_NEGATIVE_SCRIPTLEVEL_LIMIT; + gap = -gap; + scriptsizemultiplier = 1.0f / scriptsizemultiplier; + fontsize.Assign(NS_LITERAL_STRING("-")); + } + else { // the size is going to be decreased + if (gap > NS_MATHML_CSS_POSITIVE_SCRIPTLEVEL_LIMIT) + gap = NS_MATHML_CSS_POSITIVE_SCRIPTLEVEL_LIMIT; + fontsize.Assign(NS_LITERAL_STRING("+")); + } + fontsize.AppendInt(gap, 10); + // we want to make sure that the size will stay readable + const nsStyleFont* font = NS_STATIC_CAST(const nsStyleFont*, + parentContext->GetStyleData(eStyleStruct_Font)); + nscoord newFontSize = font->mFont.size; + while (0 < gap--) { + newFontSize = (nscoord)((float)(newFontSize) * scriptsizemultiplier); + } + if (newFontSize <= scriptminsize) { + fontsize.Assign(NS_LITERAL_STRING("scriptminsize")); + } + + // set the -moz-math-font-size attribute without notifying that we want a reflow + content->SetAttr(kNameSpaceID_None, nsMathMLAtoms::fontsize, + fontsize, PR_FALSE); } - // set the -moz-math-font-size attribute without notifying that we want a reflow - mContent->SetAttr(kNameSpaceID_None, nsMathMLAtoms::fontsize, - fontsize, PR_FALSE); - // then, re-resolve the style contexts in our subtree - nsCOMPtr newStyleContext; - aPresContext->ResolveStyleContextFor(mContent, aParentContext, - PR_FALSE, getter_AddRefs(newStyleContext)); - if (newStyleContext && newStyleContext.get() != mStyleContext) { - SetStyleContext(aPresContext, newStyleContext); - nsIFrame* childFrame = mFrames.FirstChild(); - while (childFrame) { - aPresContext->ReParentStyleContext(childFrame, newStyleContext); - childFrame->GetNextSibling(&childFrame); + // now, re-resolve the style contexts in our subtree + nsCOMPtr presShell; + aPresContext->GetShell(getter_AddRefs(presShell)); + if (presShell) { + nsCOMPtr fm; + presShell->GetFrameManager(getter_AddRefs(fm)); + if (fm) { + PRInt32 maxChange, minChange = NS_STYLE_HINT_NONE; + nsStyleChangeList changeList; + fm->ComputeStyleChangeFor(aPresContext, aFrame, + kNameSpaceID_None, nsMathMLAtoms::fontsize, + changeList, minChange, maxChange); } } } - // let children with different scriptsizes handle that themselves - nsIFrame* childFrame = mFrames.FirstChild(); + // recurse down the subtrees for changes that may arise deep down + nsIFrame* childFrame; + aFrame->FirstChild(aPresContext, nsnull, &childFrame); while (childFrame) { - nsIMathMLFrame* mathMLFrame; - nsresult res = childFrame->QueryInterface( - NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame); - if (NS_SUCCEEDED(res) && mathMLFrame) { - mathMLFrame->ReResolveScriptStyle(aPresContext, mStyleContext, - mPresentationData.scriptLevel); - } + PropagateScriptStyleFor(aPresContext, childFrame, aParentScriptLevel); childFrame->GetNextSibling(&childFrame); } - return NS_OK; } @@ -1106,27 +786,22 @@ nsMathMLContainerFrame::Init(nsIPresContext* aPresContext, // with other values, it will do so in its SetInitialChildList() method. nsIMathMLFrame* mathMLFrame; - nsresult res = aParent->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame); - if (NS_SUCCEEDED(res) && mathMLFrame) { + aParent->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame); + if (mathMLFrame) { nsPresentationData parentData; mathMLFrame->GetPresentationData(parentData); mPresentationData.mstyle = parentData.mstyle; mPresentationData.scriptLevel = parentData.scriptLevel; - if (NS_MATHML_IS_DISPLAYSTYLE(parentData.flags)) - mPresentationData.flags |= NS_MATHML_DISPLAYSTYLE; - else - mPresentationData.flags &= ~NS_MATHML_DISPLAYSTYLE; - } - else { - // see if our parent has 'display: block' - // XXX should we restrict this to the top level parent ? - const nsStyleDisplay* display; - aParent->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display); - if (display->mDisplay == NS_STYLE_DISPLAY_BLOCK) { + if (NS_MATHML_IS_DISPLAYSTYLE(parentData.flags)) { mPresentationData.flags |= NS_MATHML_DISPLAYSTYLE; } } - + else { + // It could be that we are wrapped by several non-MathML frames. + // So we retain displaystyle=false, knowing that if our root + // is in displaystyle=true, it will propagate an update to us + // later and we will recover the right displaystyle state anyway. + } return rv; } diff --git a/layout/mathml/base/src/nsMathMLContainerFrame.h b/layout/mathml/base/src/nsMathMLContainerFrame.h index b42b0285205..d5abebd9342 100644 --- a/layout/mathml/base/src/nsMathMLContainerFrame.h +++ b/layout/mathml/base/src/nsMathMLContainerFrame.h @@ -25,7 +25,6 @@ #define nsMathMLContainerFrame_h___ #include "nsCOMPtr.h" -#include "nsIViewManager.h" #include "nsHTMLContainerFrame.h" #include "nsBlockFrame.h" #include "nsInlineFrame.h" @@ -35,8 +34,6 @@ #include "nsMathMLFrame.h" #include "nsMathMLParts.h" -#include "nsCSSValue.h" - /* * Base class for MathML container frames. It acts like an inferred * mrow. By default, this frame uses its Reflow() method to lay its @@ -91,12 +88,30 @@ public: PRInt32 aLastIndex, PRInt32 aScriptLevelIncrement, PRUint32 aFlagsValues, - PRUint32 aFlagsToUpdate); + PRUint32 aFlagsToUpdate) + { + PRInt32 index = 0; + nsIFrame* childFrame = mFrames.FirstChild(); + while (childFrame) { + if ((index >= aFirstIndex) && + ((aLastIndex <= 0) || ((aLastIndex > 0) && (index <= aLastIndex)))) { + PropagatePresentationDataFor(aPresContext, childFrame, + aScriptLevelIncrement, aFlagsValues, aFlagsToUpdate); + } + index++; + childFrame->GetNextSibling(&childFrame); + } + return NS_OK; + } NS_IMETHOD ReResolveScriptStyle(nsIPresContext* aPresContext, nsIStyleContext* aParentContext, - PRInt32 aParentScriptLevel); + PRInt32 aParentScriptLevel) + { + PropagateScriptStyleFor(aPresContext, this, aParentScriptLevel); + return NS_OK; + } // -------------------------------------------------------------------------- // Overloaded nsHTMLContainerFrame methods -- see documentation in nsIFrame.h @@ -225,20 +240,6 @@ public: nsIRenderingContext& aRenderingContext, nsHTMLReflowMetrics& aDesiredSize); - // helper to give a style context suitable for doing the stretching to the - // MathMLChar. Frame classes that use this should make the extra style contexts - // accessible to the Style System via Get/Set AdditionalStyleContext. - // return true if the char is a mutable char - static PRBool - ResolveMathMLCharStyle(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIStyleContext* aParenStyleContext, - nsMathMLChar* aMathMLChar); - - // helper to check if a frame is an embellished container - static PRBool - IsEmbellishOperator(nsIFrame* aFrame); - // helper method to facilitate getting the reflow and bounding metrics // IMPORTANT: This function is only meant to be called in Place() methods // where it is assumed that the frame's rect is still acting as place holder @@ -248,223 +249,21 @@ public: nsHTMLReflowMetrics& aReflowMetrics, nsBoundingMetrics& aBoundingMetrics); - // helper to check if a content has an attribute. If content is nsnull or if - // the attribute is not there, check if the attribute is on the mstyle hierarchy - // @return NS_CONTENT_ATTR_HAS_VALUE --if attribute has non-empty value, attr="value" - // NS_CONTENT_ATTR_NO_VALUE --if attribute has empty value, attr="" - // NS_CONTENT_ATTR_NOT_THERE --if attribute is not there - static nsresult - GetAttribute(nsIContent* aContent, - nsIFrame* aMathMLmstyleFrame, - nsIAtom* aAttributeAtom, - nsString& aValue); - - // utilities to parse and retrieve numeric values in CSS units - // All values are stored in twips. - static PRBool - ParseNumericValue(nsString& aString, - nsCSSValue& aCSSValue); - - static nscoord - CalcLength(nsIPresContext* aPresContext, - nsIStyleContext* aStyleContext, - const nsCSSValue& aCSSValue); - - static PRBool - ParseNamedSpaceValue(nsIFrame* aMathMLmstyleFrame, - nsString& aString, - nsCSSValue& aCSSValue); - - // estimate of the italic correction + // helper to let the scriptstyle re-resolution pass through + // a subtree that may contain non-MathML container frames static void - GetItalicCorrection(nsBoundingMetrics& aBoundingMetrics, - nscoord& aItalicCorrection) - { - aItalicCorrection = aBoundingMetrics.rightBearing - aBoundingMetrics.width; - if (0 > aItalicCorrection) { - aItalicCorrection = 0; - } - } + PropagateScriptStyleFor(nsIPresContext* aPresContext, + nsIFrame* aFrame, + PRInt32 aFrameScriptLevel); + // helper to let the update of presentation data pass through + // a subtree that may contain non-MathML container frames static void - GetItalicCorrection(nsBoundingMetrics& aBoundingMetrics, - nscoord& aLeftItalicCorrection, - nscoord& aRightItalicCorrection) - { - aRightItalicCorrection = aBoundingMetrics.rightBearing - aBoundingMetrics.width; - if (0 > aRightItalicCorrection) { - aRightItalicCorrection = 0; - } - aLeftItalicCorrection = -aBoundingMetrics.leftBearing; - if (0 > aLeftItalicCorrection) { - aLeftItalicCorrection = 0; - } - } - - // helper methods for getting sup/subdrop's from a child - static void - GetSubDropFromChild (nsIPresContext* aPresContext, - nsIFrame* aChild, - nscoord& aSubDrop) - { - const nsStyleFont *font; - aChild->GetStyleData(eStyleStruct_Font, (const nsStyleStruct *&)font); - nsCOMPtr fm; - aPresContext->GetMetricsFor(font->mFont, getter_AddRefs(fm)); - - GetSubDrop (fm, aSubDrop); - } - - static void - GetSupDropFromChild (nsIPresContext* aPresContext, - nsIFrame* aChild, - nscoord& aSupDrop) - { - const nsStyleFont *font; - aChild->GetStyleData(eStyleStruct_Font, (const nsStyleStruct *&)font); - nsCOMPtr fm; - aPresContext->GetMetricsFor(font->mFont, getter_AddRefs(fm)); - - GetSupDrop (fm, aSupDrop); - } - - static void - GetSkewCorrectionFromChild (nsIPresContext* aPresContext, - nsIFrame* aChild, - nscoord& aSkewCorrection) - { - // default is 0 - // individual classes should over-ride this method if necessary - aSkewCorrection = 0; - } - - // 2 levels of subscript shifts - static void - GetSubScriptShifts (nsIFontMetrics *fm, - nscoord& aSubScriptShift1, - nscoord& aSubScriptShift2) - { - nscoord xHeight = 0; - fm->GetXHeight (xHeight); - aSubScriptShift1 = NSToCoordRound (150.000f/430.556f * xHeight); - aSubScriptShift2 = NSToCoordRound (247.217f/430.556f * xHeight); - } - - // 3 levels of superscript shifts - static void - GetSupScriptShifts (nsIFontMetrics *fm, - nscoord& aSupScriptShift1, - nscoord& aSupScriptShift2, - nscoord& aSupScriptShift3) - { - nscoord xHeight = 0; - fm->GetXHeight (xHeight); - aSupScriptShift1 = NSToCoordRound (412.892f/430.556f * xHeight); - aSupScriptShift2 = NSToCoordRound (362.892f/430.556f * xHeight); - aSupScriptShift3 = NSToCoordRound (288.889f/430.556f * xHeight); - } - - // these are TeX specific params not found in ordinary fonts - - static void - GetSubDrop (nsIFontMetrics *fm, nscoord& aSubDrop) - { - nscoord xHeight; - fm->GetXHeight (xHeight); - aSubDrop = NSToCoordRound(50.000f/430.556f * xHeight); - } - - static void - GetSupDrop (nsIFontMetrics *fm, nscoord& aSupDrop) - { - nscoord xHeight; - fm->GetXHeight (xHeight); - aSupDrop = NSToCoordRound(386.108f/430.556f * xHeight); - } - - static void - GetNumeratorShifts (nsIFontMetrics *fm, - nscoord& numShift1, - nscoord& numShift2, - nscoord& numShift3) - { - nscoord xHeight = 0; - fm->GetXHeight (xHeight); - numShift1 = NSToCoordRound (676.508f/430.556f * xHeight); - numShift2 = NSToCoordRound (393.732f/430.556f * xHeight); - numShift3 = NSToCoordRound (443.731f/430.556f * xHeight); - } - - static void - GetDenominatorShifts (nsIFontMetrics *fm, - nscoord& denShift1, - nscoord& denShift2) - { - nscoord xHeight = 0; - fm->GetXHeight (xHeight); - denShift1 = NSToCoordRound (685.951f/430.556f * xHeight); - denShift2 = NSToCoordRound (344.841f/430.556f * xHeight); - } - - static void - GetEmHeight (nsIFontMetrics *fm, - nscoord& emHeight) - { -#if 0 // should switch to this API in order to scale with changes of TextZoom - fm->GetEmHeight (emHeight); -#else - const nsFont* font; - fm->GetFont(font); - emHeight = NSToCoordRound(float(font->size)); -#endif - } - - static void - GetAxisHeight (nsIFontMetrics *fm, - nscoord& axisHeight) - { - fm->GetXHeight (axisHeight); - axisHeight = NSToCoordRound (250.000f/430.556f * axisHeight); - } - - static void - GetBigOpSpacings (nsIFontMetrics *fm, - nscoord& bigOpSpacing1, - nscoord& bigOpSpacing2, - nscoord& bigOpSpacing3, - nscoord& bigOpSpacing4, - nscoord& bigOpSpacing5) - { - nscoord xHeight = 0; - fm->GetXHeight (xHeight); - bigOpSpacing1 = NSToCoordRound (111.111f/430.556f * xHeight); - bigOpSpacing2 = NSToCoordRound (166.667f/430.556f * xHeight); - bigOpSpacing3 = NSToCoordRound (200.000f/430.556f * xHeight); - bigOpSpacing4 = NSToCoordRound (600.000f/430.556f * xHeight); - bigOpSpacing5 = NSToCoordRound (100.000f/430.556f * xHeight); - } - - static void - GetRuleThickness(nsIFontMetrics* fm, - nscoord& ruleThickness) - { - nscoord xHeight; - fm->GetXHeight (xHeight); - ruleThickness = NSToCoordRound (40.000f/430.556f * xHeight); - } - - // Some parameters are not accurately obtained using the x-height. - // Here are some slower variants to obtain the desired metrics - // by actually measuring some characters - static void - GetRuleThickness(nsIRenderingContext& aRenderingContext, - nsIFontMetrics* aFontMetrics, - nscoord& aRuleThickness); - - static void - GetAxisHeight(nsIRenderingContext& aRenderingContext, - nsIFontMetrics* aFontMetrics, - nscoord& aAxisHeight); + PropagatePresentationDataFor(nsIPresContext* aPresContext, + nsIFrame* aFrame, + PRInt32 aScriptLevelIncrement, + PRUint32 aFlagsValues, + PRUint32 aFlagsToUpdate); protected: virtual PRIntn GetSkipSides() const { return 0; } @@ -483,6 +282,8 @@ class nsMathMLmathBlockFrame : public nsBlockFrame { public: friend nsresult NS_NewMathMLmathBlockFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame); + // beware, mFrames is not set by nsBlockFrame, FirstChild() is your friend + // when you need to access the child list of the block NS_IMETHOD SetInitialChildList(nsIPresContext* aPresContext, nsIAtom* aListName, @@ -492,17 +293,17 @@ public: rv = nsBlockFrame::SetInitialChildList(aPresContext, aListName, aChildList); - // re-resolve our subtree to set any mathml-expected scriptsizes - nsIFrame* childFrame = aChildList; // mFrames is not used by nsBlockFrame + // notify our children that they are now in displaystyle=true + nsIFrame* childFrame = aChildList; while (childFrame) { - nsIMathMLFrame* mathMLFrame; - nsresult res = childFrame->QueryInterface( - NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame); - if (NS_SUCCEEDED(res) && mathMLFrame) { - mathMLFrame->ReResolveScriptStyle(aPresContext, mStyleContext, 0); - } + nsMathMLContainerFrame::PropagatePresentationDataFor(aPresContext, + childFrame, 0, NS_MATHML_DISPLAYSTYLE, NS_MATHML_DISPLAYSTYLE); childFrame->GetNextSibling(&childFrame); } + + // re-resolve our subtree to set any mathml-expected scriptsizes + nsMathMLContainerFrame::PropagateScriptStyleFor(aPresContext, this, 0); + return rv; } @@ -524,16 +325,8 @@ public: rv = nsInlineFrame::SetInitialChildList(aPresContext, aListName, aChildList); // re-resolve our subtree to set any mathml-expected scriptsizes - nsIFrame* childFrame = mFrames.FirstChild(); - while (childFrame) { - nsIMathMLFrame* mathMLFrame; - nsresult res = childFrame->QueryInterface( - NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame); - if (NS_SUCCEEDED(res) && mathMLFrame) { - mathMLFrame->ReResolveScriptStyle(aPresContext, mStyleContext, 0); - } - childFrame->GetNextSibling(&childFrame); - } + nsMathMLContainerFrame::PropagateScriptStyleFor(aPresContext, this, 0); + return rv; } diff --git a/layout/mathml/base/src/nsMathMLFrame.cpp b/layout/mathml/base/src/nsMathMLFrame.cpp index c4290c2d262..24f99890f78 100644 --- a/layout/mathml/base/src/nsMathMLFrame.cpp +++ b/layout/mathml/base/src/nsMathMLFrame.cpp @@ -19,14 +19,17 @@ * Roger B. Sidje */ +#include "nsINameSpaceManager.h" #include "nsMathMLFrame.h" +#include "nsMathMLChar.h" NS_IMPL_QUERY_INTERFACE1(nsMathMLFrame, nsIMathMLFrame) NS_IMETHODIMP -nsMathMLFrame::UpdatePresentationData(PRInt32 aScriptLevelIncrement, - PRUint32 aFlagsValues, - PRUint32 aFlagsToUpdate) +nsMathMLFrame::UpdatePresentationData(nsIPresContext* aPresContext, + PRInt32 aScriptLevelIncrement, + PRUint32 aFlagsValues, + PRUint32 aFlagsToUpdate) { mPresentationData.scriptLevel += aScriptLevelIncrement; // update flags that are relevant to this call @@ -49,3 +52,336 @@ nsMathMLFrame::UpdatePresentationData(PRInt32 aScriptLevelIncrement, } return NS_OK; } + +/* static */ PRBool +nsMathMLFrame::IsEmbellishOperator(nsIFrame* aFrame) +{ + NS_PRECONDITION(aFrame, "null arg"); + if (!aFrame) return PR_FALSE; + nsIMathMLFrame* mathMLFrame; + nsresult rv = aFrame->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame); + if (NS_FAILED(rv) || !mathMLFrame) return PR_FALSE; + nsEmbellishData embellishData; + mathMLFrame->GetEmbellishData(embellishData); + return NS_MATHML_IS_EMBELLISH_OPERATOR(embellishData.flags); +} + +// Helper to give a style context suitable for doing the stretching of +// a MathMLChar. Frame classes that use this should ensure that the +// extra leaf style contexts given to the MathMLChars are acessible to +// the Style System via the Get/Set AdditionalStyleContext() APIs. +/* static */ PRBool +nsMathMLFrame::ResolveMathMLCharStyle(nsIPresContext* aPresContext, + nsIContent* aContent, + nsIStyleContext* aParentStyleContext, + nsMathMLChar* aMathMLChar) +{ + nsAutoString data; + aMathMLChar->GetData(data); + PRBool isStretchy = nsMathMLOperators::IsMutableOperator(data); + nsIAtom* fontAtom = (isStretchy) ? + nsMathMLAtoms::fontstyle_stretchy : + nsMathMLAtoms::fontstyle_anonymous; + nsCOMPtr newStyleContext; + nsresult rv = aPresContext->ResolvePseudoStyleContextFor(aContent, fontAtom, + aParentStyleContext, PR_FALSE, + getter_AddRefs(newStyleContext)); + if (NS_SUCCEEDED(rv) && newStyleContext) + aMathMLChar->SetStyleContext(newStyleContext); + + return isStretchy; +} + +// helper to get an attribute from the content or the surrounding hierarchy +nsresult +nsMathMLFrame::GetAttribute(nsIContent* aContent, + nsIFrame* aMathMLmstyleFrame, + nsIAtom* aAttributeAtom, + nsString& aValue) +{ + nsresult rv = NS_CONTENT_ATTR_NOT_THERE; + + // see if we can get the attribute from the content + if (aContent) { + rv = aContent->GetAttr(kNameSpaceID_None, aAttributeAtom, aValue); + } + + if (NS_CONTENT_ATTR_NOT_THERE == rv) { + // see if we can get the attribute from the mstyle frame + if (aMathMLmstyleFrame) { + nsCOMPtr mstyleContent; + aMathMLmstyleFrame->GetContent(getter_AddRefs(mstyleContent)); + + nsIFrame* mstyleParent; + aMathMLmstyleFrame->GetParent(&mstyleParent); + + nsPresentationData mstyleParentData; + mstyleParentData.mstyle = nsnull; + + if (mstyleParent) { + nsIMathMLFrame* mathMLFrame; + rv = mstyleParent->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame); + if (NS_SUCCEEDED(rv) && mathMLFrame) { + mathMLFrame->GetPresentationData(mstyleParentData); + } + } + + // recurse all the way up into the hierarchy + rv = GetAttribute(mstyleContent, mstyleParentData.mstyle, aAttributeAtom, aValue); + } + } + return rv; +} + +/* static */ void +nsMathMLFrame::GetRuleThickness(nsIRenderingContext& aRenderingContext, + nsIFontMetrics* aFontMetrics, + nscoord& aRuleThickness) +{ + // get the bounding metrics of the overbar char, the rendering context + // is assumed to have been set with the font of the current style context + nscoord xHeight; + aFontMetrics->GetXHeight(xHeight); + PRUnichar overBar = 0x00AF; + nsBoundingMetrics bm; + nsresult rv = aRenderingContext.GetBoundingMetrics(&overBar, PRUint32(1), bm); + if (NS_SUCCEEDED(rv)) { + aRuleThickness = bm.ascent + bm.descent; + } + if (NS_FAILED(rv) || aRuleThickness <= 0 || aRuleThickness >= xHeight) { + // fall-back to the other version + GetRuleThickness(aFontMetrics, aRuleThickness); + } + +#if 0 + nscoord oldRuleThickness; + GetRuleThickness(aFontMetrics, oldRuleThickness); + + PRUnichar sqrt = 0xE063; // a sqrt glyph from TeX's CMEX font + rv = aRenderingContext.GetBoundingMetrics(&sqrt, PRUint32(1), bm); + nscoord sqrtrule = bm.ascent; // according to TeX, the ascent should be the rule + + printf("xheight:%4d rule:%4d oldrule:%4d sqrtrule:%4d\n", + xHeight, aRuleThickness, oldRuleThickness, sqrtrule); +#endif +} + +/* static */ void +nsMathMLFrame::GetAxisHeight(nsIRenderingContext& aRenderingContext, + nsIFontMetrics* aFontMetrics, + nscoord& aAxisHeight) +{ + // get the bounding metrics of the minus sign, the rendering context + // is assumed to have been set with the font of the current style context + nscoord xHeight; + aFontMetrics->GetXHeight(xHeight); + PRUnichar minus = '-'; + nsBoundingMetrics bm; + nsresult rv = aRenderingContext.GetBoundingMetrics(&minus, PRUint32(1), bm); + if (NS_SUCCEEDED(rv)) { + aAxisHeight = bm.ascent - (bm.ascent + bm.descent)/2; + } + if (NS_FAILED(rv) || aAxisHeight <= 0 || aAxisHeight >= xHeight) { + // fall-back to the other version + GetAxisHeight(aFontMetrics, aAxisHeight); + } + +#if 0 + nscoord oldAxis; + GetAxisHeight(aFontMetrics, oldAxis); + + PRUnichar plus = '+'; + rv = aRenderingContext.GetBoundingMetrics(&plus, PRUint32(1), bm); + nscoord plusAxis = bm.ascent - (bm.ascent + bm.descent)/2;; + + printf("xheight:%4d Axis:%4d oldAxis:%4d plusAxis:%4d\n", + xHeight, aAxisHeight, oldAxis, plusAxis); +#endif +} + +// ================ +// Utilities for parsing and retrieving numeric values +// All returned values are in twips. + +/* +The REC says: + An explicit plus sign ('+') is not allowed as part of a numeric value + except when it is specifically listed in the syntax (as a quoted '+' or "+"), + + Units allowed + ID Description + em ems (font-relative unit traditionally used for horizontal lengths) + ex exs (font-relative unit traditionally used for vertical lengths) + px pixels, or pixel size of a "typical computer display" + in inches (1 inch = 2.54 centimeters) + cm centimeters + mm millimeters + pt points (1 point = 1/72 inch) + pc picas (1 pica = 12 points) + % percentage of default value + +Implementation here: + The numeric value is valid only if it is of the form nnn.nnn [h/v-unit] +*/ + +/* static */ PRBool +nsMathMLFrame::ParseNumericValue(nsString& aString, + nsCSSValue& aCSSValue) +{ + aCSSValue.Reset(); + aString.CompressWhitespace(); // aString is not a const in this code... + + PRInt32 stringLength = aString.Length(); + + if (!stringLength) return PR_FALSE; + + nsAutoString number(aString); + number.SetLength(0); + + nsAutoString unit(aString); + unit.SetLength(0); + + // Gather up characters that make up the number + PRBool gotDot = PR_FALSE; + PRUnichar c; + for (PRInt32 i = 0; i < stringLength; i++) { + c = aString[i]; + if (gotDot && c == '.') + return PR_FALSE; // two dots encountered + else if (c == '.') + gotDot = PR_TRUE; + else if (!nsCRT::IsAsciiDigit(c)) { + aString.Right(unit, stringLength - i); + unit.CompressWhitespace(); // some authors leave blanks before the unit + break; + } + number.Append(c); + } + + // Convert number to floating point + PRInt32 errorCode; + float floatValue = number.ToFloat(&errorCode); + if (NS_FAILED(errorCode)) return PR_FALSE; + + nsCSSUnit cssUnit; + if (0 == unit.Length()) { + cssUnit = eCSSUnit_Number; // no explicit unit, this is a number that will act as a multiplier + } + else if (unit.Equals(NS_LITERAL_STRING("%"))) { + floatValue = floatValue / 100.0f; + aCSSValue.SetPercentValue(floatValue); + return PR_TRUE; + } + else if (unit.Equals(NS_LITERAL_STRING("em"))) cssUnit = eCSSUnit_EM; + else if (unit.Equals(NS_LITERAL_STRING("ex"))) cssUnit = eCSSUnit_XHeight; + else if (unit.Equals(NS_LITERAL_STRING("px"))) cssUnit = eCSSUnit_Pixel; + else if (unit.Equals(NS_LITERAL_STRING("in"))) cssUnit = eCSSUnit_Inch; + else if (unit.Equals(NS_LITERAL_STRING("cm"))) cssUnit = eCSSUnit_Centimeter; + else if (unit.Equals(NS_LITERAL_STRING("mm"))) cssUnit = eCSSUnit_Millimeter; + else if (unit.Equals(NS_LITERAL_STRING("pt"))) cssUnit = eCSSUnit_Point; + else if (unit.Equals(NS_LITERAL_STRING("pc"))) cssUnit = eCSSUnit_Pica; + else // unexpected unit + return PR_FALSE; + + aCSSValue.SetFloatValue(floatValue, cssUnit); + return PR_TRUE; +} + +/* static */ nscoord +nsMathMLFrame::CalcLength(nsIPresContext* aPresContext, + nsIStyleContext* aStyleContext, + const nsCSSValue& aCSSValue) +{ + NS_ASSERTION(aCSSValue.IsLengthUnit(), "not a length unit"); + + if (aCSSValue.IsFixedLengthUnit()) { + return aCSSValue.GetLengthTwips(); + } + + nsCSSUnit unit = aCSSValue.GetUnit(); + + if (eCSSUnit_Pixel == unit) { + float p2t; + aPresContext->GetScaledPixelsToTwips(&p2t); + return NSFloatPixelsToTwips(aCSSValue.GetFloatValue(), p2t); + } + else if (eCSSUnit_EM == unit) { + const nsStyleFont *font = NS_STATIC_CAST(const nsStyleFont*, + aStyleContext->GetStyleData(eStyleStruct_Font)); + return NSToCoordRound(aCSSValue.GetFloatValue() * (float)font->mFont.size); + } + else if (eCSSUnit_XHeight == unit) { + nscoord xHeight; + const nsStyleFont *font = NS_STATIC_CAST(const nsStyleFont*, + aStyleContext->GetStyleData(eStyleStruct_Font)); + nsCOMPtr fm; + aPresContext->GetMetricsFor(font->mFont, getter_AddRefs(fm)); + fm->GetXHeight(xHeight); + return NSToCoordRound(aCSSValue.GetFloatValue() * (float)xHeight); + } + + return 0; +} + +/* static */ PRBool +nsMathMLFrame::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.Equals(NS_LITERAL_STRING("veryverythinmathspace"))) { + i = 1; + namedspaceAtom = nsMathMLAtoms::veryverythinmathspace_; + } + else if (aString.Equals(NS_LITERAL_STRING("verythinmathspace"))) { + i = 2; + namedspaceAtom = nsMathMLAtoms::verythinmathspace_; + } + else if (aString.Equals(NS_LITERAL_STRING("thinmathspace"))) { + i = 3; + namedspaceAtom = nsMathMLAtoms::thinmathspace_; + } + else if (aString.Equals(NS_LITERAL_STRING("mediummathspace"))) { + i = 4; + namedspaceAtom = nsMathMLAtoms::mediummathspace_; + } + else if (aString.Equals(NS_LITERAL_STRING("thickmathspace"))) { + i = 5; + namedspaceAtom = nsMathMLAtoms::thickmathspace_; + } + else if (aString.Equals(NS_LITERAL_STRING("verythickmathspace"))) { + i = 6; + namedspaceAtom = nsMathMLAtoms::verythickmathspace_; + } + else if (aString.Equals(NS_LITERAL_STRING("veryverythickmathspace"))) { + i = 7; + namedspaceAtom = nsMathMLAtoms::veryverythickmathspace_; + } + + if (0 != i) { + if (aMathMLmstyleFrame) { + // see if there is a that has overriden the default value + // GetAttribute() will recurse all the way up into the 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; +} diff --git a/layout/mathml/base/src/nsMathMLFrame.h b/layout/mathml/base/src/nsMathMLFrame.h index 93e8b602942..259c9842420 100644 --- a/layout/mathml/base/src/nsMathMLFrame.h +++ b/layout/mathml/base/src/nsMathMLFrame.h @@ -22,11 +22,18 @@ #ifndef nsMathMLFrame_h___ #define nsMathMLFrame_h___ +#include "nsCOMPtr.h" #include "nsIPresContext.h" #include "nsIRenderingContext.h" +#include "nsIFontMetrics.h" #include "nsIStyleContext.h" +#include "nsMathMLAtoms.h" #include "nsMathMLOperators.h" #include "nsIMathMLFrame.h" +#include "nsFrame.h" +#include "nsCSSValue.h" + +class nsMathMLChar; // Concrete base class with default methods that derived MathML frames can override class nsMathMLFrame : public nsIMathMLFrame { @@ -121,9 +128,10 @@ public: } NS_IMETHOD - UpdatePresentationData(PRInt32 aScriptLevelIncrement, - PRUint32 aFlagsValues, - PRUint32 aFlagsToUpdate); + UpdatePresentationData(nsIPresContext* aPresContext, + PRInt32 aScriptLevelIncrement, + PRUint32 aFlagsValues, + PRUint32 aFlagsToUpdate); NS_IMETHOD UpdatePresentationDataFromChildAt(nsIPresContext* aPresContext, @@ -144,6 +152,240 @@ public: return NS_OK; } + // helper to check if a frame is embellished + static PRBool + IsEmbellishOperator(nsIFrame* aFrame); + + // helper to give a style context suitable for doing the stretching to the + // MathMLChar. Frame classes that use this should make the extra style contexts + // accessible to the Style System via Get/Set AdditionalStyleContext. + // return true if the char is a mutable char + static PRBool + ResolveMathMLCharStyle(nsIPresContext* aPresContext, + nsIContent* aContent, + nsIStyleContext* aParenStyleContext, + nsMathMLChar* aMathMLChar); + + // helper to check if a content has an attribute. If content is nsnull or if + // the attribute is not there, check if the attribute is on the mstyle hierarchy + // @return NS_CONTENT_ATTR_HAS_VALUE --if attribute has non-empty value, attr="value" + // NS_CONTENT_ATTR_NO_VALUE --if attribute has empty value, attr="" + // NS_CONTENT_ATTR_NOT_THERE --if attribute is not there + static nsresult + GetAttribute(nsIContent* aContent, + nsIFrame* aMathMLmstyleFrame, + nsIAtom* aAttributeAtom, + nsString& aValue); + + // utilities to parse and retrieve numeric values in CSS units + // All values are stored in twips. + static PRBool + ParseNumericValue(nsString& aString, + nsCSSValue& aCSSValue); + + static nscoord + CalcLength(nsIPresContext* aPresContext, + nsIStyleContext* aStyleContext, + const nsCSSValue& aCSSValue); + + static PRBool + ParseNamedSpaceValue(nsIFrame* aMathMLmstyleFrame, + nsString& aString, + nsCSSValue& aCSSValue); + + // estimate of the italic correction + static void + GetItalicCorrection(nsBoundingMetrics& aBoundingMetrics, + nscoord& aItalicCorrection) + { + aItalicCorrection = aBoundingMetrics.rightBearing - aBoundingMetrics.width; + if (0 > aItalicCorrection) { + aItalicCorrection = 0; + } + } + + static void + GetItalicCorrection(nsBoundingMetrics& aBoundingMetrics, + nscoord& aLeftItalicCorrection, + nscoord& aRightItalicCorrection) + { + aRightItalicCorrection = aBoundingMetrics.rightBearing - aBoundingMetrics.width; + if (0 > aRightItalicCorrection) { + aRightItalicCorrection = 0; + } + aLeftItalicCorrection = -aBoundingMetrics.leftBearing; + if (0 > aLeftItalicCorrection) { + aLeftItalicCorrection = 0; + } + } + + // helper methods for getting sup/subdrop's from a child + static void + GetSubDropFromChild(nsIPresContext* aPresContext, + nsIFrame* aChild, + nscoord& aSubDrop) + { + const nsStyleFont* font; + aChild->GetStyleData(eStyleStruct_Font, (const nsStyleStruct *&)font); + nsCOMPtr fm; + aPresContext->GetMetricsFor(font->mFont, getter_AddRefs(fm)); + GetSubDrop(fm, aSubDrop); + } + + static void + GetSupDropFromChild(nsIPresContext* aPresContext, + nsIFrame* aChild, + nscoord& aSupDrop) + { + const nsStyleFont* font; + aChild->GetStyleData(eStyleStruct_Font, (const nsStyleStruct *&)font); + nsCOMPtr fm; + aPresContext->GetMetricsFor(font->mFont, getter_AddRefs(fm)); + GetSupDrop(fm, aSupDrop); + } + + static void + GetSkewCorrectionFromChild(nsIPresContext* aPresContext, + nsIFrame* aChild, + nscoord& aSkewCorrection) + { + // default is 0 + // individual classes should over-ride this method if necessary + aSkewCorrection = 0; + } + + // 2 levels of subscript shifts + static void + GetSubScriptShifts(nsIFontMetrics* fm, + nscoord& aSubScriptShift1, + nscoord& aSubScriptShift2) + { + nscoord xHeight; + fm->GetXHeight(xHeight); + aSubScriptShift1 = NSToCoordRound(150.000f/430.556f * xHeight); + aSubScriptShift2 = NSToCoordRound(247.217f/430.556f * xHeight); + } + + // 3 levels of superscript shifts + static void + GetSupScriptShifts(nsIFontMetrics* fm, + nscoord& aSupScriptShift1, + nscoord& aSupScriptShift2, + nscoord& aSupScriptShift3) + { + nscoord xHeight; + fm->GetXHeight(xHeight); + aSupScriptShift1 = NSToCoordRound(412.892f/430.556f * xHeight); + aSupScriptShift2 = NSToCoordRound(362.892f/430.556f * xHeight); + aSupScriptShift3 = NSToCoordRound(288.889f/430.556f * xHeight); + } + + // these are TeX specific params not found in ordinary fonts + + static void + GetSubDrop(nsIFontMetrics* fm, + nscoord& aSubDrop) + { + nscoord xHeight; + fm->GetXHeight(xHeight); + aSubDrop = NSToCoordRound(50.000f/430.556f * xHeight); + } + + static void + GetSupDrop(nsIFontMetrics* fm, + nscoord& aSupDrop) + { + nscoord xHeight; + fm->GetXHeight(xHeight); + aSupDrop = NSToCoordRound(386.108f/430.556f * xHeight); + } + + static void + GetNumeratorShifts(nsIFontMetrics* fm, + nscoord& numShift1, + nscoord& numShift2, + nscoord& numShift3) + { + nscoord xHeight; + fm->GetXHeight(xHeight); + numShift1 = NSToCoordRound(676.508f/430.556f * xHeight); + numShift2 = NSToCoordRound(393.732f/430.556f * xHeight); + numShift3 = NSToCoordRound(443.731f/430.556f * xHeight); + } + + static void + GetDenominatorShifts(nsIFontMetrics* fm, + nscoord& denShift1, + nscoord& denShift2) + { + nscoord xHeight; + fm->GetXHeight(xHeight); + denShift1 = NSToCoordRound(685.951f/430.556f * xHeight); + denShift2 = NSToCoordRound(344.841f/430.556f * xHeight); + } + + static void + GetEmHeight(nsIFontMetrics* fm, + nscoord& emHeight) + { +#if 0 + // should switch to this API in order to scale with changes of TextZoom + fm->GetEmHeight(emHeight); +#else + const nsFont* font; + fm->GetFont(font); + emHeight = NSToCoordRound(float(font->size)); +#endif + } + + static void + GetAxisHeight (nsIFontMetrics* fm, + nscoord& axisHeight) + { + fm->GetXHeight (axisHeight); + axisHeight = NSToCoordRound(250.000f/430.556f * axisHeight); + } + + static void + GetBigOpSpacings(nsIFontMetrics* fm, + nscoord& bigOpSpacing1, + nscoord& bigOpSpacing2, + nscoord& bigOpSpacing3, + nscoord& bigOpSpacing4, + nscoord& bigOpSpacing5) + { + nscoord xHeight; + fm->GetXHeight(xHeight); + bigOpSpacing1 = NSToCoordRound(111.111f/430.556f * xHeight); + bigOpSpacing2 = NSToCoordRound(166.667f/430.556f * xHeight); + bigOpSpacing3 = NSToCoordRound(200.000f/430.556f * xHeight); + bigOpSpacing4 = NSToCoordRound(600.000f/430.556f * xHeight); + bigOpSpacing5 = NSToCoordRound(100.000f/430.556f * xHeight); + } + + static void + GetRuleThickness(nsIFontMetrics* fm, + nscoord& ruleThickness) + { + nscoord xHeight; + fm->GetXHeight(xHeight); + ruleThickness = NSToCoordRound(40.000f/430.556f * xHeight); + } + + // Some parameters are not accurately obtained using the x-height. + // Here are some slower variants to obtain the desired metrics + // by actually measuring some characters + static void + GetRuleThickness(nsIRenderingContext& aRenderingContext, + nsIFontMetrics* aFontMetrics, + nscoord& aRuleThickness); + + static void + GetAxisHeight(nsIRenderingContext& aRenderingContext, + nsIFontMetrics* aFontMetrics, + nscoord& aAxisHeight); + + protected: // information about the presentation policy of the frame nsPresentationData mPresentationData; diff --git a/layout/mathml/base/src/nsMathMLmoFrame.cpp b/layout/mathml/base/src/nsMathMLmoFrame.cpp index 1e482f48120..f64a7cee3e2 100644 --- a/layout/mathml/base/src/nsMathMLmoFrame.cpp +++ b/layout/mathml/base/src/nsMathMLmoFrame.cpp @@ -292,22 +292,17 @@ nsMathMLmoFrame::InitData(nsIPresContext* aPresContext) // it mutable irrespective of the form of the embellished container mFlags &= NS_MATHML_OPERATOR_MUTABLE; - // find our form - nsAutoString value; - nsOperatorFlags form = NS_MATHML_OPERATOR_FORM_INFIX; - + // Get our outermost embellished container and its parent. + // We ensure that we are the core, not just a sibling of the core nsIMathMLFrame* mathMLFrame = nsnull; nsIFrame* embellishAncestor = this; nsEmbellishData embellishData; - - // Get our outermost embellished container and its parent. - // We ensure that we are the core, not just a sibling of the core nsIFrame* parentAncestor = this; do { embellishAncestor = parentAncestor; embellishAncestor->GetParent(&parentAncestor); - rv = parentAncestor->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame); - if (NS_SUCCEEDED(rv) && mathMLFrame) { + parentAncestor->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame); + if (mathMLFrame) { mathMLFrame->GetEmbellishData(embellishData); } else { @@ -319,6 +314,9 @@ nsMathMLmoFrame::InitData(nsIPresContext* aPresContext) mFlags |= NS_MATHML_OPERATOR_EMBELLISH_ANCESTOR; } + // find our form + nsAutoString value; + nsOperatorFlags form = NS_MATHML_OPERATOR_FORM_INFIX; if (NS_CONTENT_ATTR_HAS_VALUE == GetAttribute(mContent, mPresentationData.mstyle, nsMathMLAtoms::form_, value)) { if (value.Equals(NS_LITERAL_STRING("prefix"))) diff --git a/layout/mathml/base/src/nsMathMLmoverFrame.cpp b/layout/mathml/base/src/nsMathMLmoverFrame.cpp index 7a23db5f2f2..986adcfa81a 100644 --- a/layout/mathml/base/src/nsMathMLmoverFrame.cpp +++ b/layout/mathml/base/src/nsMathMLmoverFrame.cpp @@ -86,6 +86,25 @@ nsMathMLmoverFrame::Init(nsIPresContext* aPresContext, return rv; } +NS_IMETHODIMP +nsMathMLmoverFrame::UpdatePresentationData(nsIPresContext* aPresContext, + PRInt32 aScriptLevelIncrement, + PRUint32 aFlagsValues, + PRUint32 aFlagsToUpdate) +{ + nsMathMLContainerFrame::UpdatePresentationData(aPresContext, + aScriptLevelIncrement, aFlagsValues, aFlagsToUpdate); + // disable the stretch-all flag if we are going to act like a superscript + if ( NS_MATHML_IS_MOVABLELIMITS(mPresentationData.flags) && + !NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags)) { + mEmbellishData.flags &= ~NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY; + } + else { + mEmbellishData.flags |= NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY; + } + return NS_OK; +} + NS_IMETHODIMP nsMathMLmoverFrame::SetInitialChildList(nsIPresContext* aPresContext, nsIAtom* aListName, @@ -200,7 +219,7 @@ XXX The winner is the outermost in conflicting settings like these: ? 0 : 1; PRUint32 compress = NS_MATHML_IS_ACCENTOVER(mPresentationData.flags) ? NS_MATHML_COMPRESSED : 0; - overscriptMathMLFrame->UpdatePresentationData(increment, + overscriptMathMLFrame->UpdatePresentationData(aPresContext, increment, ~NS_MATHML_DISPLAYSTYLE | compress, NS_MATHML_DISPLAYSTYLE | compress); overscriptMathMLFrame->UpdatePresentationDataFromChildAt(aPresContext, 0, -1, increment, diff --git a/layout/mathml/base/src/nsMathMLmoverFrame.h b/layout/mathml/base/src/nsMathMLmoverFrame.h index f3316f4a25a..5f71181fcc8 100644 --- a/layout/mathml/base/src/nsMathMLmoverFrame.h +++ b/layout/mathml/base/src/nsMathMLmoverFrame.h @@ -54,19 +54,10 @@ public: nsIFrame* aChildList); NS_IMETHOD - UpdatePresentationData(PRInt32 aScriptLevelIncrement, - PRUint32 aFlagsValues, - PRUint32 aFlagsToUpdate) - { - nsMathMLContainerFrame::UpdatePresentationData(aScriptLevelIncrement, - aFlagsValues, aFlagsToUpdate); - // disable the stretch-all flag if we are going to act like a superscript - if ( NS_MATHML_IS_MOVABLELIMITS(mPresentationData.flags) && - !NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags)) { - mEmbellishData.flags &= ~NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY; - } - return NS_OK; - } + UpdatePresentationData(nsIPresContext* aPresContext, + PRInt32 aScriptLevelIncrement, + PRUint32 aFlagsValues, + PRUint32 aFlagsToUpdate); protected: nsMathMLmoverFrame(); diff --git a/layout/mathml/base/src/nsMathMLmtableFrame.cpp b/layout/mathml/base/src/nsMathMLmtableFrame.cpp index 74ae5791189..c24e92dd504 100644 --- a/layout/mathml/base/src/nsMathMLmtableFrame.cpp +++ b/layout/mathml/base/src/nsMathMLmtableFrame.cpp @@ -31,7 +31,6 @@ #include "nsUnitConversion.h" #include "nsIStyleContext.h" #include "nsStyleConsts.h" -#include "nsStyleChangeList.h" #include "nsINameSpaceManager.h" #include "nsIRenderingContext.h" #include "nsIFontMetrics.h" @@ -329,89 +328,6 @@ nsMathMLmtableOuterFrame::Init(nsIPresContext* aPresContext, return rv; } -// helper to let the update of presentation data pass through -// a subtree that may contain non-math container frames -void -UpdatePresentationDataFor(nsIPresContext* aPresContext, - nsIFrame* aFrame, - PRInt32 aScriptLevelIncrement, - PRUint32 aFlagsValues, - PRUint32 aFlagsToUpdate) -{ - nsIMathMLFrame* mathMLFrame = nsnull; - nsresult rv = aFrame->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame); - if (NS_SUCCEEDED(rv) && mathMLFrame) { - // update - mathMLFrame->UpdatePresentationData( - aScriptLevelIncrement, aFlagsValues, aFlagsToUpdate); - } - // propagate down the subtrees - nsIFrame* childFrame; - aFrame->FirstChild(aPresContext, nsnull, &childFrame); - while (childFrame) { - UpdatePresentationDataFor(aPresContext, childFrame, - aScriptLevelIncrement, aFlagsValues, aFlagsToUpdate); - childFrame->GetNextSibling(&childFrame); - } -} - -// helper to let the scriptstyle re-resolution pass through -// a subtree that may contain non-math container frames -void -ReResolveScriptStyleFor(nsIPresContext* aPresContext, - nsIFrame* aFrame, - PRInt32 aScriptLevel) -{ - nsIFrame* childFrame = nsnull; - nsCOMPtr styleContext; - aFrame->GetStyleContext(getter_AddRefs(styleContext)); - aFrame->FirstChild(aPresContext, nsnull, &childFrame); - while (childFrame) { - nsIMathMLFrame* mathMLFrame; - nsresult res = childFrame->QueryInterface( - NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame); - if (NS_SUCCEEDED(res) && mathMLFrame) { - mathMLFrame->ReResolveScriptStyle(aPresContext, styleContext, aScriptLevel); - } - else { - ReResolveScriptStyleFor(aPresContext, childFrame, aScriptLevel); - } - childFrame->GetNextSibling(&childFrame); - } -} - -NS_IMETHODIMP -nsMathMLmtableOuterFrame::UpdatePresentationDataFromChildAt(nsIPresContext* aPresContext, - PRInt32 aFirstIndex, - PRInt32 aLastIndex, - PRInt32 aScriptLevelIncrement, - PRUint32 aFlagsValues, - PRUint32 aFlagsToUpdate) -{ - PRInt32 index = 0; - nsIFrame* childFrame = mFrames.FirstChild(); - while (childFrame) { - if ((index >= aFirstIndex) && - ((aLastIndex <= 0) || ((aLastIndex > 0) && (index <= aLastIndex)))) { - UpdatePresentationDataFor(aPresContext, childFrame, - aScriptLevelIncrement, aFlagsValues, aFlagsToUpdate); - } - index++; - childFrame->GetNextSibling(&childFrame); - } - return NS_OK; -} - -NS_IMETHODIMP -nsMathMLmtableOuterFrame::ReResolveScriptStyle(nsIPresContext* aPresContext, - nsIStyleContext* aParentContext, - PRInt32 aParentScriptLevel) -{ - // pass aParentScriptLevel -- it is as if we were not there... - ReResolveScriptStyleFor(aPresContext, this, aParentScriptLevel); - return NS_OK; -} - NS_IMETHODIMP nsMathMLmtableOuterFrame::Reflow(nsIPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, @@ -539,10 +455,10 @@ nsMathMLmtdInnerFrame::~nsMathMLmtdInnerFrame() NS_IMETHODIMP nsMathMLmtdInnerFrame::Init(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIFrame* aParent, - nsIStyleContext* aContext, - nsIFrame* aPrevInFlow) + nsIContent* aContent, + nsIFrame* aParent, + nsIStyleContext* aContext, + nsIFrame* aPrevInFlow) { nsresult rv; rv = nsBlockFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow); @@ -575,16 +491,6 @@ nsMathMLmtdInnerFrame::Init(nsIPresContext* aPresContext, return rv; } -NS_IMETHODIMP -nsMathMLmtdInnerFrame::ReResolveScriptStyle(nsIPresContext* aPresContext, - nsIStyleContext* aParentContext, - PRInt32 aParentScriptLevel) -{ - // pass aParentScriptLevel -- it is as if we were not there... - ReResolveScriptStyleFor(aPresContext, this, aParentScriptLevel); - return NS_OK; -} - NS_IMETHODIMP nsMathMLmtdInnerFrame::Reflow(nsIPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, diff --git a/layout/mathml/base/src/nsMathMLmtableFrame.h b/layout/mathml/base/src/nsMathMLmtableFrame.h index ce90aaec111..6622c469287 100644 --- a/layout/mathml/base/src/nsMathMLmtableFrame.h +++ b/layout/mathml/base/src/nsMathMLmtableFrame.h @@ -45,12 +45,31 @@ public: PRInt32 aLastIndex, PRInt32 aScriptLevelIncrement, PRUint32 aFlagsValues, - PRUint32 aFlagsToUpdate); + PRUint32 aFlagsToUpdate) + { + PRInt32 index = 0; + nsIFrame* childFrame; + FirstChild(aPresContext, nsnull, &childFrame); + while (childFrame) { + if ((index >= aFirstIndex) && + ((aLastIndex <= 0) || ((aLastIndex > 0) && (index <= aLastIndex)))) { + nsMathMLContainerFrame::PropagatePresentationDataFor(aPresContext, + childFrame, aScriptLevelIncrement, aFlagsValues, aFlagsToUpdate); + } + index++; + childFrame->GetNextSibling(&childFrame); + } + return NS_OK; + } NS_IMETHOD ReResolveScriptStyle(nsIPresContext* aPresContext, nsIStyleContext* aParentContext, - PRInt32 aParentScriptLevel); + PRInt32 aParentScriptLevel) + { + nsMathMLContainerFrame::PropagateScriptStyleFor(aPresContext, this, aParentScriptLevel); + return NS_OK; + } // overloaded nsTableOuterFrame methods @@ -82,10 +101,41 @@ public: NS_DECL_ISUPPORTS_INHERITED + // Overloaded nsIMathMLFrame methods + + NS_IMETHOD + UpdatePresentationDataFromChildAt(nsIPresContext* aPresContext, + PRInt32 aFirstIndex, + PRInt32 aLastIndex, + PRInt32 aScriptLevelIncrement, + PRUint32 aFlagsValues, + PRUint32 aFlagsToUpdate) + { + PRInt32 index = 0; + nsIFrame* childFrame; + FirstChild(aPresContext, nsnull, &childFrame); + while (childFrame) { + if ((index >= aFirstIndex) && + ((aLastIndex <= 0) || ((aLastIndex > 0) && (index <= aLastIndex)))) { + nsMathMLContainerFrame::PropagatePresentationDataFor(aPresContext, + childFrame, aScriptLevelIncrement, aFlagsValues, aFlagsToUpdate); + } + index++; + childFrame->GetNextSibling(&childFrame); + } + return NS_OK; + } + NS_IMETHOD ReResolveScriptStyle(nsIPresContext* aPresContext, nsIStyleContext* aParentContext, - PRInt32 aParentScriptLevel); + PRInt32 aParentScriptLevel) + { + nsMathMLContainerFrame::PropagateScriptStyleFor(aPresContext, this, aParentScriptLevel); + return NS_OK; + } + + // overloaded nsBlockFrame methods NS_IMETHOD Init(nsIPresContext* aPresContext, diff --git a/layout/mathml/base/src/nsMathMLmunderFrame.cpp b/layout/mathml/base/src/nsMathMLmunderFrame.cpp index d6ebee019bc..9874588c702 100644 --- a/layout/mathml/base/src/nsMathMLmunderFrame.cpp +++ b/layout/mathml/base/src/nsMathMLmunderFrame.cpp @@ -86,6 +86,25 @@ nsMathMLmunderFrame::Init(nsIPresContext* aPresContext, return rv; } +NS_IMETHODIMP +nsMathMLmunderFrame::UpdatePresentationData(nsIPresContext* aPresContext, + PRInt32 aScriptLevelIncrement, + PRUint32 aFlagsValues, + PRUint32 aFlagsToUpdate) +{ + nsMathMLContainerFrame::UpdatePresentationData(aPresContext, + aScriptLevelIncrement, aFlagsValues, aFlagsToUpdate); + // disable the stretch-all flag if we are going to act like a subscript + if ( NS_MATHML_IS_MOVABLELIMITS(mPresentationData.flags) && + !NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags)) { + mEmbellishData.flags &= ~NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY; + } + else { + mEmbellishData.flags |= NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY; + } + return NS_OK; +} + NS_IMETHODIMP nsMathMLmunderFrame::SetInitialChildList(nsIPresContext* aPresContext, nsIAtom* aListName, @@ -194,7 +213,7 @@ XXX The winner is the outermost setting in conflicting settings like these: if (underscriptMathMLFrame) { PRInt32 increment; increment = NS_MATHML_IS_ACCENTUNDER(mPresentationData.flags)? 0 : 1; - underscriptMathMLFrame->UpdatePresentationData(increment, + underscriptMathMLFrame->UpdatePresentationData(aPresContext, increment, ~NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED, NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED); underscriptMathMLFrame->UpdatePresentationDataFromChildAt(aPresContext, 0, -1, increment, diff --git a/layout/mathml/base/src/nsMathMLmunderFrame.h b/layout/mathml/base/src/nsMathMLmunderFrame.h index 44fba0b08bc..9fb4ee1bd26 100644 --- a/layout/mathml/base/src/nsMathMLmunderFrame.h +++ b/layout/mathml/base/src/nsMathMLmunderFrame.h @@ -54,19 +54,10 @@ public: nsIFrame* aChildList); NS_IMETHOD - UpdatePresentationData(PRInt32 aScriptLevelIncrement, - PRUint32 aFlagsValues, - PRUint32 aFlagsToUpdate) - { - nsMathMLContainerFrame::UpdatePresentationData(aScriptLevelIncrement, - aFlagsValues, aFlagsToUpdate); - // disable the stretch-all flag if we are going to act like a subscript - if ( NS_MATHML_IS_MOVABLELIMITS(mPresentationData.flags) && - !NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags)) { - mEmbellishData.flags &= ~NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY; - } - return NS_OK; - } + UpdatePresentationData(nsIPresContext* aPresContext, + PRInt32 aScriptLevelIncrement, + PRUint32 aFlagsValues, + PRUint32 aFlagsToUpdate); protected: nsMathMLmunderFrame(); diff --git a/layout/mathml/base/src/nsMathMLmunderoverFrame.cpp b/layout/mathml/base/src/nsMathMLmunderoverFrame.cpp index 5301e9eeb97..0bb15dbdd66 100644 --- a/layout/mathml/base/src/nsMathMLmunderoverFrame.cpp +++ b/layout/mathml/base/src/nsMathMLmunderoverFrame.cpp @@ -86,6 +86,25 @@ nsMathMLmunderoverFrame::Init(nsIPresContext* aPresContext, return rv; } +NS_IMETHODIMP +nsMathMLmunderoverFrame::UpdatePresentationData(nsIPresContext* aPresContext, + PRInt32 aScriptLevelIncrement, + PRUint32 aFlagsValues, + PRUint32 aFlagsToUpdate) +{ + nsMathMLContainerFrame::UpdatePresentationData(aPresContext, + aScriptLevelIncrement, aFlagsValues, aFlagsToUpdate); + // disable the stretch-all flag if we are going to act like a subscript-superscript pair + if ( NS_MATHML_IS_MOVABLELIMITS(mPresentationData.flags) && + !NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags)) { + mEmbellishData.flags &= ~NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY; + } + else { + mEmbellishData.flags |= NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY; + } + return NS_OK; +} + NS_IMETHODIMP nsMathMLmunderoverFrame::SetInitialChildList(nsIPresContext* aPresContext, nsIAtom* aListName, @@ -232,7 +251,7 @@ nsMathMLmunderoverFrame::SetInitialChildList(nsIPresContext* aPresContext, ? 0 : 1; PRUint32 compress = NS_MATHML_IS_ACCENTOVER(mPresentationData.flags) ? NS_MATHML_COMPRESSED : 0; - overscriptMathMLFrame->UpdatePresentationData(increment, + overscriptMathMLFrame->UpdatePresentationData(aPresContext, increment, ~NS_MATHML_DISPLAYSTYLE | compress, NS_MATHML_DISPLAYSTYLE | compress); overscriptMathMLFrame->UpdatePresentationDataFromChildAt(aPresContext, 0, -1, increment, @@ -246,7 +265,7 @@ nsMathMLmunderoverFrame::SetInitialChildList(nsIPresContext* aPresContext, */ if (underscriptMathMLFrame) { PRInt32 increment = NS_MATHML_IS_ACCENTUNDER(mPresentationData.flags)? 0 : 1; - underscriptMathMLFrame->UpdatePresentationData(increment, + underscriptMathMLFrame->UpdatePresentationData(aPresContext, increment, ~NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED, NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED); underscriptMathMLFrame->UpdatePresentationDataFromChildAt(aPresContext, 0, -1, increment, diff --git a/layout/mathml/base/src/nsMathMLmunderoverFrame.h b/layout/mathml/base/src/nsMathMLmunderoverFrame.h index dbfe415649f..85be5565110 100644 --- a/layout/mathml/base/src/nsMathMLmunderoverFrame.h +++ b/layout/mathml/base/src/nsMathMLmunderoverFrame.h @@ -54,19 +54,10 @@ public: nsIFrame* aChildList); NS_IMETHOD - UpdatePresentationData(PRInt32 aScriptLevelIncrement, - PRUint32 aFlagsValues, - PRUint32 aFlagsToUpdate) - { - nsMathMLContainerFrame::UpdatePresentationData(aScriptLevelIncrement, - aFlagsValues, aFlagsToUpdate); - // disable the stretch-all flag if we are going to act like a subscript-superscript pair - if ( NS_MATHML_IS_MOVABLELIMITS(mPresentationData.flags) && - !NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags)) { - mEmbellishData.flags &= ~NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY; - } - return NS_OK; - } + UpdatePresentationData(nsIPresContext* aPresContext, + PRInt32 aScriptLevelIncrement, + PRUint32 aFlagsValues, + PRUint32 aFlagsToUpdate); protected: nsMathMLmunderoverFrame();