[MathML only] shuffle shared functions between files to balance the weights of the files

This commit is contained in:
rbs%maths.uq.edu.au 2002-01-09 18:51:30 +00:00
Родитель 9161ae9fda
Коммит a69d15b103
14 изменённых файлов: 926 добавлений и 891 удалений

Просмотреть файл

@ -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,

Просмотреть файл

@ -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 <mstyle> 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<nsIContent> 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 <mstyle> 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<nsIFontMetrics> 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 <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;
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<nsIStyleContext> 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<nsIStyleContext> oldStyleContext;
aFrame->GetStyleContext(getter_AddRefs(oldStyleContext));
nsCOMPtr<nsIStyleContext> parentContext(dont_AddRef(oldStyleContext->GetParent()));
// see if there is a scriptminsize attribute on a <mstyle> 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<nsIContent> 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 <mstyle> 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<nsIStyleContext> 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<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, 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 <math> 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 <math>
// is in displaystyle=true, it will propagate an update to us
// later and we will recover the right displaystyle state anyway.
}
return rv;
}

Просмотреть файл

@ -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<nsIFontMetrics> 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<nsIFontMetrics> 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;
}

Просмотреть файл

@ -19,14 +19,17 @@
* Roger B. Sidje <rbs@maths.uq.edu.au>
*/
#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<nsIStyleContext> 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 <mstyle> 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<nsIContent> 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 <mstyle> 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<nsIFontMetrics> 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 <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;
}

Просмотреть файл

@ -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<nsIFontMetrics> 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<nsIFontMetrics> 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;

Просмотреть файл

@ -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")))

Просмотреть файл

@ -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,

Просмотреть файл

@ -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();

Просмотреть файл

@ -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<nsIStyleContext> 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,

Просмотреть файл

@ -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,

Просмотреть файл

@ -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,

Просмотреть файл

@ -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();

Просмотреть файл

@ -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,

Просмотреть файл

@ -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();