diff --git a/layout/mathml/base/src/nsIMathMLFrame.h b/layout/mathml/base/src/nsIMathMLFrame.h index 09d796efc6ff..65d0b10b4801 100644 --- a/layout/mathml/base/src/nsIMathMLFrame.h +++ b/layout/mathml/base/src/nsIMathMLFrame.h @@ -70,6 +70,11 @@ public: * Called to ask a stretchy MathML frame to stretch itself depending * on its context. * + * An embellished frame is treated in a special way. When it receives a + * Stretch() command, it passes the command to its embellished child and + * the stretched size is bubbled up from the inner-most frame. In other + * words, the stretch command descend through the embellished hierarchy. + * * @param aStretchDirection [in] the direction where to attempt to * stretch. * @param aContainerSize [in] struct that suggests the maximumn size for @@ -121,36 +126,6 @@ public: PRBool aPlaceOrigin, nsHTMLReflowMetrics& aDesiredSize) = 0; - /* EmbellishOperator : - * Call this method to probe and set a frame as an "embellished operator". - * Calls must be bottom up. The method will set the frame as an - * "embellished operator" if the frame satisfies the definition of - * the MathML REC. Conversely, it will set the frame as - * non-embellished if it is not an "embellished operator". - * - * Note that this method must only be called from tags who *can* be - * embellished operators. - * - * The MathML REC precisely defines an "embellished operator" as: - * - an element; - * - or one of the elements , , , , , - * , , , or , whose first - * argument exists and is an embellished operator; - * - or one of the elements , , or , such that - * an containing the same arguments would be an embellished - * operator; - * - or an element whose selected subexpression exists and is an - * embellished operator; - * - or an whose arguments consist (in any order) of one embellished - * operator and zero or more spacelike elements. - * - * When an embellished frame receives a Stretch() command, it passes the - * command to its first child and the stretched size is bubbled up from the - * inner-most frame. - */ - NS_IMETHOD - EmbellishOperator() = 0; - /* GetEmbellishData/SetEmbellishData : * Get/Set the mEmbellishData member variable. */ @@ -184,17 +159,37 @@ public: * within their subtrees. * * InheritAutomaticData() is called in a top-down manner [like nsIFrame::Init], - * as we descend the frame tree during its construction, whereas - * TransmitAutomaticData() is called in a bottom-up manner, as we ascend the - * frame tree after its construction [like nsIFrame::SetInitialChildList]. - * However, unlike Init() and SetInitialChildList() which are called only - * once during the life-time of a frame, these two methods are called - * whenever we are walking the frame tree to handle dynamic changes that - * happen in the content model. + * as we descend the frame tree, whereas TransmitAutomaticData() is called in a + * bottom-up manner, as we ascend the tree [like nsIFrame::SetInitialChildList]. + * However, unlike Init() and SetInitialChildList() which are called only once + * during the life-time of a frame (when initially constructing the frame tree), + * these two methods are called to build automatic data after the ... + * subtree has been constructed fully, and are called again as we walk a child's + * subtree to handle dynamic changes that happen in the content model. + * + * As a rule of thumb: + * + * 1. Use InheritAutomaticData() to set properties related to your ancestors: + * - set properties that are intrinsic to yourself + * - set properties that depend on the state that you expect your ancestors + * to have already reached in their own InheritAutomaticData(). + * - set properties that your descendants assume that you would have set in + * your InheritAutomaticData() -- this way, they can safely query them and + * the process will feed upon itself. + * + * 2. Use TransmitAutomaticData() to set properties related to your descendants: + * - set properties that depend on the state that you expect your descendants + * to have reached upon processing their own TransmitAutomaticData(). + * - transmit properties that your descendants expect that you will transmit to + * them in your TransmitAutomaticData() -- this way, they remain up-to-date. + * - set properties that your ancestors expect that you would set in your + * TransmitAutomaticData() -- this way, they can safely query them and the + * process will feed upon itself. */ NS_IMETHOD - InheritAutomaticData(nsIPresContext* aPresContext, nsIFrame* aParent) = 0; + InheritAutomaticData(nsIPresContext* aPresContext, + nsIFrame* aParent) = 0; NS_IMETHOD TransmitAutomaticData(nsIPresContext* aPresContext) = 0; @@ -305,35 +300,64 @@ public: PRInt32 aParentScriptLevel) = 0; }; -// struct used by a frame to modulate its presentation -struct nsPresentationData { - PRUint32 flags; // bits for: displaystyle, compressed, etc - nsIFrame* mstyle; // up-pointer on the mstyle frame, if any, that defines the scope - PRInt32 scriptLevel; // Relevant to nested frames within: msub, msup, msubsup, munder, - // mover, munderover, mmultiscripts, mfrac, mroot, mtable. - nsPresentationData() - { - flags = 0; - mstyle = nsnull; - scriptLevel = 0; - } -}; - -// struct used by an embellished container to keep track of its embellished child +// struct used by a container frame to keep track of its embellishments. +// By convention, the data that we keep here is bubbled from the embellished +// hierarchy, and it remains unchanged unless we have to recover from a change +// that occurs in the embellished hierarchy. The struct remains in its nil +// state in those frames that are not part of the embellished hierarchy. struct nsEmbellishData { - PRUint32 flags; - nsIFrame* nextFrame; // handy pointer on our embellished child to descend the hierarchy - nsIFrame* coreFrame; // pointer on the mo frame at the core of the embellished hierarchy - nsStretchDirection direction; - nscoord leftSpace, rightSpace; + // bits used to mark certain properties of our embellishments + PRUint32 flags; - nsEmbellishData() - { + // handy pointer on our embellished child to descend the embellished hierarchy + nsIFrame* nextFrame; + + // pointer on the frame at the core of the embellished hierarchy + nsIFrame* coreFrame; + + // stretchy direction that the nsMathMLChar owned by the core supports + nsStretchDirection direction; + + // spacing that may come from depending on its 'form'. Since + // the 'form' may also depend on the position of the outermost + // embellished ancestor, the set up of these values may require + // looking up the position of our ancestors. + nscoord leftSpace; + nscoord rightSpace; + + nsEmbellishData() { flags = 0; nextFrame = nsnull; coreFrame = nsnull; direction = NS_STRETCH_DIRECTION_UNSUPPORTED; - leftSpace = rightSpace = 0; + leftSpace = 0; + rightSpace = 0; + } +}; + +// struct used by a container frame to modulate its presentation. +// By convention, the data that we keep in this struct can change depending +// on any of our ancestors and/or descendants. If a data can be resolved +// solely from the embellished hierarchy, and it remains immutable once +// resolved, we put it in |nsEmbellishData|. If it can be affected by other +// things, it comes here. This struct is updated as we receive information +// transmitted by our ancestors and is kept in sync with changes in our +// descendants that affects us. +struct nsPresentationData { + // bits for: displaystyle, compressed, etc + PRUint32 flags; + + // up-pointer on the mstyle frame, if any, that defines the scope + nsIFrame* mstyle; + + // level of nested frames within: msub, msup, msubsup, munder, + // mover, munderover, mmultiscripts, mfrac, mroot, mtable. + PRInt32 scriptLevel; + + nsPresentationData() { + flags = 0; + mstyle = nsnull; + scriptLevel = 0; } }; @@ -353,38 +377,40 @@ struct nsEmbellishData { // Internal use only, cannot be set by the user with an attribute. #define NS_MATHML_COMPRESSED 0x00000002 +// This bit is set if the frame will fire a vertical stretch +// command on all its (non-empty) children. +// Tags like (or an inferred mrow), mpadded, etc, will fire a +// vertical stretch command on all their non-empty children +#define NS_MATHML_STRETCH_ALL_CHILDREN_VERTICALLY 0x00000004 + +// This bit is set if the frame will fire a horizontal stretch +// command on all its (non-empty) children. +// Tags like munder, mover, munderover, will fire a +// horizontal stretch command on all their non-empty children +#define NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY 0x00000008 + // This bit is set if the frame is actually an frame *and* that // frame has an explicit attribute scriptlevel="value". // Note: the flag is not set if the instead has an incremental +/-value. -#define NS_MATHML_MSTYLE_WITH_EXPLICIT_SCRIPTLEVEL 0x00000004 +#define NS_MATHML_MSTYLE_WITH_EXPLICIT_SCRIPTLEVEL 0x00000010 // This bit is set if the frame is actually an *and* that // has an explicit attribute displaystyle="true" or "false" -#define NS_MATHML_MSTYLE_WITH_DISPLAYSTYLE 0x00000008 - -// This bit is set if the frame is an or with -// an accent frame -#define NS_MATHML_ACCENTOVER 0x00000010 - -// This bit is set if the frame is an or with -// an accentunder frame -#define NS_MATHML_ACCENTUNDER 0x00000020 - -// This bit is set if the frame is an , or -// whose base frame is a frame (or an embellished container with -// a core ) for which the movablelimits attribute is set to true -#define NS_MATHML_MOVABLELIMITS 0x00000040 +#define NS_MATHML_MSTYLE_WITH_DISPLAYSTYLE 0x00000020 // This bit is set when the frame cannot be formatted due to an // error (e.g., invalid markup such as a without an overscript). // When set, a visual feedback will be provided to the user. #define NS_MATHML_ERROR 0x80000000 +// a bit used for debug +#define NS_MATHML_STRETCH_DONE 0x20000000 + // This bit is used for visual debug. When set, the bounding box // of your frame is painted. This visual debug enable to ensure that // you have properly filled your mReference and mBoundingMetrics in // Place(). -#define NS_MATHML_SHOW_BOUNDING_METRICS 0x40000000 +#define NS_MATHML_SHOW_BOUNDING_METRICS 0x10000000 // Macros that retrieve those bits @@ -394,24 +420,24 @@ struct nsEmbellishData { #define NS_MATHML_IS_COMPRESSED(_flags) \ (NS_MATHML_COMPRESSED == ((_flags) & NS_MATHML_COMPRESSED)) +#define NS_MATHML_WILL_STRETCH_ALL_CHILDREN_VERTICALLY(_flags) \ + (NS_MATHML_STRETCH_ALL_CHILDREN_VERTICALLY == ((_flags) & NS_MATHML_STRETCH_ALL_CHILDREN_VERTICALLY)) + +#define NS_MATHML_WILL_STRETCH_ALL_CHILDREN_HORIZONTALLY(_flags) \ + (NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY == ((_flags) & NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY)) + #define NS_MATHML_IS_MSTYLE_WITH_DISPLAYSTYLE(_flags) \ (NS_MATHML_MSTYLE_WITH_DISPLAYSTYLE == ((_flags) & NS_MATHML_MSTYLE_WITH_DISPLAYSTYLE)) #define NS_MATHML_IS_MSTYLE_WITH_EXPLICIT_SCRIPTLEVEL(_flags) \ (NS_MATHML_MSTYLE_WITH_EXPLICIT_SCRIPTLEVEL == ((_flags) & NS_MATHML_MSTYLE_WITH_EXPLICIT_SCRIPTLEVEL)) -#define NS_MATHML_IS_ACCENTOVER(_flags) \ - (NS_MATHML_ACCENTOVER == ((_flags) & NS_MATHML_ACCENTOVER)) - -#define NS_MATHML_IS_ACCENTUNDER(_flags) \ - (NS_MATHML_ACCENTUNDER == ((_flags) & NS_MATHML_ACCENTUNDER)) - -#define NS_MATHML_IS_MOVABLELIMITS(_flags) \ - (NS_MATHML_MOVABLELIMITS == ((_flags) & NS_MATHML_MOVABLELIMITS)) - #define NS_MATHML_HAS_ERROR(_flags) \ (NS_MATHML_ERROR == ((_flags) & NS_MATHML_ERROR)) +#define NS_MATHML_STRETCH_WAS_DONE(_flags) \ + (NS_MATHML_STRETCH_DONE == ((_flags) & NS_MATHML_STRETCH_DONE)) + #define NS_MATHML_PAINT_BOUNDING_METRICS(_flags) \ (NS_MATHML_SHOW_BOUNDING_METRICS == ((_flags) & NS_MATHML_SHOW_BOUNDING_METRICS)) @@ -422,47 +448,37 @@ struct nsEmbellishData { // This bit is set if the frame is an embellished operator. #define NS_MATHML_EMBELLISH_OPERATOR 0x00000001 -// This bit is set if the frame will fire a vertical stretch -// command on all its (non-empty) children. -// Tags like (or an inferred mrow), mpadded, etc, will fire a -// vertical stretch command on all their non-empty children -#define NS_MATHML_STRETCH_ALL_CHILDREN_VERTICALLY 0x00000002 +// This bit is set if the frame is an frame or an embellihsed +// operator for which the core has movablelimits="true" +#define NS_MATHML_EMBELLISH_MOVABLELIMITS 0x00000002 -// This bit is set if the frame will fire a horizontal stretch -// command on all its (non-empty) children. -// Tags like munder, mover, munderover, will fire a -// horizontal stretch command on all their non-empty children -#define NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY 0x00000004 +// This bit is set if the frame is an frame or an embellihsed +// operator for which the core has accent="true" +#define NS_MATHML_EMBELLISH_ACCENT 0x00000004 -// This bit is set if the frame is an frame that should behave -// like an accent XXX since it is specific, use NS_MATHML_EMBELLISH_MO_ACCENT instead? -#define NS_MATHML_EMBELLISH_ACCENT 0x00000008 +// This bit is set if the frame is an or with +// an accent frame +#define NS_MATHML_EMBELLISH_ACCENTOVER 0x00000008 -// This bit is set if the frame is an frame with the movablelimits -// attribute set to true XXX since it is specific, use NS_MATHML_EMBELLISH_MO_MOVABLELIMITS instead? -#define NS_MATHML_EMBELLISH_MOVABLELIMITS 0x00000010 - -// a bit used for debug -#define NS_MATHML_STRETCH_DONE 0x80000000 +// This bit is set if the frame is an or with +// an accentunder frame +#define NS_MATHML_EMBELLISH_ACCENTUNDER 0x00000010 // Macros that retrieve those bits #define NS_MATHML_IS_EMBELLISH_OPERATOR(_flags) \ (NS_MATHML_EMBELLISH_OPERATOR == ((_flags) & NS_MATHML_EMBELLISH_OPERATOR)) -#define NS_MATHML_WILL_STRETCH_ALL_CHILDREN_VERTICALLY(_flags) \ - (NS_MATHML_STRETCH_ALL_CHILDREN_VERTICALLY == ((_flags) & NS_MATHML_STRETCH_ALL_CHILDREN_VERTICALLY)) - -#define NS_MATHML_WILL_STRETCH_ALL_CHILDREN_HORIZONTALLY(_flags) \ - (NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY == ((_flags) & NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY)) - -#define NS_MATHML_STRETCH_WAS_DONE(_flags) \ - (NS_MATHML_STRETCH_DONE == ((_flags) & NS_MATHML_STRETCH_DONE)) +#define NS_MATHML_EMBELLISH_IS_MOVABLELIMITS(_flags) \ + (NS_MATHML_EMBELLISH_MOVABLELIMITS == ((_flags) & NS_MATHML_EMBELLISH_MOVABLELIMITS)) #define NS_MATHML_EMBELLISH_IS_ACCENT(_flags) \ (NS_MATHML_EMBELLISH_ACCENT == ((_flags) & NS_MATHML_EMBELLISH_ACCENT)) -#define NS_MATHML_EMBELLISH_IS_MOVABLELIMITS(_flags) \ - (NS_MATHML_EMBELLISH_MOVABLELIMITS == ((_flags) & NS_MATHML_EMBELLISH_MOVABLELIMITS)) +#define NS_MATHML_EMBELLISH_IS_ACCENTOVER(_flags) \ + (NS_MATHML_EMBELLISH_ACCENTOVER == ((_flags) & NS_MATHML_EMBELLISH_ACCENTOVER)) + +#define NS_MATHML_EMBELLISH_IS_ACCENTUNDER(_flags) \ + (NS_MATHML_EMBELLISH_ACCENTUNDER == ((_flags) & NS_MATHML_EMBELLISH_ACCENTUNDER)) #endif /* nsIMathMLFrame_h___ */ diff --git a/layout/mathml/base/src/nsMathMLContainerFrame.cpp b/layout/mathml/base/src/nsMathMLContainerFrame.cpp index fbd991e88ce0..54be01f1638a 100644 --- a/layout/mathml/base/src/nsMathMLContainerFrame.cpp +++ b/layout/mathml/base/src/nsMathMLContainerFrame.cpp @@ -118,8 +118,7 @@ nsMathMLContainerFrame::PaintError(nsIPresContext* aPresContext, const nsRect& aDirtyRect, nsFramePaintLayer aWhichLayer) { - if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) - { + if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) { NS_ASSERTION(NS_MATHML_HAS_ERROR(mPresentationData.flags), "There is nothing wrong with this frame!"); // Set color and font ... @@ -140,7 +139,6 @@ nsMathMLContainerFrame::PaintError(nsIPresContext* aPresContext, aRenderingContext.DrawString(errorMsg.get(), PRUint32(errorMsg.Length()), 0, ascent); - } return NS_OK; } @@ -150,35 +148,6 @@ nsMathMLContainerFrame::PaintError(nsIPresContext* aPresContext, * ============================================================================= */ -// 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.nextFrame = 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.coreFrame = embellishData.coreFrame; - mEmbellishData.direction = embellishData.direction; - } - else { - mEmbellishData.flags &= ~NS_MATHML_EMBELLISH_OPERATOR; - mEmbellishData.nextFrame = nsnull; - mEmbellishData.coreFrame = nsnull; - mEmbellishData.direction = NS_STRETCH_DIRECTION_UNSUPPORTED; - } - return NS_OK; -} - // helper method to facilitate getting the reflow and bounding metrics void nsMathMLContainerFrame::GetReflowAndBoundingMetricsFor(nsIFrame* aFrame, @@ -234,8 +203,8 @@ nsMathMLContainerFrame::GetPreferredStretchSize(nsIPresContext* aPresContex else { // compute a size that doesn't include embellishements NS_ASSERTION(NS_MATHML_IS_EMBELLISH_OPERATOR(mEmbellishData.flags) || - NS_MATHML_WILL_STRETCH_ALL_CHILDREN_HORIZONTALLY(mEmbellishData.flags) || - NS_MATHML_WILL_STRETCH_ALL_CHILDREN_VERTICALLY(mEmbellishData.flags), + NS_MATHML_WILL_STRETCH_ALL_CHILDREN_HORIZONTALLY(mPresentationData.flags) || + NS_MATHML_WILL_STRETCH_ALL_CHILDREN_VERTICALLY(mPresentationData.flags), "invalid call to GetPreferredStretchSize"); nsRect rect; PRBool firstTime = PR_TRUE; @@ -273,14 +242,14 @@ nsMathMLContainerFrame::GetPreferredStretchSize(nsIPresContext* aPresContex if (firstTime) { firstTime = PR_FALSE; bm = bmChild; - if (!NS_MATHML_WILL_STRETCH_ALL_CHILDREN_HORIZONTALLY(mEmbellishData.flags) && - !NS_MATHML_WILL_STRETCH_ALL_CHILDREN_VERTICALLY(mEmbellishData.flags)) { + if (!NS_MATHML_WILL_STRETCH_ALL_CHILDREN_HORIZONTALLY(mPresentationData.flags) && + !NS_MATHML_WILL_STRETCH_ALL_CHILDREN_VERTICALLY(mPresentationData.flags)) { // we may get here for cases such as ... ... break; } } else { - if (NS_MATHML_WILL_STRETCH_ALL_CHILDREN_HORIZONTALLY(mEmbellishData.flags)) { + if (NS_MATHML_WILL_STRETCH_ALL_CHILDREN_HORIZONTALLY(mPresentationData.flags)) { // if we get here, it means this is container that will stack its children // vertically and fire an horizontal stretch on each them. This is the case // for \munder, \mover, \munderover. We just sum-up the size vertically. @@ -290,7 +259,7 @@ nsMathMLContainerFrame::GetPreferredStretchSize(nsIPresContext* aPresContex if (bm.rightBearing < bmChild.rightBearing) bm.rightBearing = bmChild.rightBearing; } - else if (NS_MATHML_WILL_STRETCH_ALL_CHILDREN_VERTICALLY(mEmbellishData.flags)) { + else if (NS_MATHML_WILL_STRETCH_ALL_CHILDREN_VERTICALLY(mPresentationData.flags)) { // just sum-up the sizes horizontally. bm += bmChild; } @@ -314,11 +283,11 @@ nsMathMLContainerFrame::Stretch(nsIPresContext* aPresContext, { if (NS_MATHML_IS_EMBELLISH_OPERATOR(mEmbellishData.flags)) { - if (NS_MATHML_STRETCH_WAS_DONE(mEmbellishData.flags)) { + if (NS_MATHML_STRETCH_WAS_DONE(mPresentationData.flags)) { NS_WARNING("it is wrong to fire stretch more than once on a frame"); return NS_OK; } - mEmbellishData.flags |= NS_MATHML_STRETCH_DONE; + mPresentationData.flags |= NS_MATHML_STRETCH_DONE; if (NS_MATHML_HAS_ERROR(mPresentationData.flags)) { NS_WARNING("it is wrong to fire stretch on a erroneous frame"); @@ -334,8 +303,8 @@ nsMathMLContainerFrame::Stretch(nsIPresContext* aPresContext, NS_ASSERTION(mathMLFrame, "Something is wrong somewhere"); if (mathMLFrame) { PRBool stretchAll = - NS_MATHML_WILL_STRETCH_ALL_CHILDREN_VERTICALLY(mEmbellishData.flags) || - NS_MATHML_WILL_STRETCH_ALL_CHILDREN_HORIZONTALLY(mEmbellishData.flags); + NS_MATHML_WILL_STRETCH_ALL_CHILDREN_VERTICALLY(mPresentationData.flags) || + NS_MATHML_WILL_STRETCH_ALL_CHILDREN_HORIZONTALLY(mPresentationData.flags); // And the trick is that the child's rect.x is still holding the descent, // and rect.y is still holding the ascent ... @@ -382,7 +351,7 @@ nsMathMLContainerFrame::Stretch(nsIPresContext* aPresContext, if (stretchAll) { nsStretchDirection stretchDir = - NS_MATHML_WILL_STRETCH_ALL_CHILDREN_VERTICALLY(mEmbellishData.flags) ? + NS_MATHML_WILL_STRETCH_ALL_CHILDREN_VERTICALLY(mPresentationData.flags) ? NS_STRETCH_DIRECTION_VERTICAL : NS_STRETCH_DIRECTION_HORIZONTAL; GetPreferredStretchSize(aPresContext, aRenderingContext, STRETCH_CONSIDER_EMBELLISHMENTS, @@ -416,11 +385,16 @@ nsMathMLContainerFrame::Stretch(nsIPresContext* aPresContext, // container and so we put the spacing, otherwise we don't include the spacing, // the outermost embellished container will take care of it. - if (!IsEmbellishOperator(mParent)) { - + nsEmbellishData parentData; + GetEmbellishDataFrom(mParent, parentData); + // ensure that we are the embellished child, not just a sibling + // (need to test coreFrame since resets other things) + if (parentData.coreFrame != mEmbellishData.coreFrame) { + // (we fetch values from the core since they may use units that depend + // on style data, and style changes could have occured in the core since + // our last visit there) nsEmbellishData coreData; - mEmbellishData.coreFrame->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame); - mathMLFrame->GetEmbellishData(coreData); + GetEmbellishDataFrom(mEmbellishData.coreFrame, coreData); mBoundingMetrics.width += coreData.leftSpace + coreData.rightSpace; aDesiredStretchSize.width = mBoundingMetrics.width; @@ -484,15 +458,17 @@ nsMathMLContainerFrame::FinalizeReflow(nsIPresContext* aPresContext, // Don't go without checking to see if our parent will later fire a Stretch() command // targeted at us. The Stretch() will cause the rect.x and rect.y to clear... PRBool parentWillFireStretch = PR_FALSE; - nsEmbellishData parentData; nsIMathMLFrame* mathMLFrame; mParent->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame); if (mathMLFrame) { - mathMLFrame->GetEmbellishData(parentData); - if (NS_MATHML_WILL_STRETCH_ALL_CHILDREN_VERTICALLY(parentData.flags) || - NS_MATHML_WILL_STRETCH_ALL_CHILDREN_HORIZONTALLY(parentData.flags) || - (NS_MATHML_IS_EMBELLISH_OPERATOR(parentData.flags) - && parentData.nextFrame == this)) + nsEmbellishData embellishData; + nsPresentationData presentationData; + mathMLFrame->GetEmbellishData(embellishData); + mathMLFrame->GetPresentationData(presentationData); + if (NS_MATHML_WILL_STRETCH_ALL_CHILDREN_VERTICALLY(presentationData.flags) || + NS_MATHML_WILL_STRETCH_ALL_CHILDREN_HORIZONTALLY(presentationData.flags) || + (NS_MATHML_IS_EMBELLISH_OPERATOR(embellishData.flags) + && embellishData.nextFrame == this)) { parentWillFireStretch = PR_TRUE; } @@ -501,8 +477,8 @@ nsMathMLContainerFrame::FinalizeReflow(nsIPresContext* aPresContext, // There is nobody who will fire the stretch for us, we do it ourselves! PRBool stretchAll = - /* NS_MATHML_WILL_STRETCH_ALL_CHILDREN_VERTICALLY(mEmbellishData.flags) || */ - NS_MATHML_WILL_STRETCH_ALL_CHILDREN_HORIZONTALLY(mEmbellishData.flags); + /* NS_MATHML_WILL_STRETCH_ALL_CHILDREN_VERTICALLY(mPresentationData.flags) || */ + NS_MATHML_WILL_STRETCH_ALL_CHILDREN_HORIZONTALLY(mPresentationData.flags); nsBoundingMetrics defaultSize; if (mEmbellishData.coreFrame == this /* case of a bare ... itself */ @@ -860,13 +836,10 @@ nsMathMLContainerFrame::Init(nsIPresContext* aPresContext, CompressWhitespace(aContent); // let the base class do its Init() - nsresult rv; - rv = nsHTMLContainerFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow); + return nsHTMLContainerFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow); - // now, inherit the scriptlevel and displaystyle from our parent - InheritAutomaticData(aPresContext, aParent); - - return rv; + // ...We will build our automatic MathML data once the entire ... + // tree is constructed. } // This method is called in a bottom-up manner, as we ascend the frame tree @@ -877,7 +850,7 @@ nsMathMLContainerFrame::SetInitialChildList(nsIPresContext* aPresContext, nsIFrame* aChildList) { // First, let the base class do its job - nsHTMLContainerFrame::SetInitialChildList(aPresContext, aListName, aChildList); + nsresult rv = nsHTMLContainerFrame::SetInitialChildList(aPresContext, aListName, aChildList); // Next, since we are an inline frame, and since we are a container, we have to // be very careful with the way we treat our children. Things look okay when @@ -891,63 +864,55 @@ nsMathMLContainerFrame::SetInitialChildList(nsIPresContext* aPresContext, // So wrap foreign children in nsMathMLForeignFrameWrapper frames WrapForeignFrames(aPresContext); + return rv; - // Now that our subtree is fully constructed, set the automatic - // presentation data and embellishment data that apply in our subtree - return TransmitAutomaticData(aPresContext); + // ...We will build our automatic MathML data once the entire ... + // tree is constructed. } // Note that this method re-builds the automatic data in the children -- not -// in aFrame itself (except for those particular operations that the frame -// may do in aFrame->TransmitAutomaticData()). The reason it works this way -// is because a container frame knows what it wants for its children, whereas -// children have no clue who their parent is. For example, it is who -// knows that its children have to be in scriptsizes, and has to transmit this -// information to them. Hence, when changes occur in a child frame, the child -// has to pass the re-build to its parent. Unfortunately, the extra cost for -// this is that it will re-sync in the siblings of the child as well. +// in aParentFrame itself (except for those particular operations that the +// parent frame may do in its TransmitAutomaticData()). /* static */ void -nsMathMLContainerFrame::RebuildAutomaticDataFor(nsIPresContext* aPresContext, - nsIFrame* aFrame) +nsMathMLContainerFrame::RebuildAutomaticDataForChildren(nsIPresContext* aPresContext, + nsIFrame* aParentFrame) { // 1. As we descend the tree, make each child frame inherit data from // the parent // 2. As we ascend the tree, transmit any specific change that we want // down the subtrees nsIFrame* childFrame; - aFrame->FirstChild(aPresContext, nsnull, &childFrame); + aParentFrame->FirstChild(aPresContext, nsnull, &childFrame); while (childFrame) { nsIMathMLFrame* childMathMLFrame; childFrame->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&childMathMLFrame); if (childMathMLFrame) { - childMathMLFrame->InheritAutomaticData(aPresContext, aFrame); + childMathMLFrame->InheritAutomaticData(aPresContext, aParentFrame); } - RebuildAutomaticDataFor(aPresContext, childFrame); + RebuildAutomaticDataForChildren(aPresContext, childFrame); childFrame->GetNextSibling(&childFrame); } nsIMathMLFrame* mathMLFrame; - aFrame->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame); + aParentFrame->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame); if (mathMLFrame) { mathMLFrame->TransmitAutomaticData(aPresContext); } } /* static */ nsresult -nsMathMLContainerFrame::ReLayout(nsIPresContext* aPresContext, - nsIFrame* aFrame) +nsMathMLContainerFrame::ReLayoutChildren(nsIPresContext* aPresContext, + nsIFrame* aParentFrame) { // walk-up to the first frame that is a MathML frame, stop if we reach PRInt32 parentScriptLevel = 0; - nsIFrame* frame = aFrame; + nsIFrame* frame = aParentFrame; while (frame) { // stop if it is a MathML frame nsIMathMLFrame* mathMLFrame; frame->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame); if (mathMLFrame) { - nsIFrame* parent; - frame->GetParent(&parent); nsPresentationData parentData; - GetPresentationDataFrom(parent, parentData); + mathMLFrame->GetPresentationData(parentData); parentScriptLevel = parentData.scriptLevel; break; } @@ -971,7 +936,7 @@ nsMathMLContainerFrame::ReLayout(nsIPresContext* aPresContext, PRBool old = IsEmbellishOperator(frame); #endif - RebuildAutomaticDataFor(aPresContext, frame); + RebuildAutomaticDataForChildren(aPresContext, frame); #ifdef DEBUG_rbs PRBool now = IsEmbellishOperator(frame); @@ -979,8 +944,22 @@ nsMathMLContainerFrame::ReLayout(nsIPresContext* aPresContext, NS_WARNING("REMIND: case where the embellished hierarchy has to be rebuilt too"); #endif - // re-resolve the style data in our subtree to sync any change of script sizes - PropagateScriptStyleFor(aPresContext, frame, parentScriptLevel); + // re-resolve the style data to sync any change of script sizes + nsIFrame* childFrame; + aParentFrame->FirstChild(aPresContext, nsnull, &childFrame); + while (childFrame) { + nsIMathMLFrame* mathMLFrame; + childFrame->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame); + if (mathMLFrame) { + // propagate using the base method to make sure that the control + // is passed on to MathML frames that may be overloading the method + mathMLFrame->ReResolveScriptStyle(aPresContext, parentScriptLevel); + } + else { + PropagateScriptStyleFor(aPresContext, childFrame, parentScriptLevel); + } + childFrame->GetNextSibling(&childFrame); + } // Ask our parent frame to reflow us nsCOMPtr presShell; @@ -1000,7 +979,7 @@ nsMathMLContainerFrame::ChildListChanged(nsIPresContext* aPresContext, // wrap any new foreign child that may have crept in WrapForeignFrames(aPresContext); } - return ReLayout(aPresContext, this); + return ReLayoutChildren(aPresContext, this); } NS_IMETHODIMP @@ -1084,14 +1063,29 @@ nsMathMLContainerFrame::AttributeChanged(nsIPresContext* aPresContext, nsresult rv = nsHTMLContainerFrame::AttributeChanged(aPresContext, aChild, aNameSpaceID, aAttribute, aModType, aHint); if (NS_FAILED(rv)) return rv; - nsCOMPtr shell; - nsHTMLReflowCommand *reflowCmd; - aPresContext->GetShell(getter_AddRefs(shell)); - rv = NS_NewHTMLReflowCommand(&reflowCmd, this, - eReflowType_ContentChanged, - nsnull, aAttribute); - if (NS_SUCCEEDED(rv) && shell) shell->AppendReflowCommand(reflowCmd); - return rv; + + // check if this is an attribute that can affect the embellished hierarchy + // in a significant way. We handle this here to avoid duplication of code. + if (nsMathMLAtoms::accent_ == aAttribute || + nsMathMLAtoms::accentunder_ == aAttribute || + nsMathMLAtoms::movablelimits_ == aAttribute) { + + // set the target as the parent of our outermost embellished container + // (we ensure that we are the core, not just a sibling of the core) + nsIFrame* target = this; + nsEmbellishData embellishData; + do { + target->GetParent(&target); + GetEmbellishDataFrom(target, embellishData); + } while (embellishData.coreFrame == this); + + // we have automatic data to update in the children of the target frame + return ReLayoutChildren(aPresContext, target); + } + + nsCOMPtr presShell; + aPresContext->GetShell(getter_AddRefs(presShell)); + return mParent->ReflowDirtyChild(presShell, this); } // helper function to reflow token elements @@ -1319,12 +1313,12 @@ printf("\n"); // after finishing the stretching of the embellished child - bug 117652 if (!NS_MATHML_IS_EMBELLISH_OPERATOR(mEmbellishData.flags) && - (NS_MATHML_WILL_STRETCH_ALL_CHILDREN_VERTICALLY(mEmbellishData.flags) || - NS_MATHML_WILL_STRETCH_ALL_CHILDREN_HORIZONTALLY(mEmbellishData.flags))) { + (NS_MATHML_WILL_STRETCH_ALL_CHILDREN_VERTICALLY(mPresentationData.flags) || + NS_MATHML_WILL_STRETCH_ALL_CHILDREN_HORIZONTALLY(mPresentationData.flags))) { // get the stretchy direction nsStretchDirection stretchDir = - NS_MATHML_WILL_STRETCH_ALL_CHILDREN_VERTICALLY(mEmbellishData.flags) + NS_MATHML_WILL_STRETCH_ALL_CHILDREN_VERTICALLY(mPresentationData.flags) ? NS_STRETCH_DIRECTION_VERTICAL : NS_STRETCH_DIRECTION_HORIZONTAL; diff --git a/layout/mathml/base/src/nsMathMLContainerFrame.h b/layout/mathml/base/src/nsMathMLContainerFrame.h index 4f3dace21929..9f2a61c45a76 100644 --- a/layout/mathml/base/src/nsMathMLContainerFrame.h +++ b/layout/mathml/base/src/nsMathMLContainerFrame.h @@ -79,9 +79,6 @@ public: PRBool aPlaceOrigin, nsHTMLReflowMetrics& aDesiredSize); - NS_IMETHOD - EmbellishOperator(); - NS_IMETHOD UpdatePresentationDataFromChildAt(nsIPresContext* aPresContext, PRInt32 aFirstIndex, @@ -163,7 +160,7 @@ public: nsDidReflowStatus aStatus) { - mEmbellishData.flags &= ~NS_MATHML_STRETCH_DONE; + mPresentationData.flags &= ~NS_MATHML_STRETCH_DONE; return nsHTMLContainerFrame::DidReflow(aPresContext, aReflowState, aStatus); } @@ -174,6 +171,23 @@ public: nsFramePaintLayer aWhichLayer, PRUint32 aFlags = 0); + // Notification when an attribute is changed. The MathML module uses the + // following paradigm: + // + // 1. If the MathML frame class doesn't have any cached automatic data that + // depends on the attribute: we just reflow (e.g., this happens with , + // , , etc). This is the default behavior implemented + // by this base class. + // + // 2. If the MathML frame class has cached automatic data that depends on + // the attribute: + // 2a. If the automatic data to update resides only within the descendants, + // we just re-layout them using ReLayoutChildren(aPresContext, this); + // (e.g., this happens with ). + // 2b. If the automatic data to update affects us in some way, we ask our parent + // to re-layout its children using ReLayoutChildren(aPresContext, mParent); + // Therefore, there is an overhead here in that our siblings are re-laid + // too (e.g., this happens with , , , ). NS_IMETHOD AttributeChanged(nsIPresContext* aPresContext, nsIContent* aChild, @@ -185,8 +199,8 @@ public: // -------------------------------------------------------------------------- // Additional methods - // helper to sync our automatic data and notify our parent to reflow us - // when changes (e.g., append/insert/remove) happen in our child list + // helper to re-sync the automatic data in our children and notify our parent to + // reflow us when changes (e.g., append/insert/remove) happen in our child list virtual nsresult ChildListChanged(nsIPresContext* aPresContext, PRInt32 aModType); @@ -279,7 +293,7 @@ public: static void PropagateScriptStyleFor(nsIPresContext* aPresContext, nsIFrame* aFrame, - PRInt32 aFrameScriptLevel); + PRInt32 aParentScriptLevel); // helper to let the update of presentation data pass through // a subtree that may contain non-MathML container frames @@ -301,19 +315,31 @@ public: // helper to let the rebuild of automatic data (presentation data // and embellishement data) walk through a subtree that may contain - // non-MathML container frames + // non-MathML container frames. Note that this method re-builds the + // automatic data in the children -- not in aParentFrame itself (except + // for those particular operations that the parent frame may do in its + // TransmitAutomaticData()). The reason it works this way is because + // a container frame knows what it wants for its children, whereas children + // have no clue who their parent is. For example, it is who knows + // that its children have to be in scriptsizes, and has to transmit this + // information to them. Hence, when changes occur in a child frame, the child + // has to request the re-build from its parent. Unfortunately, the extra cost + // for this is that it will re-sync in the siblings of the child as well. static void - RebuildAutomaticDataFor(nsIPresContext* aPresContext, - nsIFrame* aFrame); + RebuildAutomaticDataForChildren(nsIPresContext* aPresContext, + nsIFrame* aParentFrame); // helper to blow away the automatic data cached in a frame's subtree and // re-layout its subtree to reflect changes that may have happen. In the - // event where aFrame isn't a MathML frame, it will first walk up to the - // ancestor that is a MathML frame, and re-layout from there -- this is to - // guarantee that automatic data will be rebuilt properly. + // event where aParentFrame isn't a MathML frame, it will first walk up to + // the ancestor that is a MathML frame, and re-layout from there -- this is + // to guarantee that automatic data will be rebuilt properly. Note that this + // method re-builds the automatic data in the children -- not in the parent + // frame itself (except for those particular operations that the parent frame + // may do do its TransmitAutomaticData()). @see RebuildAutomaticDataForChildren static nsresult - ReLayout(nsIPresContext* aPresContext, - nsIFrame* aFrame); + ReLayoutChildren(nsIPresContext* aPresContext, + nsIFrame* aParentFrame); protected: virtual PRIntn GetSkipSides() const { return 0; } @@ -340,7 +366,8 @@ public: nsIFrame* aChildList) { nsresult rv = nsBlockFrame::SetInitialChildList(aPresContext, aListName, aChildList); - // re-resolve our subtree to set any mathml-expected scriptsizes + // re-resolve our subtree to set any mathml-expected data + nsMathMLContainerFrame::RebuildAutomaticDataForChildren(aPresContext, this); nsMathMLContainerFrame::PropagateScriptStyleFor(aPresContext, this, 0); return rv; } @@ -352,7 +379,7 @@ public: nsIFrame* aFrameList) { nsresult rv = nsBlockFrame::AppendFrames(aPresContext, aPresShell, aListName, aFrameList); - nsMathMLContainerFrame::ReLayout(aPresContext, this); + nsMathMLContainerFrame::ReLayoutChildren(aPresContext, this); return rv; } @@ -364,7 +391,7 @@ public: nsIFrame* aFrameList) { nsresult rv = nsBlockFrame::InsertFrames(aPresContext, aPresShell, aListName, aPrevFrame, aFrameList); - nsMathMLContainerFrame::ReLayout(aPresContext, this); + nsMathMLContainerFrame::ReLayoutChildren(aPresContext, this); return rv; } @@ -376,7 +403,7 @@ public: nsIFrame* aNewFrame) { nsresult rv = nsBlockFrame::ReplaceFrame(aPresContext, aPresShell, aListName, aOldFrame, aNewFrame); - nsMathMLContainerFrame::ReLayout(aPresContext, this); + nsMathMLContainerFrame::ReLayoutChildren(aPresContext, this); return rv; } @@ -387,7 +414,7 @@ public: nsIFrame* aOldFrame) { nsresult rv = nsBlockFrame::RemoveFrame(aPresContext, aPresShell, aListName, aOldFrame); - nsMathMLContainerFrame::ReLayout(aPresContext, this); + nsMathMLContainerFrame::ReLayoutChildren(aPresContext, this); return rv; } @@ -408,7 +435,8 @@ public: nsIFrame* aChildList) { nsresult rv = nsInlineFrame::SetInitialChildList(aPresContext, aListName, aChildList); - // re-resolve our subtree to set any mathml-expected scriptsizes + // re-resolve our subtree to set any mathml-expected data + nsMathMLContainerFrame::RebuildAutomaticDataForChildren(aPresContext, this); nsMathMLContainerFrame::PropagateScriptStyleFor(aPresContext, this, 0); return rv; } @@ -420,7 +448,7 @@ public: nsIFrame* aFrameList) { nsresult rv = nsInlineFrame::AppendFrames(aPresContext, aPresShell, aListName, aFrameList); - nsMathMLContainerFrame::ReLayout(aPresContext, this); + nsMathMLContainerFrame::ReLayoutChildren(aPresContext, this); return rv; } @@ -432,7 +460,7 @@ public: nsIFrame* aFrameList) { nsresult rv = nsInlineFrame::InsertFrames(aPresContext, aPresShell, aListName, aPrevFrame, aFrameList); - nsMathMLContainerFrame::ReLayout(aPresContext, this); + nsMathMLContainerFrame::ReLayoutChildren(aPresContext, this); return rv; } @@ -444,7 +472,7 @@ public: nsIFrame* aNewFrame) { nsresult rv = nsInlineFrame::ReplaceFrame(aPresContext, aPresShell, aListName, aOldFrame, aNewFrame); - nsMathMLContainerFrame::ReLayout(aPresContext, this); + nsMathMLContainerFrame::ReLayoutChildren(aPresContext, this); return rv; } @@ -455,7 +483,7 @@ public: nsIFrame* aOldFrame) { nsresult rv = nsInlineFrame::RemoveFrame(aPresContext, aPresShell, aListName, aOldFrame); - nsMathMLContainerFrame::ReLayout(aPresContext, this); + nsMathMLContainerFrame::ReLayoutChildren(aPresContext, this); return rv; } diff --git a/layout/mathml/base/src/nsMathMLForeignFrameWrapper.cpp b/layout/mathml/base/src/nsMathMLForeignFrameWrapper.cpp index 4ff7051ab401..5aa7981bc6b3 100644 --- a/layout/mathml/base/src/nsMathMLForeignFrameWrapper.cpp +++ b/layout/mathml/base/src/nsMathMLForeignFrameWrapper.cpp @@ -69,13 +69,7 @@ nsMathMLForeignFrameWrapper::Init(nsIPresContext* aPresContext, nsIStyleContext* aContext, nsIFrame* aPrevInFlow) { - nsresult rv; - rv = nsBlockFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow); - - // let the base class inherit the scriptlevel and displaystyle from our parent - nsMathMLFrame::InheritAutomaticData(aPresContext, aParent); - - return rv; + return nsBlockFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow); } NS_IMETHODIMP diff --git a/layout/mathml/base/src/nsMathMLFrame.cpp b/layout/mathml/base/src/nsMathMLFrame.cpp index d5c107ec4836..a4eca425aadb 100644 --- a/layout/mathml/base/src/nsMathMLFrame.cpp +++ b/layout/mathml/base/src/nsMathMLFrame.cpp @@ -29,18 +29,30 @@ NS_IMETHODIMP nsMathMLFrame::InheritAutomaticData(nsIPresContext* aPresContext, nsIFrame* aParent) { - mPresentationData.flags = 0; - mPresentationData.mstyle = nsnull; - mPresentationData.scriptLevel = 0; - mEmbellishData.flags = 0; mEmbellishData.nextFrame = nsnull; mEmbellishData.coreFrame = nsnull; mEmbellishData.direction = NS_STRETCH_DIRECTION_UNSUPPORTED; - mEmbellishData.leftSpace = mEmbellishData.rightSpace = 0; + mEmbellishData.leftSpace = 0; + mEmbellishData.rightSpace = 0; + + mPresentationData.flags = 0; + mPresentationData.mstyle = nsnull; + mPresentationData.scriptLevel = 0; // by default, just inherit the display & scriptlevel of our parent - GetPresentationDataFrom(aParent, mPresentationData); + nsPresentationData parentData; + GetPresentationDataFrom(aParent, parentData); + mPresentationData.mstyle = parentData.mstyle; + mPresentationData.scriptLevel = parentData.scriptLevel; + if (NS_MATHML_IS_DISPLAYSTYLE(parentData.flags)) { + mPresentationData.flags |= NS_MATHML_DISPLAYSTYLE; + } + +#if defined(NS_DEBUG) && defined(SHOW_BOUNDING_BOX) + mPresentationData.flags |= NS_MATHML_SHOW_BOUNDING_METRICS; +#endif + return NS_OK; } @@ -72,63 +84,79 @@ nsMathMLFrame::UpdatePresentationData(nsIPresContext* aPresContext, return NS_OK; } -/* static */ PRBool -nsMathMLFrame::IsEmbellishOperator(nsIFrame* aFrame) -{ - NS_PRECONDITION(aFrame, "null arg"); - if (!aFrame) return PR_FALSE; - nsIMathMLFrame* mathMLFrame; - aFrame->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame); - if (!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 +/* static */ void nsMathMLFrame::ResolveMathMLCharStyle(nsIPresContext* aPresContext, nsIContent* aContent, nsIStyleContext* aParentStyleContext, - nsMathMLChar* aMathMLChar) + nsMathMLChar* aMathMLChar, + PRBool aIsMutableChar) { - nsAutoString data; - aMathMLChar->GetData(data); - PRBool isStretchy = nsMathMLOperators::IsMutableOperator(data); - nsIAtom* fontAtom = (isStretchy) ? + nsIAtom* fontAtom = (aIsMutableChar) ? nsMathMLAtoms::fontstyle_stretchy : - nsMathMLAtoms::fontstyle_anonymous; + nsMathMLAtoms::fontstyle_anonymous; // savings nsCOMPtr newStyleContext; nsresult rv = aPresContext->ResolvePseudoStyleContextFor(aContent, fontAtom, aParentStyleContext, PR_FALSE, getter_AddRefs(newStyleContext)); if (NS_SUCCEEDED(rv) && newStyleContext) aMathMLChar->SetStyleContext(newStyleContext); +} - return isStretchy; +/* static */ PRBool +nsMathMLFrame::IsEmbellishOperator(nsIFrame* aFrame) +{ + nsEmbellishData embellishData; + GetEmbellishDataFrom(aFrame, embellishData); + return NS_MATHML_IS_EMBELLISH_OPERATOR(embellishData.flags); +} + +/* static */ void +nsMathMLFrame::GetEmbellishDataFrom(nsIFrame* aFrame, + nsEmbellishData& aEmbellishData) +{ + // initialize OUT params + aEmbellishData.flags = 0; + aEmbellishData.nextFrame = nsnull; + aEmbellishData.coreFrame = nsnull; + aEmbellishData.direction = NS_STRETCH_DIRECTION_UNSUPPORTED; + aEmbellishData.leftSpace = 0; + aEmbellishData.rightSpace = 0; + + if (aFrame) { + nsIMathMLFrame* mathMLFrame; + aFrame->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame); + if (mathMLFrame) { + mathMLFrame->GetEmbellishData(aEmbellishData); + } + } } // helper to get the presentation data of a frame, by possibly walking up // the frame hierarchy if we happen to be surrounded by non-MathML frames. /* static */ void nsMathMLFrame::GetPresentationDataFrom(nsIFrame* aFrame, - nsPresentationData& aPresentationData) + nsPresentationData& aPresentationData, + PRBool aClimbTree) { + // initialize OUT params + aPresentationData.flags = 0; + aPresentationData.mstyle = nsnull; + aPresentationData.scriptLevel = 0; + nsIFrame* frame = aFrame; while (frame) { nsIMathMLFrame* mathMLFrame; frame->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame); if (mathMLFrame) { - nsPresentationData presentationData; - mathMLFrame->GetPresentationData(presentationData); - aPresentationData.mstyle = presentationData.mstyle; - aPresentationData.scriptLevel = presentationData.scriptLevel; - if (NS_MATHML_IS_DISPLAYSTYLE(presentationData.flags)) { - aPresentationData.flags |= NS_MATHML_DISPLAYSTYLE; - } + mathMLFrame->GetPresentationData(aPresentationData); + break; + } + // stop if the caller doesn't want to lookup beyond the frame + if (!aClimbTree) { break; } // stop if we reach the root tag @@ -148,6 +176,17 @@ nsMathMLFrame::GetPresentationDataFrom(nsIFrame* aFrame, } } +/* static */ PRBool +nsMathMLFrame::HasNextSibling(nsIFrame* aFrame) +{ + if (aFrame) { + nsIFrame* sibling; + aFrame->GetNextSibling(&sibling); + return sibling != nsnull; + } + return PR_FALSE; +} + // helper to get an attribute from the content or the surrounding hierarchy /* static */ nsresult nsMathMLFrame::GetAttribute(nsIContent* aContent, diff --git a/layout/mathml/base/src/nsMathMLFrame.h b/layout/mathml/base/src/nsMathMLFrame.h index f51f8bdb6a85..a93473136350 100644 --- a/layout/mathml/base/src/nsMathMLFrame.h +++ b/layout/mathml/base/src/nsMathMLFrame.h @@ -98,11 +98,6 @@ public: return NS_OK; } - NS_IMETHOD - EmbellishOperator() { - return NS_OK; - } - NS_IMETHOD GetEmbellishData(nsEmbellishData& aEmbellishData) { aEmbellishData = mEmbellishData; @@ -164,24 +159,47 @@ public: // 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 + static void ResolveMathMLCharStyle(nsIPresContext* aPresContext, nsIContent* aContent, nsIStyleContext* aParenStyleContext, - nsMathMLChar* aMathMLChar); + nsMathMLChar* aMathMLChar, + PRBool aIsMutableChar); // helper to check if a frame is embellished + // The MathML REC precisely defines an "embellished operator" as: + // - an element; + // - or one of the elements , , , , , + // , , , or , whose first + // argument exists and is an embellished operator; + //- or one of the elements , , or , such that + // an containing the same arguments would be an embellished + // operator; + // - or an element whose selected subexpression exists and is an + // embellished operator; + // - or an whose arguments consist (in any order) of one embellished + // operator and zero or more spacelike elements. static PRBool IsEmbellishOperator(nsIFrame* aFrame); - // helper to get the presentation data of a frame. If we happen to - // be surrounded by non-MathML helper frames needed for our support, - // we walk up the frame hierarchy until we reach a MathML frame - // or the math element. + // helper to get the mEmbellishData of a frame + static void + GetEmbellishDataFrom(nsIFrame* aFrame, + nsEmbellishData& aEmbellishData); + + // helper to get the presentation data of a frame. If aClimbTree is + // set to true and the frame happens to be surrounded by non-MathML + // helper frames needed for its support, we walk up the frame hierarchy + // until we reach a MathML ancestor or the math element. static void GetPresentationDataFrom(nsIFrame* aFrame, - nsPresentationData& aPresentationData); + nsPresentationData& aPresentationData, + PRBool aClimbTree = PR_TRUE); + + // helper to check if a frame has a next sibling - used to report + // an error when a next sibling is found where unexpected + static PRBool + HasNextSibling(nsIFrame* aFrame); // 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 diff --git a/layout/mathml/base/src/nsMathMLmactionFrame.cpp b/layout/mathml/base/src/nsMathMLmactionFrame.cpp index ec753d41de5c..4b67b529327a 100644 --- a/layout/mathml/base/src/nsMathMLmactionFrame.cpp +++ b/layout/mathml/base/src/nsMathMLmactionFrame.cpp @@ -99,7 +99,6 @@ nsMathMLmactionFrame::Init(nsIPresContext* aPresContext, nsIStyleContext* aContext, nsIFrame* aPrevInFlow) { - nsresult rv; nsAutoString value, prefix; // Init our local attributes @@ -166,13 +165,7 @@ nsMathMLmactionFrame::Init(nsIPresContext* aPresContext, } // Let the base class do the rest - rv = nsMathMLContainerFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow); - -#if defined(NS_DEBUG) && defined(SHOW_BOUNDING_BOX) - mPresentationData.flags |= NS_MATHML_SHOW_BOUNDING_METRICS; -#endif - - return rv; + return nsMathMLContainerFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow); } // return the frame whose number is given by the attribute selection="number" @@ -221,23 +214,9 @@ nsMathMLmactionFrame::GetSelectedFrame() // if the selected child is an embellished operator, // we become embellished as well - mEmbellishData.flags &= ~NS_MATHML_EMBELLISH_OPERATOR; - mEmbellishData.nextFrame = nsnull; - mEmbellishData.coreFrame = nsnull; - mEmbellishData.direction = NS_STRETCH_DIRECTION_UNSUPPORTED; - if (mSelectedFrame) { - nsIMathMLFrame* mathMLFrame; - mSelectedFrame->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame); - if (mathMLFrame) { - nsEmbellishData embellishData; - mathMLFrame->GetEmbellishData(embellishData); - if (NS_MATHML_IS_EMBELLISH_OPERATOR(embellishData.flags)) { - mEmbellishData.flags |= NS_MATHML_EMBELLISH_OPERATOR; - mEmbellishData.nextFrame = mSelectedFrame; // yes! - mEmbellishData.coreFrame = embellishData.coreFrame; - mEmbellishData.direction = embellishData.direction; - } - } + GetEmbellishDataFrom(mSelectedFrame, mEmbellishData); + if (NS_MATHML_IS_EMBELLISH_OPERATOR(mEmbellishData.flags)) { + mEmbellishData.nextFrame = mSelectedFrame; // yes! } return mSelectedFrame; @@ -316,8 +295,7 @@ nsMathMLmactionFrame::Paint(nsIPresContext* aPresContext, #if defined(NS_DEBUG) && defined(SHOW_BOUNDING_BOX) // visual debug if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer && - NS_MATHML_PAINT_BOUNDING_METRICS(mPresentationData.flags)) - { + NS_MATHML_PAINT_BOUNDING_METRICS(mPresentationData.flags)) { aRenderingContext.SetColor(NS_RGB(0,0,255)); nscoord x = mReference.x + mBoundingMetrics.leftBearing; diff --git a/layout/mathml/base/src/nsMathMLmfencedFrame.cpp b/layout/mathml/base/src/nsMathMLmfencedFrame.cpp index edae9ff7aa25..e35df28f4165 100644 --- a/layout/mathml/base/src/nsMathMLmfencedFrame.cpp +++ b/layout/mathml/base/src/nsMathMLmfencedFrame.cpp @@ -69,41 +69,46 @@ nsMathMLmfencedFrame::~nsMathMLmfencedFrame() } NS_IMETHODIMP -nsMathMLmfencedFrame::Init(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIFrame* aParent, - nsIStyleContext* aContext, - nsIFrame* aPrevInFlow) +nsMathMLmfencedFrame::InheritAutomaticData(nsIPresContext* aPresContext, + nsIFrame* aParent) { - nsresult rv = nsMathMLContainerFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow); + // let the base class get the default from our parent + nsMathMLContainerFrame::InheritAutomaticData(aPresContext, aParent); - mEmbellishData.flags |= NS_MATHML_STRETCH_ALL_CHILDREN_VERTICALLY; + mPresentationData.flags |= NS_MATHML_STRETCH_ALL_CHILDREN_VERTICALLY; - mOpenChar = nsnull; - mCloseChar = nsnull; - mSeparatorsChar = nsnull; - mSeparatorsCount = 0; - -#if defined(NS_DEBUG) && defined(SHOW_BOUNDING_BOX) - mPresentationData.flags |= NS_MATHML_SHOW_BOUNDING_METRICS; -#endif - return rv; + return NS_OK; } - NS_IMETHODIMP nsMathMLmfencedFrame::SetInitialChildList(nsIPresContext* aPresContext, nsIAtom* aListName, nsIFrame* aChildList) { - nsresult rv; - // First, let the base class do its work - rv = nsMathMLContainerFrame::SetInitialChildList(aPresContext, aListName, aChildList); + nsresult rv = nsMathMLContainerFrame::SetInitialChildList(aPresContext, aListName, aChildList); if (NS_FAILED(rv)) return rv; - rv = CreateFencesAndSeparators(aPresContext); - return rv; + // No need to tract the style contexts given to our MathML chars. + // The Style System will use Get/SetAdditionalStyleContext() to keep them + // up-to-date if dynamic changes arise. + return CreateFencesAndSeparators(aPresContext); +} + +NS_IMETHODIMP +nsMathMLmfencedFrame::AttributeChanged(nsIPresContext* aPresContext, + nsIContent* aContent, + PRInt32 aNameSpaceID, + nsIAtom* aAttribute, + PRInt32 aModType, + PRInt32 aHint) +{ + RemoveFencesAndSeparators(); + CreateFencesAndSeparators(aPresContext); + + return nsMathMLContainerFrame:: + AttributeChanged(aPresContext, aContent, aNameSpaceID, + aAttribute, aModType, aHint); } void @@ -112,7 +117,7 @@ nsMathMLmfencedFrame::RemoveFencesAndSeparators() if (mOpenChar) delete mOpenChar; if (mCloseChar) delete mCloseChar; if (mSeparatorsChar) delete[] mSeparatorsChar; - + mOpenChar = nsnull; mCloseChar = nsnull; mSeparatorsChar = nsnull; @@ -123,8 +128,8 @@ nsresult nsMathMLmfencedFrame::CreateFencesAndSeparators(nsIPresContext* aPresContext) { nsresult rv; - nsAutoString value, data; + PRBool isMutable; ////////////// // see if the opening fence is there ... @@ -143,7 +148,8 @@ nsMathMLmfencedFrame::CreateFencesAndSeparators(nsIPresContext* aPresContext) mOpenChar = new nsMathMLChar; if (!mOpenChar) return NS_ERROR_OUT_OF_MEMORY; mOpenChar->SetData(aPresContext, data); - ResolveMathMLCharStyle(aPresContext, mContent, mStyleContext, mOpenChar); + isMutable = nsMathMLOperators::IsMutableOperator(data); + ResolveMathMLCharStyle(aPresContext, mContent, mStyleContext, mOpenChar, isMutable); } ////////////// @@ -163,7 +169,8 @@ nsMathMLmfencedFrame::CreateFencesAndSeparators(nsIPresContext* aPresContext) mCloseChar = new nsMathMLChar; if (!mCloseChar) return NS_ERROR_OUT_OF_MEMORY; mCloseChar->SetData(aPresContext, data); - ResolveMathMLCharStyle(aPresContext, mContent, mStyleContext, mCloseChar); + isMutable = nsMathMLOperators::IsMutableOperator(data); + ResolveMathMLCharStyle(aPresContext, mContent, mStyleContext, mCloseChar, isMutable); } ////////////// @@ -192,12 +199,16 @@ nsMathMLmfencedFrame::CreateFencesAndSeparators(nsIPresContext* aPresContext) if (!mSeparatorsChar) return NS_ERROR_OUT_OF_MEMORY; nsAutoString sepChar; for (PRInt32 i = 0; i < sepCount; i++) { - if (i < mSeparatorsCount) + if (i < mSeparatorsCount) { sepChar = data[i]; - else + isMutable = nsMathMLOperators::IsMutableOperator(sepChar); + } + else { sepChar = data[mSeparatorsCount-1]; + // keep the value of isMutable that was set earlier + } mSeparatorsChar[i].SetData(aPresContext, sepChar); - ResolveMathMLCharStyle(aPresContext, mContent, mStyleContext, &mSeparatorsChar[i]); + ResolveMathMLCharStyle(aPresContext, mContent, mStyleContext, &mSeparatorsChar[i], isMutable); } } mSeparatorsCount = sepCount; @@ -212,12 +223,10 @@ nsMathMLmfencedFrame::Paint(nsIPresContext* aPresContext, nsFramePaintLayer aWhichLayer, PRUint32 aFlags) { - nsresult rv = NS_OK; - ///////////// // paint the content - rv = nsMathMLContainerFrame::Paint(aPresContext, aRenderingContext, - aDirtyRect, aWhichLayer); + nsresult rv = nsMathMLContainerFrame::Paint(aPresContext, aRenderingContext, + aDirtyRect, aWhichLayer); //////////// // paint fences and separators if (NS_SUCCEEDED(rv)) { @@ -317,9 +326,9 @@ nsMathMLmfencedFrame::doReflow(nsIPresContext* aPresContext, nsBoundingMetrics containerSize; nsStretchDirection stretchDir = NS_STRETCH_DIRECTION_VERTICAL; - nsEmbellishData embellishData; - mathMLFrame->GetEmbellishData(embellishData); - if (!NS_MATHML_WILL_STRETCH_ALL_CHILDREN_VERTICALLY(embellishData.flags)) { + nsPresentationData presentationData; + mathMLFrame->GetPresentationData(presentationData); + if (!NS_MATHML_WILL_STRETCH_ALL_CHILDREN_VERTICALLY(presentationData.flags)) { // case when the call is made for mfrac, we only need to stretch the '/' separator containerSize = aDesiredSize.mBoundingMetrics; // computed earlier } @@ -331,8 +340,8 @@ nsMathMLmfencedFrame::doReflow(nsIPresContext* aPresContext, childFrame = fisrtChild; while (childFrame) { nsIMathMLFrame* mathmlChild; - rv = childFrame->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathmlChild); - if (NS_SUCCEEDED(rv) && mathmlChild) { + childFrame->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathmlChild); + if (mathmlChild) { // retrieve the metrics that was stored at the previous pass GetReflowAndBoundingMetricsFor(childFrame, childDesiredSize, childDesiredSize.mBoundingMetrics); @@ -372,9 +381,6 @@ nsMathMLmfencedFrame::doReflow(nsIPresContext* aPresContext, containerSize.ascent = delta + axisHeight; containerSize.descent = delta - axisHeight; - nsPresentationData presentationData; - mathMLFrame->GetPresentationData(presentationData); - ///////////////// // opening fence ... ReflowChar(aPresContext, *aReflowState.rendContext, aOpenChar, diff --git a/layout/mathml/base/src/nsMathMLmfencedFrame.h b/layout/mathml/base/src/nsMathMLmfencedFrame.h index e7763caea09c..4d97844eee1b 100644 --- a/layout/mathml/base/src/nsMathMLmfencedFrame.h +++ b/layout/mathml/base/src/nsMathMLmfencedFrame.h @@ -42,11 +42,8 @@ public: nsIStyleContext** aStyleContext) const; NS_IMETHOD - Init(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIFrame* aParent, - nsIStyleContext* aContext, - nsIFrame* aPrevInFlow); + InheritAutomaticData(nsIPresContext* aPresContext, + nsIFrame* aParent); NS_IMETHOD SetInitialChildList(nsIPresContext* aPresContext, @@ -66,6 +63,14 @@ public: nsFramePaintLayer aWhichLayer, PRUint32 aFlags = 0); + NS_IMETHOD + AttributeChanged(nsIPresContext* aPresContext, + nsIContent* aContent, + PRInt32 aNameSpaceID, + nsIAtom* aAttribute, + PRInt32 aModType, + PRInt32 aHint); + // exported routine that both mfenced and mfrac share. // mfrac uses this when its bevelled attribute is set. static nsresult diff --git a/layout/mathml/base/src/nsMathMLmfracFrame.cpp b/layout/mathml/base/src/nsMathMLmfracFrame.cpp index dc2a74581384..c5d9414e3d7f 100644 --- a/layout/mathml/base/src/nsMathMLmfracFrame.cpp +++ b/layout/mathml/base/src/nsMathMLmfracFrame.cpp @@ -88,6 +88,20 @@ nsMathMLmfracFrame::~nsMathMLmfracFrame() } } +PRBool +nsMathMLmfracFrame::IsBevelled() +{ + nsAutoString value; + if (NS_CONTENT_ATTR_HAS_VALUE == + GetAttribute(mContent, mPresentationData.mstyle, + nsMathMLAtoms::bevelled_, value)) { + if (value.Equals(NS_LITERAL_STRING("true"))) { + return PR_TRUE; + } + } + return PR_FALSE; +} + NS_IMETHODIMP nsMathMLmfracFrame::Init(nsIPresContext* aPresContext, nsIContent* aContent, @@ -104,7 +118,7 @@ nsMathMLmfracFrame::Init(nsIPresContext* aPresContext, if (mSlashChar) { nsAutoString slashChar; slashChar.Assign(kSlashChar); mSlashChar->SetData(aPresContext, slashChar); - ResolveMathMLCharStyle(aPresContext, mContent, mStyleContext, mSlashChar); + ResolveMathMLCharStyle(aPresContext, mContent, mStyleContext, mSlashChar, PR_TRUE); } } @@ -114,10 +128,6 @@ nsMathMLmfracFrame::Init(nsIPresContext* aPresContext, NS_IMETHODIMP nsMathMLmfracFrame::TransmitAutomaticData(nsIPresContext* aPresContext) { -#if defined(NS_DEBUG) && defined(SHOW_BOUNDING_BOX) - mPresentationData.flags |= NS_MATHML_SHOW_BOUNDING_METRICS; -#endif - // 1. The REC says: // The element sets displaystyle to "false", or if it was already // false increments scriptlevel by 1, within numerator and denominator. @@ -132,14 +142,18 @@ nsMathMLmfracFrame::TransmitAutomaticData(nsIPresContext* aPresContext) UpdatePresentationDataFromChildAt(aPresContext, 1, 1, 0, NS_MATHML_COMPRESSED, NS_MATHML_COMPRESSED); - // check whether or not this is an embellished operator - EmbellishOperator(); - // even when embellished, we need to record that won't fire - // Stretch() on its embellished child - mEmbellishData.direction = NS_STRETCH_DIRECTION_UNSUPPORTED; - // break the embellished hierarchy to stop propagating the stretching - // process, but keep access to mEmbellishData.coreFrame for convenience - mEmbellishData.nextFrame = nsnull; + + // if our numerator is an embellished operator, let its state bubble to us + GetEmbellishDataFrom(mFrames.FirstChild(), mEmbellishData); + if (NS_MATHML_IS_EMBELLISH_OPERATOR(mEmbellishData.flags)) { + // even when embellished, we need to record that won't fire + // Stretch() on its embellished child + mEmbellishData.direction = NS_STRETCH_DIRECTION_UNSUPPORTED; + // break the embellished hierarchy to stop propagating the stretching + // process, but keep access to mEmbellishData.coreFrame for convenience + mEmbellishData.nextFrame = nsnull; + } + return NS_OK; } @@ -253,34 +267,20 @@ nsMathMLmfracFrame::Place(nsIPresContext* aPresContext, //////////////////////////////////// // Get the children's desired sizes - PRInt32 count = 0; nsBoundingMetrics bmNum, bmDen; nsHTMLReflowMetrics sizeNum (nsnull); nsHTMLReflowMetrics sizeDen (nsnull); - nsIFrame* frameNum = nsnull; nsIFrame* frameDen = nsnull; - - nsIFrame* childFrame = mFrames.FirstChild(); - while (childFrame) { - if (0 == count) { - // numerator - frameNum = childFrame; - GetReflowAndBoundingMetricsFor(frameNum, sizeNum, bmNum); - } - else if (1 == count) { - // denominator - frameDen = childFrame; - GetReflowAndBoundingMetricsFor(frameDen, sizeDen, bmDen); - } - count++; - - childFrame->GetNextSibling(&childFrame); - } - if (2 != count) { + nsIFrame* frameNum = mFrames.FirstChild(); + if (frameNum) + frameNum->GetNextSibling(&frameDen); + if (!frameNum || !frameDen || HasNextSibling(frameDen)) { // report an error, encourage people to get their markups in order NS_WARNING("invalid markup"); return ReflowError(aPresContext, aRenderingContext, aDesiredSize); } + GetReflowAndBoundingMetricsFor(frameNum, sizeNum, bmNum); + GetReflowAndBoundingMetricsFor(frameDen, sizeDen, bmDen); ////////////////// // Get shifts @@ -300,19 +300,14 @@ nsMathMLmfracFrame::Place(nsIPresContext* aPresContext, GetAxisHeight(aRenderingContext, fm, axisHeight); // by default, leave at least one-pixel padding at either end, or use - // lspace & rspace from if we are an embellished container - nscoord leftSpace = onePixel; - nscoord rightSpace = onePixel; - if (mEmbellishData.coreFrame) { - nsEmbellishData coreData; - nsIMathMLFrame* mathMLFrame; - mEmbellishData.coreFrame->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame); - mathMLFrame->GetEmbellishData(coreData); - leftSpace = coreData.leftSpace; - rightSpace = coreData.rightSpace; - } - if (leftSpace < onePixel) leftSpace = onePixel; - if (rightSpace < onePixel) rightSpace = onePixel; + // lspace & rspace that may come from if we are an embellished container + // (we fetch values from the core since they may use units that depend + // on style data, and style changes could have occured in the core since + // our last visit there) + nsEmbellishData coreData; + GetEmbellishDataFrom(mEmbellishData.coreFrame, coreData); + nscoord leftSpace = PR_MAX(onePixel, coreData.leftSpace); + nscoord rightSpace = PR_MAX(onePixel, coreData.rightSpace); // see if the linethickness attribute is there nsAutoString value; @@ -476,7 +471,7 @@ nsMathMLmfracFrame::AttributeChanged(nsIPresContext* aPresContext, if (mSlashChar) { nsAutoString slashChar; slashChar.Assign(kSlashChar); mSlashChar->SetData(aPresContext, slashChar); - ResolveMathMLCharStyle(aPresContext, mContent, mStyleContext, mSlashChar); + ResolveMathMLCharStyle(aPresContext, mContent, mStyleContext, mSlashChar, PR_TRUE); } } } diff --git a/layout/mathml/base/src/nsMathMLmfracFrame.h b/layout/mathml/base/src/nsMathMLmfracFrame.h index 0a260fb70545..0eecfcfdc3e8 100644 --- a/layout/mathml/base/src/nsMathMLmfracFrame.h +++ b/layout/mathml/base/src/nsMathMLmfracFrame.h @@ -144,18 +144,7 @@ protected: virtual PRIntn GetSkipSides() const { return 0; } PRBool - IsBevelled() - { - nsAutoString value; - if (NS_CONTENT_ATTR_HAS_VALUE == - GetAttribute(mContent, mPresentationData.mstyle, - nsMathMLAtoms::bevelled_, value)) { - if (value.Equals(NS_LITERAL_STRING("true"))) { - return PR_TRUE; - } - } - return PR_FALSE; - } + IsBevelled(); PRInt32 mInnerScriptLevel; nsRect mLineRect; diff --git a/layout/mathml/base/src/nsMathMLmiFrame.cpp b/layout/mathml/base/src/nsMathMLmiFrame.cpp index 70008af9d050..a5789d62c7b9 100644 --- a/layout/mathml/base/src/nsMathMLmiFrame.cpp +++ b/layout/mathml/base/src/nsMathMLmiFrame.cpp @@ -74,13 +74,9 @@ IsStyleInvariant(PRUnichar aChar) } // if our content is not a single character, we turn the font to normal -NS_IMETHODIMP -nsMathMLmiFrame::TransmitAutomaticData(nsIPresContext* aPresContext) +void +nsMathMLmiFrame::ProcessTextData(nsIPresContext* aPresContext) { -#if defined(NS_DEBUG) && defined(SHOW_BOUNDING_BOX) - mPresentationData.flags |= NS_MATHML_SHOW_BOUNDING_METRICS; -#endif - // Get the text content that we enclose and its length // our content can include comment-nodes, attribute-nodes, text-nodes... // we use the DOM to make sure that we are only looking at text-nodes... @@ -119,7 +115,7 @@ nsMathMLmiFrame::TransmitAutomaticData(nsIPresContext* aPresContext) nsMathMLAtoms::fontstyle_, fontstyle)) { if (fontstyle.Equals(NS_LITERAL_STRING("italic"))) - return NS_OK; + return; } } @@ -142,7 +138,20 @@ nsMathMLmiFrame::TransmitAutomaticData(nsIPresContext* aPresContext) } } } - return NS_OK; +} + +NS_IMETHODIMP +nsMathMLmiFrame::SetInitialChildList(nsIPresContext* aPresContext, + nsIAtom* aListName, + nsIFrame* aChildList) +{ + // First, let the base class do its work + nsresult rv = nsMathMLContainerFrame::SetInitialChildList(aPresContext, aListName, aChildList); + if (NS_FAILED(rv)) return rv; + + // re-style our content depending on what it is + ProcessTextData(aPresContext); + return rv; } NS_IMETHODIMP @@ -164,3 +173,17 @@ nsMathMLmiFrame::Place(nsIPresContext* aPresContext, return PlaceTokenFor(this, aPresContext, aRenderingContext, aPlaceOrigin, aDesiredSize); } + +NS_IMETHODIMP +nsMathMLmiFrame::ReflowDirtyChild(nsIPresShell* aPresShell, + nsIFrame* aChild) +{ + // if we get this, it means it was called by the nsTextFrame beneath us, and + // this means something changed in the text content. So re-process our text + + nsCOMPtr presContext; + aPresShell->GetPresContext(getter_AddRefs(presContext)); + ProcessTextData(presContext); + + return mParent->ReflowDirtyChild(aPresShell, this); +} diff --git a/layout/mathml/base/src/nsMathMLmiFrame.h b/layout/mathml/base/src/nsMathMLmiFrame.h index 3ecac6a89236..9892c0dfea38 100644 --- a/layout/mathml/base/src/nsMathMLmiFrame.h +++ b/layout/mathml/base/src/nsMathMLmiFrame.h @@ -34,12 +34,10 @@ class nsMathMLmiFrame : public nsMathMLContainerFrame { public: friend nsresult NS_NewMathMLmiFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame); - /* needs to switch to a normal-font (rather than italics) if - * its text content is not a single character (as per the MathML REC). - * special care is also needed for style-invariant chars - bug 65951 - */ NS_IMETHOD - TransmitAutomaticData(nsIPresContext* aPresContext); + SetInitialChildList(nsIPresContext* aPresContext, + nsIAtom* aListName, + nsIFrame* aChildList); NS_IMETHOD Reflow(nsIPresContext* aPresContext, @@ -53,11 +51,22 @@ public: PRBool aPlaceOrigin, nsHTMLReflowMetrics& aDesiredSize); + NS_IMETHOD + ReflowDirtyChild(nsIPresShell* aPresShell, + nsIFrame* aChild); + protected: nsMathMLmiFrame(); virtual ~nsMathMLmiFrame(); - + virtual PRIntn GetSkipSides() const { return 0; } + + /* needs to switch to a normal-font (rather than italics) if + * its text content is not a single character (as per the MathML REC). + * special care is also needed for style-invariant chars - bug 65951 + */ + void + ProcessTextData(nsIPresContext* aPresContext); }; #endif /* nsMathMLmiFrame_h___ */ diff --git a/layout/mathml/base/src/nsMathMLmmultiscriptsFrame.cpp b/layout/mathml/base/src/nsMathMLmmultiscriptsFrame.cpp index 266b23f52da6..16424d0f2f66 100644 --- a/layout/mathml/base/src/nsMathMLmmultiscriptsFrame.cpp +++ b/layout/mathml/base/src/nsMathMLmmultiscriptsFrame.cpp @@ -68,15 +68,63 @@ nsMathMLmmultiscriptsFrame::~nsMathMLmmultiscriptsFrame() } NS_IMETHODIMP -nsMathMLmmultiscriptsFrame::Init(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIFrame* aParent, - nsIStyleContext* aContext, - nsIFrame* aPrevInFlow) +nsMathMLmmultiscriptsFrame::TransmitAutomaticData(nsIPresContext* aPresContext) { - nsresult rv = nsMathMLContainerFrame::Init - (aPresContext, aContent, aParent, aContext, aPrevInFlow); + // if our base is an embellished operator, let its state bubble to us + GetEmbellishDataFrom(mFrames.FirstChild(), mEmbellishData); + if (NS_MATHML_IS_EMBELLISH_OPERATOR(mEmbellishData.flags)) + mEmbellishData.nextFrame = mFrames.FirstChild(); + // The REC says: + // The element increments scriptlevel by 1, and sets + // displaystyle to "false", within each of its arguments except base + UpdatePresentationDataFromChildAt(aPresContext, 1, -1, 1, + ~NS_MATHML_DISPLAYSTYLE, NS_MATHML_DISPLAYSTYLE); + + // The TeXbook (Ch 17. p.141) says the superscript inherits the compression + // while the subscript is compressed. So here we collect subscripts and set + // the compression flag in them. + PRInt32 count = 0; + PRBool isSubScript = PR_FALSE; + nsAutoVoidArray subScriptFrames; + nsIFrame* childFrame = mFrames.FirstChild(); + while (childFrame) { + nsCOMPtr childContent; + nsCOMPtr childTag; + childFrame->GetContent(getter_AddRefs(childContent)); + childContent->GetTag(*getter_AddRefs(childTag)); + if (childTag.get() == nsMathMLAtoms::mprescripts_) { + // mprescripts frame + } + else if (0 == count) { + // base frame + } + else { + // super/subscript block + if (isSubScript) { + // subscript + subScriptFrames.AppendElement(childFrame); + } + else { + // superscript + } + isSubScript = !isSubScript; + } + count++; + childFrame->GetNextSibling(&childFrame); + } + for (PRInt32 i = subScriptFrames.Count() - 1; i >= 0; i--) { + childFrame = (nsIFrame*)subScriptFrames[i]; + PropagatePresentationDataFor(aPresContext, childFrame, 0, + NS_MATHML_COMPRESSED, NS_MATHML_COMPRESSED); + } + + return NS_OK; +} + +void +nsMathMLmmultiscriptsFrame::ProcessAttributes(nsIPresContext* aPresContext) +{ mSubScriptShift = 0; mSupScriptShift = 0; mScriptSpace = NSFloatPointsToTwips(0.5f); // 0.5pt as in plain TeX @@ -98,27 +146,6 @@ nsMathMLmmultiscriptsFrame::Init(nsIPresContext* aPresContext, mSupScriptShift = CalcLength(aPresContext, mStyleContext, cssValue); } } - - return rv; -} - -NS_IMETHODIMP -nsMathMLmmultiscriptsFrame::TransmitAutomaticData(nsIPresContext* aPresContext) -{ -#if defined(NS_DEBUG) && defined(SHOW_BOUNDING_BOX) - mPresentationData.flags |= NS_MATHML_SHOW_BOUNDING_METRICS; -#endif - - // check whether or not this is an embellished operator - EmbellishOperator(); - // The REC says: - // The element increments scriptlevel by 1, and sets - // displaystyle to "false", within each of its arguments except base, but - // leaves both attributes unchanged within base. - // XXX Need to update the compression flags in the sub/sup pairs as per TeX - UpdatePresentationDataFromChildAt(aPresContext, 1, -1, 1, - ~NS_MATHML_DISPLAYSTYLE, NS_MATHML_DISPLAYSTYLE); - return NS_OK; } NS_IMETHODIMP @@ -127,8 +154,6 @@ nsMathMLmmultiscriptsFrame::Place(nsIPresContext* aPresContext, PRBool aPlaceOrigin, nsHTMLReflowMetrics& aDesiredSize) { - nsresult rv = NS_OK; - //////////////////////////////////// // Get the children's desired sizes @@ -139,16 +164,9 @@ nsMathMLmmultiscriptsFrame::Place(nsIPresContext* aPresContext, // depend only on the current font //////////////////////////////////////// - // get x-height (an ex) -#if 0 - nscoord xHeight = 0; - nsCOMPtr fm; - const nsStyleFont* aFont = - (const nsStyleFont*) mStyleContext->GetStyleData (eStyleStruct_Font); - aPresContext->GetMetricsFor (aFont->mFont, getter_AddRefs(fm)); - fm->GetXHeight (xHeight); -#endif + ProcessAttributes(aPresContext); + // get x-height (an ex) const nsStyleFont *font = NS_STATIC_CAST(const nsStyleFont*, mStyleContext->GetStyleData(eStyleStruct_Font)); aRenderingContext.SetFont(font->mFont); @@ -244,11 +262,9 @@ nsMathMLmmultiscriptsFrame::Place(nsIPresContext* aPresContext, nsBoundingMetrics bmBase, bmSubScript, bmSupScript; nscoord italicCorrection = 0; - // XXX is there an NSPR macro for int_max ??? - mBoundingMetrics.ascent = mBoundingMetrics.descent = -10000000; mBoundingMetrics.width = 0; - - aDesiredSize.ascent = aDesiredSize.descent = -10000000; + mBoundingMetrics.ascent = mBoundingMetrics.descent = -0x7FFFFFFF; + aDesiredSize.ascent = aDesiredSize.descent = -0x7FFFFFFF; aDesiredSize.width = aDesiredSize.height = 0; nsIFrame* childFrame = mFrames.FirstChild(); @@ -259,6 +275,12 @@ nsMathMLmmultiscriptsFrame::Place(nsIPresContext* aPresContext, childContent->GetTag(*getter_AddRefs(childTag)); if (childTag.get() == nsMathMLAtoms::mprescripts_) { + if (mprescriptsFrame) { + // duplicate found + // report an error, encourage people to get their markups in order + NS_WARNING("invalid markup"); + return ReflowError(aPresContext, aRenderingContext, aDesiredSize); + } mprescriptsFrame = childFrame; firstPrescriptsPair = PR_TRUE; } @@ -446,5 +468,5 @@ nsMathMLmmultiscriptsFrame::Place(nsIPresContext* aPresContext, } while (mprescriptsFrame != childFrame); } - return rv; + return NS_OK; } diff --git a/layout/mathml/base/src/nsMathMLmmultiscriptsFrame.h b/layout/mathml/base/src/nsMathMLmmultiscriptsFrame.h index 4b2d87da7f6b..d1b5d37f3207 100644 --- a/layout/mathml/base/src/nsMathMLmmultiscriptsFrame.h +++ b/layout/mathml/base/src/nsMathMLmmultiscriptsFrame.h @@ -35,13 +35,6 @@ class nsMathMLmmultiscriptsFrame : public nsMathMLContainerFrame { public: friend nsresult NS_NewMathMLmmultiscriptsFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame); - NS_IMETHOD - Init(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIFrame* aParent, - nsIStyleContext* aContext, - nsIFrame* aPrevInFlow); - NS_IMETHOD TransmitAutomaticData(nsIPresContext* aPresContext); @@ -62,6 +55,9 @@ private: // = 0.5pt in plain TeX nscoord mSubScriptShift; nscoord mSupScriptShift; + + void + ProcessAttributes(nsIPresContext* aPresContext); }; #endif /* nsMathMLmmultiscriptsFrame_h___ */ diff --git a/layout/mathml/base/src/nsMathMLmoFrame.cpp b/layout/mathml/base/src/nsMathMLmoFrame.cpp index aa776118e4d3..b9113a67f347 100644 --- a/layout/mathml/base/src/nsMathMLmoFrame.cpp +++ b/layout/mathml/base/src/nsMathMLmoFrame.cpp @@ -46,46 +46,6 @@ // -- operator, fence, or separator - implementation // -// TODO: -// * Handle embellished operators -// See the section "Exception for embellished operators" -// in http://www.w3.org/TR/REC-MathML/chap3_2.html -// -// * For a markup content, if "content" is not found in -// the operator dictionary, the REC sets default attributes : -// fence = false -// separator = false -// lspace = .27777em -// rspace = .27777em -// stretchy = false -// symmetric = true -// maxsize = infinity -// minsize = 1 -// largeop = false -// movablelimits = false -// accent = false -// -// We only have to handle *lspace* and *rspace*, perhaps via a CSS padding rule -// in mathml.css, and override the rule if the content is found? -// - -// * The spacing is wrong in certain situations, e.g.// + -// -// The REC tells more about lspace and rspace attributes: -// -// The values for lspace and rspace given here range from 0 to 6/18 em in -// units of 1/18 em. For the invisible operators whose content is -// "⁢" or "⁡", it is suggested that MathML -// renderers choose spacing in a context-sensitive way (which is an exception to -// the static values given in the following table). For , -// the total spacing (lspace + rspace) in expressions such as "sin x" -// (where the right operand doesn't start with a fence) should be greater -// than 0; for , the total spacing should be greater -// than 0 when both operands (or the nearest tokens on either side, if on -// the baseline) are identifiers displayed in a non-slanted font (i.e., under -// the suggested rules, when both operands are multi-character identifiers). - - // additional style context to be used by our MathMLChar. #define NS_MATHML_CHAR_STYLE_CONTEXT_INDEX 0 @@ -127,8 +87,7 @@ nsMathMLmoFrame::Paint(nsIPresContext* aPresContext, #if defined(NS_DEBUG) && defined(SHOW_BOUNDING_BOX) // for visual debug if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer && - NS_MATHML_PAINT_BOUNDING_METRICS(mPresentationData.flags)) - { + NS_MATHML_PAINT_BOUNDING_METRICS(mPresentationData.flags)) { aRenderingContext.SetColor(NS_RGB(0,255,255)); nscoord x = mReference.x + mBoundingMetrics.leftBearing; nscoord y = mReference.y - mBoundingMetrics.ascent; @@ -145,25 +104,17 @@ nsMathMLmoFrame::Paint(nsIPresContext* aPresContext, return rv; } -NS_IMETHODIMP -nsMathMLmoFrame::Init(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIFrame* aParent, - nsIStyleContext* aContext, - nsIFrame* aPrevInFlow) +// get the text that we enclose and setup our nsMathMLChar +void +nsMathMLmoFrame::ProcessTextData(nsIPresContext* aPresContext) { - // Let the base class do its Init() - nsresult rv = nsMathMLContainerFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow); - - // Init our local attributes mFlags = 0; - mMinSize = float(NS_UNCONSTRAINEDSIZE); - mMaxSize = float(NS_UNCONSTRAINEDSIZE); + if (!mFrames.FirstChild()) + return; - // get the text that we enclose - nsAutoString data; // kids can be comment-nodes, attribute-nodes, text-nodes... // we use the DOM to ensure that we only look at text-nodes... + nsAutoString data; PRInt32 numKids; mContent->ChildCount(numKids); for (PRInt32 kid=0; kid, , or , they will treat us properly: - // 1) do we have accent="true" - // 2) do we have movablelimits="true" - - // they need the extra information to decide how to treat their scripts/limits - // (note: , , or need not necessarily be our - // direct parent -- case of embellished operators) - - mEmbellishData.flags &= ~NS_MATHML_EMBELLISH_ACCENT; // default is false - mEmbellishData.flags &= ~NS_MATHML_EMBELLISH_MOVABLELIMITS; // default is false - - nsAutoString value; - PRBool accentAttribute = PR_FALSE; - PRBool movablelimitsAttribute = PR_FALSE; - - // see if the accent attribute is there - if (NS_CONTENT_ATTR_HAS_VALUE == GetAttribute(mContent, mPresentationData.mstyle, - nsMathMLAtoms::accent_, value)) - { - accentAttribute = PR_TRUE; - if (value.Equals(NS_LITERAL_STRING("true"))) - { - mEmbellishData.flags |= NS_MATHML_EMBELLISH_ACCENT; - } - } - - // see if the movablelimits attribute is there - if (NS_CONTENT_ATTR_HAS_VALUE == GetAttribute(mContent, mPresentationData.mstyle, - nsMathMLAtoms::movablelimits_, value)) - { - movablelimitsAttribute = PR_TRUE; - if (value.Equals(NS_LITERAL_STRING("true"))) - { - mEmbellishData.flags |= NS_MATHML_EMBELLISH_MOVABLELIMITS; - } - } - - if (!accentAttribute || !movablelimitsAttribute) { - // If we reach here, it means one or both attributes are missing. - // Unfortunately, we have to lookup the dictionary to see who - // we are, i.e., two lookups, counting also the one in Stretch()! - // The lookup in Stretch() assumes that the surrounding frame tree - // is already fully constructed, which is not true at this stage. - - // all accent="true" in the dictionary have form="postfix" - // XXX should we check if the form attribute is there? - nsAutoString data; - mMathMLChar.GetData(data); - nsOperatorFlags form = NS_MATHML_OPERATOR_FORM_POSTFIX; - nsOperatorFlags flags = 0; - float leftSpace, rightSpace; - PRBool found = nsMathMLOperators::LookupOperator(data, form, - &flags, &leftSpace, &rightSpace); - - if (found && !accentAttribute && NS_MATHML_OPERATOR_IS_ACCENT(flags)) - { - mEmbellishData.flags |= NS_MATHML_EMBELLISH_ACCENT; - } - - // all movablemits="true" in the dictionary have form="prefix", - // but this doesn't matter here, as the lookup has returned whatever - // is in the dictionary - if (found && !movablelimitsAttribute && NS_MATHML_OPERATOR_IS_MOVABLELIMITS(flags)) - { - mEmbellishData.flags |= NS_MATHML_EMBELLISH_MOVABLELIMITS; - } - } - } - return NS_OK; + // cache the operator + mMathMLChar.SetData(aPresContext, data); + ResolveMathMLCharStyle(aPresContext, mContent, mStyleContext, &mMathMLChar, isMutable); } +// get our 'form' and lookup in the Operator Dictionary to fetch +// our default data that may come from there, the look our attributes. +// The function has to be called during reflow because certain value +// before, we will re-use unchanged things that we computed earlier void -nsMathMLmoFrame::InitData(nsIPresContext* aPresContext) +nsMathMLmoFrame::ProcessOperatorData(nsIPresContext* aPresContext) { - nsresult rv = NS_OK; + // if we have been here before, we will just use our cached form + nsOperatorFlags form = NS_MATHML_OPERATOR_GET_FORM(mFlags); + nsAutoString value; - // Remember the mutable bit from Init(). + // special bits are always kept in mFlags. + // remember the mutable bit from ProcessTextData(). // Some chars are listed under different forms in the dictionary, // and there could be a form under which the char is mutable. // If the char is the core of an embellished container, we will keep - // it mutable irrespective of the form of the embellished container - mFlags &= NS_MATHML_OPERATOR_MUTABLE; + // it mutable irrespective of the form of the embellished container. + // Also remember the other special bits that we want to carry forward. + mFlags &= NS_MATHML_OPERATOR_MUTABLE | + NS_MATHML_OPERATOR_ACCENT | + NS_MATHML_OPERATOR_MOVABLELIMITS | + NS_MATHML_OPERATOR_CENTERED; - // 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; - nsIFrame* parentAncestor = this; - do { - embellishAncestor = parentAncestor; - embellishAncestor->GetParent(&parentAncestor); - parentAncestor->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame); - if (mathMLFrame) { - mathMLFrame->GetEmbellishData(embellishData); + if (!mEmbellishData.coreFrame) { + // i.e., we haven't been here before, the default form is infix + form = NS_MATHML_OPERATOR_FORM_INFIX; + + // reset everything so that we don't keep outdated values around + // in case of dynamic changes + mEmbellishData.flags = 0; + mEmbellishData.nextFrame = nsnull; + mEmbellishData.coreFrame = nsnull; + mEmbellishData.direction = NS_STRETCH_DIRECTION_UNSUPPORTED; + mEmbellishData.leftSpace = 0; + mEmbellishData.rightSpace = 0; + + if (!mFrames.FirstChild()) + return; + + mEmbellishData.flags |= NS_MATHML_EMBELLISH_OPERATOR; + mEmbellishData.nextFrame = nsnull; + mEmbellishData.coreFrame = this; + mEmbellishData.direction = mMathMLChar.GetStretchDirection(); + + // there are two particular things that we also need to record so that if our + // parent is , , or , they will treat us properly: + // 1) do we have accent="true" + // 2) do we have movablelimits="true" + + // they need the extra information to decide how to treat their scripts/limits + // (note: , , or need not necessarily be our + // direct parent -- case of embellished operators) + + // default values from the Operator Dictionary were obtained in ProcessTextData() + // and these special bits are always kept in mFlags + if (NS_MATHML_OPERATOR_IS_ACCENT(mFlags)) + mEmbellishData.flags |= NS_MATHML_EMBELLISH_ACCENT; + if (NS_MATHML_OPERATOR_IS_MOVABLELIMITS(mFlags)) + mEmbellishData.flags |= NS_MATHML_EMBELLISH_MOVABLELIMITS; + + // see if the accent attribute is there + if (NS_CONTENT_ATTR_HAS_VALUE == GetAttribute(mContent, mPresentationData.mstyle, + nsMathMLAtoms::accent_, value)) { + if (value.Equals(NS_LITERAL_STRING("true"))) + mEmbellishData.flags |= NS_MATHML_EMBELLISH_ACCENT; + else if (value.Equals(NS_LITERAL_STRING("false"))) + mEmbellishData.flags &= ~NS_MATHML_EMBELLISH_ACCENT; + } + // see if the movablelimits attribute is there + if (NS_CONTENT_ATTR_HAS_VALUE == GetAttribute(mContent, mPresentationData.mstyle, + nsMathMLAtoms::movablelimits_, value)) { + if (value.Equals(NS_LITERAL_STRING("true"))) + mEmbellishData.flags |= NS_MATHML_EMBELLISH_MOVABLELIMITS; + else if (value.Equals(NS_LITERAL_STRING("false"))) + mEmbellishData.flags &= ~NS_MATHML_EMBELLISH_MOVABLELIMITS; + } + + // get our outermost embellished container and its parent. + // (we ensure that we are the core, not just a sibling of the core) + nsIFrame* embellishAncestor = this; + nsEmbellishData embellishData; + nsIFrame* parentAncestor = this; + do { + embellishAncestor = parentAncestor; + embellishAncestor->GetParent(&parentAncestor); + GetEmbellishDataFrom(parentAncestor, embellishData); + } while (embellishData.coreFrame == this); + + // flag if we have an embellished ancestor + if (embellishAncestor != this) + mFlags |= NS_MATHML_OPERATOR_EMBELLISH_ANCESTOR; + else + mFlags &= ~NS_MATHML_OPERATOR_EMBELLISH_ANCESTOR; + + // find the position of our outermost embellished container w.r.t + // its siblings (frames are singly-linked together). + nsIFrame* firstChild; + parentAncestor->FirstChild(aPresContext, nsnull, &firstChild); + nsFrameList frameList(firstChild); + + nsIFrame* nextSibling; + embellishAncestor->GetNextSibling(&nextSibling); + nsIFrame* prevSibling = frameList.GetPrevSiblingFor(embellishAncestor); + + // flag to distinguish from a real infix + if (!prevSibling && !nextSibling) + mFlags |= NS_MATHML_OPERATOR_EMBELLISH_ISOLATED; + else + mFlags &= ~NS_MATHML_OPERATOR_EMBELLISH_ISOLATED; + + // find our form + if (NS_CONTENT_ATTR_HAS_VALUE == GetAttribute(mContent, mPresentationData.mstyle, + nsMathMLAtoms::form_, value)) { + if (value.Equals(NS_LITERAL_STRING("prefix"))) + form = NS_MATHML_OPERATOR_FORM_PREFIX; + else if (value.Equals(NS_LITERAL_STRING("postfix"))) + form = NS_MATHML_OPERATOR_FORM_POSTFIX; } else { - embellishData.coreFrame = nsnull; + // set our form flag depending on the position + if (!prevSibling && nextSibling) + form = NS_MATHML_OPERATOR_FORM_PREFIX; + else if (prevSibling && !nextSibling) + form = NS_MATHML_OPERATOR_FORM_POSTFIX; } - } while (embellishData.coreFrame == this); - // flag if we have an embellished ancestor - if (embellishAncestor != this) { - 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"))) - form = NS_MATHML_OPERATOR_FORM_PREFIX; - else if (value.Equals(NS_LITERAL_STRING("postfix"))) - form = NS_MATHML_OPERATOR_FORM_POSTFIX; - } - else { - // Find the position of our outermost embellished container w.r.t - // its siblings (frames are singly-linked together). - nsIFrame* prev = nsnull; - nsIFrame* next = nsnull; - nsIFrame* frame; + // lookup the operator dictionary + // the form can be null to mean that the stretching of our mMathMLChar + // failed earlier, in which case we won't bother re-stretching again + if (form) { + float lspace = 0.0f; + float rspace = 0.0f; + nsAutoString data; + mMathMLChar.GetData(data); + mMathMLChar.SetData(aPresContext, data); // XXX hack to reset, bug 45010 + PRBool found = nsMathMLOperators::LookupOperator(data, form, &mFlags, &lspace, &rspace); + if (found) { + // cache the default values of lspace & rspace that we get from the dictionary. + // since these values are relative to the 'em' unit, convert to twips now + nscoord em; + const nsStyleFont* font; + GetStyleData(eStyleStruct_Font, (const nsStyleStruct *&)font); + nsCOMPtr fm; + aPresContext->GetMetricsFor(font->mFont, getter_AddRefs(fm)); + GetEmHeight(fm, em); - embellishAncestor->GetNextSibling(&next); - parentAncestor->FirstChild(aPresContext, nsnull, &frame); - while (frame) { - if (frame == embellishAncestor) break; - prev = frame; - frame->GetNextSibling(&frame); + mEmbellishData.leftSpace = NSToCoordRound(lspace * em); + mEmbellishData.rightSpace = NSToCoordRound(rspace * em); + + // tuning if we don't want too much extra space when we are a script. + // (with its fonts, TeX sets lspace=0 & rspace=0 as soon as scriptlevel>0. + // Our fonts can be anything, so...) + if (mPresentationData.scriptLevel > 0) { + if (NS_MATHML_OPERATOR_EMBELLISH_IS_ISOLATED(mFlags)) { + // could be an isolated accent or script, e.g., x^{+}, just zero out + mEmbellishData.leftSpace = 0; + mEmbellishData.rightSpace = 0; + } + else if (!NS_MATHML_OPERATOR_HAS_EMBELLISH_ANCESTOR(mFlags)) { + mEmbellishData.leftSpace /= 2; + mEmbellishData.rightSpace /= 2; + } + } } - - // set our form flag depending on the position - if (!prev && next) - form = NS_MATHML_OPERATOR_FORM_PREFIX; - else if (prev && !next) - form = NS_MATHML_OPERATOR_FORM_POSTFIX; - } - - // Lookup the operator dictionary - nsAutoString data; - mMathMLChar.GetData(data); - mMathMLChar.SetData(aPresContext, data); // XXX hack to reset, bug 45010 - float lspace, rspace; - PRBool found = nsMathMLOperators::LookupOperator(data, form, &mFlags, &lspace, &rspace); - - // If we don't want too much extra space when we are a script - if ((0 < mPresentationData.scriptLevel) && - !NS_MATHML_OPERATOR_HAS_EMBELLISH_ANCESTOR(mFlags)) { - lspace /= 2.0f; - rspace /= 2.0f; - } - - // Since these values are relative to the 'em' unit, convert to twips now - nscoord leftSpace, rightSpace, em; - const nsStyleFont* font; - GetStyleData(eStyleStruct_Font, (const nsStyleStruct *&)font); - nsCOMPtr fm; - aPresContext->GetMetricsFor(font->mFont, getter_AddRefs(fm)); - GetEmHeight(fm, em); - leftSpace = NSToCoordRound(lspace * em); - rightSpace = NSToCoordRound(rspace * em); - - // Now see if there are user-defined attributes that override the dictionary. - // XXX If an attribute can be forced to be true when it is false in the - // dictionary, then the following code has to change... - - // For each attribute overriden by the user, turn off its bit flag. - // symmetric|movablelimits|separator|largeop|accent|fence|stretchy|form - nsAutoString kfalse, ktrue; - kfalse.Assign(NS_LITERAL_STRING("false")); - ktrue.Assign(NS_LITERAL_STRING("true")); - if (NS_MATHML_OPERATOR_IS_STRETCHY(mFlags)) { - if (NS_CONTENT_ATTR_HAS_VALUE == GetAttribute(mContent, mPresentationData.mstyle, - nsMathMLAtoms::stretchy_, value) && value == kfalse) - mFlags &= ~NS_MATHML_OPERATOR_STRETCHY; - } - if (NS_MATHML_OPERATOR_IS_FENCE(mFlags)) { - if (NS_CONTENT_ATTR_HAS_VALUE == GetAttribute(mContent, mPresentationData.mstyle, - nsMathMLAtoms::fence_, value) && value == kfalse) - mFlags &= ~NS_MATHML_OPERATOR_FENCE; - } - if (NS_MATHML_OPERATOR_IS_ACCENT(mFlags)) { - if (NS_CONTENT_ATTR_HAS_VALUE == GetAttribute(mContent, mPresentationData.mstyle, - nsMathMLAtoms::accent_, value) && value == kfalse) - mFlags &= ~NS_MATHML_OPERATOR_ACCENT; - } - if (NS_MATHML_OPERATOR_IS_LARGEOP(mFlags)) { - if (NS_CONTENT_ATTR_HAS_VALUE == GetAttribute(mContent, mPresentationData.mstyle, - nsMathMLAtoms::largeop_, value) && value == kfalse) - mFlags &= ~NS_MATHML_OPERATOR_LARGEOP; - } - if (NS_MATHML_OPERATOR_IS_SEPARATOR(mFlags)) { - if (NS_CONTENT_ATTR_HAS_VALUE == GetAttribute(mContent, mPresentationData.mstyle, - nsMathMLAtoms::separator_, value) && value == kfalse) - mFlags &= ~NS_MATHML_OPERATOR_SEPARATOR; - } - if (NS_MATHML_OPERATOR_IS_MOVABLELIMITS(mFlags)) { - if (NS_CONTENT_ATTR_HAS_VALUE == GetAttribute(mContent, mPresentationData.mstyle, - nsMathMLAtoms::movablelimits_, value) && value == kfalse) - mFlags &= ~NS_MATHML_OPERATOR_MOVABLELIMITS; - } - if (NS_CONTENT_ATTR_HAS_VALUE == GetAttribute(mContent, mPresentationData.mstyle, - nsMathMLAtoms::symmetric_, value)) { - if (value == kfalse) mFlags &= ~NS_MATHML_OPERATOR_SYMMETRIC; - else if (value == ktrue) mFlags |= NS_MATHML_OPERATOR_SYMMETRIC; } // If we are an accent without explicit lspace="." or rspace=".", - // ignore our default left/right space + // we will ignore our default left/right space // lspace = number h-unit | namedspace + nscoord leftSpace = mEmbellishData.leftSpace; if (NS_CONTENT_ATTR_HAS_VALUE == GetAttribute(mContent, mPresentationData.mstyle, nsMathMLAtoms::lspace_, value)) { nsCSSValue cssValue; @@ -431,6 +357,7 @@ nsMathMLmoFrame::InitData(nsIPresContext* aPresContext) } // rspace = number h-unit | namedspace + nscoord rightSpace = mEmbellishData.rightSpace; if (NS_CONTENT_ATTR_HAS_VALUE == GetAttribute(mContent, mPresentationData.mstyle, nsMathMLAtoms::rspace_, value)) { nsCSSValue cssValue; @@ -447,11 +374,53 @@ nsMathMLmoFrame::InitData(nsIPresContext* aPresContext) rightSpace = 0; } - // cache these values + // the values that we get from our attributes override the dictionary mEmbellishData.leftSpace = leftSpace; mEmbellishData.rightSpace = rightSpace; + // Nows see if there are user-defined attributes that override the dictionary. + // XXX If an attribute can be forced to be true when it is false in the + // dictionary, then the following code has to change... + + // For each attribute overriden by the user, turn off its bit flag. + // symmetric|movablelimits|separator|largeop|accent|fence|stretchy|form + // special: accent and movablelimits are handled in ProcessEmbellishData() + // don't process them here + + nsAutoString kfalse, ktrue; + kfalse.Assign(NS_LITERAL_STRING("false")); + ktrue.Assign(NS_LITERAL_STRING("true")); + + if (NS_MATHML_OPERATOR_IS_STRETCHY(mFlags)) { + if (NS_CONTENT_ATTR_HAS_VALUE == GetAttribute(mContent, mPresentationData.mstyle, + nsMathMLAtoms::stretchy_, value) && value == kfalse) + mFlags &= ~NS_MATHML_OPERATOR_STRETCHY; + } + if (NS_MATHML_OPERATOR_IS_FENCE(mFlags)) { + if (NS_CONTENT_ATTR_HAS_VALUE == GetAttribute(mContent, mPresentationData.mstyle, + nsMathMLAtoms::fence_, value) && value == kfalse) + mFlags &= ~NS_MATHML_OPERATOR_FENCE; + } + if (NS_MATHML_OPERATOR_IS_LARGEOP(mFlags)) { + if (NS_CONTENT_ATTR_HAS_VALUE == GetAttribute(mContent, mPresentationData.mstyle, + nsMathMLAtoms::largeop_, value) && value == kfalse) + mFlags &= ~NS_MATHML_OPERATOR_LARGEOP; + } + if (NS_MATHML_OPERATOR_IS_SEPARATOR(mFlags)) { + if (NS_CONTENT_ATTR_HAS_VALUE == GetAttribute(mContent, mPresentationData.mstyle, + nsMathMLAtoms::separator_, value) && value == kfalse) + mFlags &= ~NS_MATHML_OPERATOR_SEPARATOR; + } + if (NS_CONTENT_ATTR_HAS_VALUE == GetAttribute(mContent, mPresentationData.mstyle, + nsMathMLAtoms::symmetric_, value)) { + if (value == kfalse) + mFlags &= ~NS_MATHML_OPERATOR_SYMMETRIC; + else if (value == ktrue) + mFlags |= NS_MATHML_OPERATOR_SYMMETRIC; + } + // minsize = number [ v-unit | h-unit ] | namedspace + mMinSize = float(NS_UNCONSTRAINEDSIZE); if (NS_CONTENT_ATTR_HAS_VALUE == GetAttribute(mContent, mPresentationData.mstyle, nsMathMLAtoms::minsize_, value)) { nsCSSValue cssValue; @@ -484,6 +453,7 @@ nsMathMLmoFrame::InitData(nsIPresContext* aPresContext) } // maxsize = number [ v-unit | h-unit ] | namedspace | infinity + mMaxSize = float(NS_UNCONSTRAINEDSIZE); if (NS_CONTENT_ATTR_HAS_VALUE == GetAttribute(mContent, mPresentationData.mstyle, nsMathMLAtoms::maxsize_, value)) { nsCSSValue cssValue; @@ -514,25 +484,6 @@ nsMathMLmoFrame::InitData(nsIPresContext* aPresContext) } } } - - // If the stretchy or largeop attributes have been disabled, - // the operator is not mutable - if (!found || - (!NS_MATHML_OPERATOR_IS_STRETCHY(mFlags) && - !NS_MATHML_OPERATOR_IS_LARGEOP(mFlags))) - { - mFlags &= ~NS_MATHML_OPERATOR_MUTABLE; - } - - // See if this is an operator that should be centered to cater for - // fonts that are not math-aware - if (1 == data.Length()) { - PRUnichar ch = data[0]; - if ((ch == '+') || (ch == '=') || (ch == '*') || - (ch == 0x00D7)) { // × - mFlags |= NS_MATHML_OPERATOR_CENTERED; - } - } } // NOTE: aDesiredStretchSize is an IN/OUT parameter @@ -545,13 +496,11 @@ nsMathMLmoFrame::Stretch(nsIPresContext* aPresContext, nsBoundingMetrics& aContainerSize, nsHTMLReflowMetrics& aDesiredStretchSize) { - if (NS_MATHML_STRETCH_WAS_DONE(mEmbellishData.flags)) { + if (NS_MATHML_STRETCH_WAS_DONE(mPresentationData.flags)) { NS_WARNING("it is wrong to fire stretch more than once on a frame"); return NS_OK; } - mEmbellishData.flags |= NS_MATHML_STRETCH_DONE; - - InitData(aPresContext); + mPresentationData.flags |= NS_MATHML_STRETCH_DONE; // get the axis height; const nsStyleFont *font = NS_STATIC_CAST(const nsStyleFont*, @@ -574,8 +523,15 @@ nsMathMLmoFrame::Stretch(nsIPresContext* aPresContext, PRBool isVertical = PR_FALSE; PRUint32 stretchHint = NS_STRETCH_NORMAL; - // see if it is okay to stretch - if (NS_MATHML_OPERATOR_IS_MUTABLE(mFlags)) { + // see if it is okay to stretch, starting from what the Operator Dictionary said + PRBool isMutable = NS_MATHML_OPERATOR_IS_MUTABLE(mFlags); + // if the stretchy and largeop attributes have been disabled, + // the operator is not mutable + if (!NS_MATHML_OPERATOR_IS_STRETCHY(mFlags) && + !NS_MATHML_OPERATOR_IS_LARGEOP(mFlags)) + isMutable = PR_FALSE; + + if (isMutable) { container = aContainerSize; @@ -786,12 +742,40 @@ nsMathMLmoFrame::Stretch(nsIPresContext* aPresContext, return NS_OK; } +NS_IMETHODIMP +nsMathMLmoFrame::SetInitialChildList(nsIPresContext* aPresContext, + nsIAtom* aListName, + nsIFrame* aChildList) +{ + // First, let the base class do its work + nsresult rv = nsMathMLContainerFrame::SetInitialChildList(aPresContext, aListName, aChildList); + if (NS_FAILED(rv)) return rv; + + // No need to tract the style context given to our MathML char. + // The Style System will use Get/SetAdditionalStyleContext() to keep it + // up-to-date if dynamic changes arise. + ProcessTextData(aPresContext); + return rv; +} + +NS_IMETHODIMP +nsMathMLmoFrame::TransmitAutomaticData(nsIPresContext* aPresContext) +{ + // this will cause us to re-sync our flags from scratch + mEmbellishData.coreFrame = nsnull; + ProcessOperatorData(aPresContext); + return NS_OK; +} + NS_IMETHODIMP nsMathMLmoFrame::Reflow(nsIPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { + // certain values use units that depend on our style context, so + // it is safer to just process the whole lot here + ProcessOperatorData(aPresContext); return ReflowTokenFor(this, aPresContext, aDesiredSize, aReflowState, aStatus); } @@ -806,6 +790,31 @@ nsMathMLmoFrame::Place(nsIPresContext* aPresContext, aPlaceOrigin, aDesiredSize); } +NS_IMETHODIMP +nsMathMLmoFrame::ReflowDirtyChild(nsIPresShell* aPresShell, + nsIFrame* aChild) +{ + // if we get this, it means it was called by the nsTextFrame beneath us, and + // this means something changed in the text content. So blow away everything + // an re-build the automatic data from the parent of our outermost embellished + // container (we ensure that we are the core, not just a sibling of the core) + + nsCOMPtr presContext; + aPresShell->GetPresContext(getter_AddRefs(presContext)); + + ProcessTextData(presContext); + + nsIFrame* target = this; + nsEmbellishData embellishData; + do { + target->GetParent(&target); + GetEmbellishDataFrom(target, embellishData); + } while (embellishData.coreFrame == this); + + // we have automatic data to update in the children of the target frame + return ReLayoutChildren(presContext, target); +} + // ---------------------- // the Style System will use these to pass the proper style context to our MathMLChar NS_IMETHODIMP diff --git a/layout/mathml/base/src/nsMathMLmoFrame.h b/layout/mathml/base/src/nsMathMLmoFrame.h index 1f08620cc030..8cf091b667b6 100644 --- a/layout/mathml/base/src/nsMathMLmoFrame.h +++ b/layout/mathml/base/src/nsMathMLmoFrame.h @@ -43,11 +43,9 @@ public: nsIStyleContext** aStyleContext) const; NS_IMETHOD - Init(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIFrame* aParent, - nsIStyleContext* aContext, - nsIFrame* aPrevInFlow); + SetInitialChildList(nsIPresContext* aPresContext, + nsIAtom* aListName, + nsIFrame* aChildList); NS_IMETHOD Paint(nsIPresContext* aPresContext, @@ -56,6 +54,9 @@ public: nsFramePaintLayer aWhichLayer, PRUint32 aFlags = 0); + NS_IMETHOD + TransmitAutomaticData(nsIPresContext* aPresContext); + NS_IMETHOD Reflow(nsIPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, @@ -69,7 +70,8 @@ public: nsHTMLReflowMetrics& aDesiredSize); NS_IMETHOD - TransmitAutomaticData(nsIPresContext* aPresContext); + ReflowDirtyChild(nsIPresShell* aPresShell, + nsIFrame* aChild); // This method is called by the parent frame to ask // to stretch itself. @@ -80,10 +82,6 @@ public: nsBoundingMetrics& aContainerSize, nsHTMLReflowMetrics& aDesiredStretchSize); - // helper method to lookup the operator dictionary and initialize our member data - void - InitData(nsIPresContext* aPresContext); - protected: nsMathMLmoFrame(); virtual ~nsMathMLmoFrame(); @@ -91,10 +89,19 @@ protected: virtual PRIntn GetSkipSides() const { return 0; } nsMathMLChar mMathMLChar; // Here is the MathMLChar that will deal with the operator. - nsOperatorFlags mFlags; float mMinSize; float mMaxSize; + + // helper to get the text that we enclose and setup our nsMathMLChar + void + ProcessTextData(nsIPresContext* aPresContext); + + // helper to get our 'form' and lookup in the Operator Dictionary to fetch + // our default data that may come from there, and to complete the setup + // using attributes that we may have + void + ProcessOperatorData(nsIPresContext* aPresContext); }; #endif /* nsMathMLmoFrame_h___ */ diff --git a/layout/mathml/base/src/nsMathMLmoverFrame.cpp b/layout/mathml/base/src/nsMathMLmoverFrame.cpp index 41c20e0b3a6b..bee58849ddce 100644 --- a/layout/mathml/base/src/nsMathMLmoverFrame.cpp +++ b/layout/mathml/base/src/nsMathMLmoverFrame.cpp @@ -69,6 +69,25 @@ nsMathMLmoverFrame::~nsMathMLmoverFrame() { } +NS_IMETHODIMP +nsMathMLmoverFrame::AttributeChanged(nsIPresContext* aPresContext, + nsIContent* aContent, + PRInt32 aNameSpaceID, + nsIAtom* aAttribute, + PRInt32 aModType, + PRInt32 aHint) +{ + if (nsMathMLAtoms::accent_ == aAttribute) { + // When we have automatic data to update within ourselves, we ask our + // parent to re-layout its children + return ReLayoutChildren(aPresContext, mParent); + } + + return nsMathMLContainerFrame:: + AttributeChanged(aPresContext, aContent, aNameSpaceID, + aAttribute, aModType, aHint); +} + NS_IMETHODIMP nsMathMLmoverFrame::UpdatePresentationData(nsIPresContext* aPresContext, PRInt32 aScriptLevelIncrement, @@ -78,12 +97,12 @@ nsMathMLmoverFrame::UpdatePresentationData(nsIPresContext* aPresContext, 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) && + if ( NS_MATHML_EMBELLISH_IS_MOVABLELIMITS(mEmbellishData.flags) && !NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags)) { - mEmbellishData.flags &= ~NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY; + mPresentationData.flags &= ~NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY; } else { - mEmbellishData.flags |= NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY; + mPresentationData.flags |= NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY; } return NS_OK; } @@ -124,24 +143,28 @@ nsMathMLmoverFrame::UpdatePresentationDataFromChildAt(nsIPresContext* aPresConte } return NS_OK; - // XXX For #2, if the inner changes, is has to trigger - // XXX a re-computation of all flags that depend on its state - // XXX in the entire embellished hierarchy + // For #2, the base class will trigger a re-build of all automatic data + // in the embellished hierarchy when an accent attribute is changed +} + +NS_IMETHODIMP +nsMathMLmoverFrame::InheritAutomaticData(nsIPresContext* aPresContext, + nsIFrame* aParent) +{ + // let the base class get the default from our parent + nsMathMLContainerFrame::InheritAutomaticData(aPresContext, aParent); + + mPresentationData.flags |= NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY; + + return NS_OK; } NS_IMETHODIMP nsMathMLmoverFrame::TransmitAutomaticData(nsIPresContext* aPresContext) { -#if defined(NS_DEBUG) && defined(SHOW_BOUNDING_BOX) - mPresentationData.flags |= NS_MATHML_SHOW_BOUNDING_METRICS; -#endif - - mEmbellishData.flags |= NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY; - - // check whether or not this is an embellished operator - EmbellishOperator(); - - // set our accent flag + // At this stage, all our children are in sync and we can fully + // resolve our own mEmbellishData struct + //--------------------------------------------------------------------- /* The REC says: The default value of accent is false, unless overscript @@ -159,104 +182,65 @@ XXX The winner is the outermost in conflicting settings like these: */ - PRInt32 count = 0; - nsIFrame* baseFrame = nsnull; nsIFrame* overscriptFrame = nsnull; - nsIFrame* childFrame = mFrames.FirstChild(); - while (childFrame) { - if (0 == count) baseFrame = childFrame; - if (1 == count) { overscriptFrame = childFrame; break; } - count++; - childFrame->GetNextSibling(&childFrame); - } + nsIFrame* baseFrame = mFrames.FirstChild(); + if (baseFrame) + baseFrame->GetNextSibling(&overscriptFrame); + if (!baseFrame || !overscriptFrame) + return NS_OK; // a visual error indicator will be reported later during layout + + // if our base is an embellished operator, let its state bubble to us (in particular, + // this is where we get the flag for NS_MATHML_EMBELLISH_MOVABLELIMITS). Our flags + // are reset to the default values of false if the base frame isn't embellished. + GetEmbellishDataFrom(baseFrame, mEmbellishData); + if (NS_MATHML_IS_EMBELLISH_OPERATOR(mEmbellishData.flags)) + mEmbellishData.nextFrame = baseFrame; - nsIMathMLFrame* overscriptMathMLFrame = nsnull; - nsIMathMLFrame* mathMLFrame = nsnull; - nsEmbellishData embellishData; nsAutoString value; - mPresentationData.flags &= ~NS_MATHML_MOVABLELIMITS; // default is false - mPresentationData.flags &= ~NS_MATHML_ACCENTOVER; // default of accent is false + // The default value of accent is false, unless the overscript is embellished + // and its core is an accent + nsEmbellishData embellishData; + GetEmbellishDataFrom(overscriptFrame, embellishData); + if (NS_MATHML_EMBELLISH_IS_ACCENT(embellishData.flags)) + mEmbellishData.flags |= NS_MATHML_EMBELLISH_ACCENTOVER; + else + mEmbellishData.flags &= ~NS_MATHML_EMBELLISH_ACCENTOVER; - // see if the baseFrame has movablelimits="true" or if it is an - // embellished operator whose movablelimits attribute is set to true - if (baseFrame && NS_MATHML_IS_EMBELLISH_OPERATOR(mEmbellishData.flags)) { - nsCOMPtr baseContent; - baseFrame->GetContent(getter_AddRefs(baseContent)); - if (NS_CONTENT_ATTR_HAS_VALUE == baseContent->GetAttr(kNameSpaceID_None, - nsMathMLAtoms::movablelimits_, value)) { - if (value.Equals(NS_LITERAL_STRING("true"))) { - mPresentationData.flags |= NS_MATHML_MOVABLELIMITS; - } - } - else { // no attribute, get the value from the core - mEmbellishData.coreFrame->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame); - if (mathMLFrame) { - mathMLFrame->GetEmbellishData(embellishData); - if (NS_MATHML_EMBELLISH_IS_MOVABLELIMITS(embellishData.flags)) { - mPresentationData.flags |= NS_MATHML_MOVABLELIMITS; - } - } - } + // if we have an accent attribute, it overrides what the overscript said + if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttr(kNameSpaceID_None, + nsMathMLAtoms::accent_, value)) { + if (value.Equals(NS_LITERAL_STRING("true"))) + mEmbellishData.flags |= NS_MATHML_EMBELLISH_ACCENTOVER; + else if (value.Equals(NS_LITERAL_STRING("false"))) + mEmbellishData.flags &= ~NS_MATHML_EMBELLISH_ACCENTOVER; } - // see if the overscriptFrame is or an embellished operator - if (overscriptFrame) { - overscriptFrame->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&overscriptMathMLFrame); - if (overscriptMathMLFrame) { - overscriptMathMLFrame->GetEmbellishData(embellishData); - // core of the overscriptFrame - if (NS_MATHML_IS_EMBELLISH_OPERATOR(embellishData.flags) && embellishData.coreFrame) { - embellishData.coreFrame->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame); - if (mathMLFrame) { - mathMLFrame->GetEmbellishData(embellishData); - // if we have the accent attribute, tell the core to behave as - // requested (otherwise leave the core with its default behavior) - if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttr(kNameSpaceID_None, - nsMathMLAtoms::accent_, value)) - { - if (value.Equals(NS_LITERAL_STRING("true"))) embellishData.flags |= NS_MATHML_EMBELLISH_ACCENT; - else if (value.Equals(NS_LITERAL_STRING("false"))) embellishData.flags &= ~NS_MATHML_EMBELLISH_ACCENT; - mathMLFrame->SetEmbellishData(embellishData); - } + // disable the stretch-all flag if we are going to act like a superscript + if ( NS_MATHML_EMBELLISH_IS_MOVABLELIMITS(mEmbellishData.flags) && + !NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags)) + mPresentationData.flags &= ~NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY; - // sync the presentation data: record whether we have an accent - if (NS_MATHML_EMBELLISH_IS_ACCENT(embellishData.flags)) - mPresentationData.flags |= NS_MATHML_ACCENTOVER; - } -//XXX should sync the presentation data be at this spot, after the if? - } - } - } + // Now transmit any change that we want to our children so that they + // can update their mPresentationData structs + //--------------------------------------------------------------------- /* The REC says: Within overscript, always sets displaystyle to "false", but increments scriptlevel by 1 only when accent is "false". - */ - /* + The TeXBook treats 'over' like a superscript, so p.141 or Rule 13a say it shouldn't be compressed. However, The TeXBook says that math accents and \overline change uncramped styles to their cramped counterparts. */ - if (overscriptMathMLFrame) { - PRInt32 increment = NS_MATHML_IS_ACCENTOVER(mPresentationData.flags) - ? 0 : 1; - PRUint32 compress = NS_MATHML_IS_ACCENTOVER(mPresentationData.flags) - ? NS_MATHML_COMPRESSED : 0; - overscriptMathMLFrame->UpdatePresentationData(aPresContext, increment, - ~NS_MATHML_DISPLAYSTYLE | compress, - NS_MATHML_DISPLAYSTYLE | compress); - overscriptMathMLFrame->UpdatePresentationDataFromChildAt(aPresContext, 0, -1, increment, - ~NS_MATHML_DISPLAYSTYLE | compress, - NS_MATHML_DISPLAYSTYLE | compress); - } - - // 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; - } + PRInt32 increment = NS_MATHML_EMBELLISH_IS_ACCENTOVER(mEmbellishData.flags) + ? 0 : 1; + PRUint32 compress = NS_MATHML_EMBELLISH_IS_ACCENTOVER(mEmbellishData.flags) + ? NS_MATHML_COMPRESSED : 0; + PropagatePresentationDataFor(aPresContext, overscriptFrame, increment, + ~NS_MATHML_DISPLAYSTYLE | compress, + NS_MATHML_DISPLAYSTYLE | compress); return NS_OK; } @@ -270,7 +254,7 @@ The REC says: often used for limits on symbols such as ∑. i.e.: - if ( NS_MATHML_IS_MOVABLELIMITS(mPresentationData.flags) && + if ( NS_MATHML_EMBELLISH_IS_MOVABLELIMITS(mEmbellishData.flags) && !NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags)) { // place like superscript } @@ -285,9 +269,7 @@ nsMathMLmoverFrame::Place(nsIPresContext* aPresContext, PRBool aPlaceOrigin, nsHTMLReflowMetrics& aDesiredSize) { - nsresult rv = NS_OK; - - if ( NS_MATHML_IS_MOVABLELIMITS(mPresentationData.flags) && + if ( NS_MATHML_EMBELLISH_IS_MOVABLELIMITS(mEmbellishData.flags) && !NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags)) { // place like superscript return nsMathMLmsupFrame::PlaceSuperScript(aPresContext, @@ -300,33 +282,20 @@ nsMathMLmoverFrame::Place(nsIPresContext* aPresContext, //////////////////////////////////// // Get the children's desired sizes - PRInt32 count = 0; nsBoundingMetrics bmBase, bmOver; - nsHTMLReflowMetrics baseSize (nsnull); - nsHTMLReflowMetrics overSize (nsnull); - nsIFrame* baseFrame = nsnull; + nsHTMLReflowMetrics baseSize(nsnull); + nsHTMLReflowMetrics overSize(nsnull); nsIFrame* overFrame = nsnull; - - nsIFrame* childFrame = mFrames.FirstChild(); - while (childFrame) { - if (0 == count) { - // base - baseFrame = childFrame; - GetReflowAndBoundingMetricsFor(baseFrame, baseSize, bmBase); - } - else if (1 == count) { - // over - overFrame = childFrame; - GetReflowAndBoundingMetricsFor(overFrame, overSize, bmOver); - } - count++; - childFrame->GetNextSibling(&childFrame); - } - if (2 != count) { + nsIFrame* baseFrame = mFrames.FirstChild(); + if (baseFrame) + baseFrame->GetNextSibling(&overFrame); + if (!baseFrame || !overFrame || HasNextSibling(overFrame)) { // report an error, encourage people to get their markups in order NS_WARNING("invalid markup"); return ReflowError(aPresContext, aRenderingContext, aDesiredSize); } + GetReflowAndBoundingMetricsFor(baseFrame, baseSize, bmBase); + GetReflowAndBoundingMetricsFor(overFrame, overSize, bmOver); //////////////////// // Place Children @@ -349,7 +318,7 @@ nsMathMLmoverFrame::Place(nsIPresContext* aPresContext, nscoord correction = 0; nscoord delta1 = 0; // gap between base and overscript nscoord delta2 = 0; // extra space above overscript - if (!NS_MATHML_IS_ACCENTOVER(mPresentationData.flags)) { + if (!NS_MATHML_EMBELLISH_IS_ACCENTOVER(mEmbellishData.flags)) { // Rule 13a, App. G, TeXbook GetItalicCorrection (bmBase, correction); nscoord bigOpSpacing1, bigOpSpacing3, bigOpSpacing5, dummy; @@ -424,7 +393,7 @@ nsMathMLmoverFrame::Place(nsIPresContext* aPresContext, dxOver = -bmOver.leftBearing; } - if (NS_MATHML_IS_ACCENTOVER(mPresentationData.flags)) { + if (NS_MATHML_EMBELLISH_IS_ACCENTOVER(mEmbellishData.flags)) { mBoundingMetrics.width = PR_MAX(bmBase.width, overWidth); } else { @@ -443,7 +412,7 @@ nsMathMLmoverFrame::Place(nsIPresContext* aPresContext, dxBase = (mBoundingMetrics.width - bmBase.width) / 2; dyBase = aDesiredSize.ascent - baseSize.ascent; - if (NS_MATHML_IS_ACCENTOVER(mPresentationData.flags)) { + if (NS_MATHML_EMBELLISH_IS_ACCENTOVER(mEmbellishData.flags)) { dxOver += correction + (mBoundingMetrics.width - overWidth)/2; } else { diff --git a/layout/mathml/base/src/nsMathMLmoverFrame.h b/layout/mathml/base/src/nsMathMLmoverFrame.h index 277fb861d2f3..eb8b842c4a52 100644 --- a/layout/mathml/base/src/nsMathMLmoverFrame.h +++ b/layout/mathml/base/src/nsMathMLmoverFrame.h @@ -41,6 +41,10 @@ public: PRBool aPlaceOrigin, nsHTMLReflowMetrics& aDesiredSize); + NS_IMETHOD + InheritAutomaticData(nsIPresContext* aPresContext, + nsIFrame* aParent); + NS_IMETHOD TransmitAutomaticData(nsIPresContext* aPresContext); @@ -58,6 +62,14 @@ public: PRUint32 aFlagsValues, PRUint32 aFlagsToUpdate); + NS_IMETHOD + AttributeChanged(nsIPresContext* aPresContext, + nsIContent* aChild, + PRInt32 aNameSpaceID, + nsIAtom* aAttribute, + PRInt32 aModType, + PRInt32 aHint); + protected: nsMathMLmoverFrame(); virtual ~nsMathMLmoverFrame(); diff --git a/layout/mathml/base/src/nsMathMLmpaddedFrame.cpp b/layout/mathml/base/src/nsMathMLmpaddedFrame.cpp index 1ff20fecd5fe..5a75ee123764 100644 --- a/layout/mathml/base/src/nsMathMLmpaddedFrame.cpp +++ b/layout/mathml/base/src/nsMathMLmpaddedFrame.cpp @@ -88,6 +88,14 @@ nsMathMLmpaddedFrame::InheritAutomaticData(nsIPresContext* aPresContext, // let the base class get the default from our parent nsMathMLContainerFrame::InheritAutomaticData(aPresContext, aParent); + mPresentationData.flags |= NS_MATHML_STRETCH_ALL_CHILDREN_VERTICALLY; + + return NS_OK; +} + +void +nsMathMLmpaddedFrame::ProcessAttributes(nsIPresContext* aPresContext) +{ /* parse the attributes @@ -135,8 +143,6 @@ nsMathMLmpaddedFrame::InheritAutomaticData(nsIPresContext* aPresContext, nsMathMLAtoms::lspace_, value)) { ParseAttribute(value, mLeftSpaceSign, mLeftSpace, mLeftSpacePseudoUnit); } - - return NS_OK; } PRBool @@ -350,16 +356,14 @@ nsMathMLmpaddedFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { - nsresult rv = NS_OK; + ProcessAttributes(aPresContext); /////////////// // Let the base class format our content like an inferred mrow - rv = nsMathMLContainerFrame::Reflow(aPresContext, aDesiredSize, - aReflowState, aStatus); - NS_ASSERTION(NS_FRAME_IS_COMPLETE(aStatus), "bad status"); - if (NS_FAILED(rv)) { - return rv; - } + nsresult rv = nsMathMLContainerFrame::Reflow(aPresContext, aDesiredSize, + aReflowState, aStatus); + //NS_ASSERTION(NS_FRAME_IS_COMPLETE(aStatus), "bad status"); + if (NS_FAILED(rv)) return rv; nscoord height = mBoundingMetrics.ascent; nscoord depth = mBoundingMetrics.descent; diff --git a/layout/mathml/base/src/nsMathMLmpaddedFrame.h b/layout/mathml/base/src/nsMathMLmpaddedFrame.h index 5249d64cab94..f61c554b6333 100644 --- a/layout/mathml/base/src/nsMathMLmpaddedFrame.h +++ b/layout/mathml/base/src/nsMathMLmpaddedFrame.h @@ -33,20 +33,10 @@ class nsMathMLmpaddedFrame : public nsMathMLContainerFrame { public: friend nsresult NS_NewMathMLmpaddedFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame); - - NS_IMETHOD - InheritAutomaticData(nsIPresContext* aPresContext, - nsIFrame* aParent); NS_IMETHOD - TransmitAutomaticData(nsIPresContext* aPresContext) - { -#if defined(NS_DEBUG) && defined(SHOW_BOUNDING_BOX) - mPresentationData.flags |= NS_MATHML_SHOW_BOUNDING_METRICS; -#endif - mEmbellishData.flags |= NS_MATHML_STRETCH_ALL_CHILDREN_VERTICALLY; - return NS_OK; - } + InheritAutomaticData(nsIPresContext* aPresContext, + nsIFrame* aParent); NS_IMETHOD Reflow(nsIPresContext* aPresContext, @@ -77,6 +67,9 @@ private: PRInt32 mLeftSpacePseudoUnit; // helpers to process the attributes + void + ProcessAttributes(nsIPresContext* aPresContext); + static PRBool ParseAttribute(nsString& aString, PRInt32& aSign, diff --git a/layout/mathml/base/src/nsMathMLmphantomFrame.cpp b/layout/mathml/base/src/nsMathMLmphantomFrame.cpp index 21a4b535497d..e1162de4dc3b 100644 --- a/layout/mathml/base/src/nsMathMLmphantomFrame.cpp +++ b/layout/mathml/base/src/nsMathMLmphantomFrame.cpp @@ -67,9 +67,14 @@ nsMathMLmphantomFrame::~nsMathMLmphantomFrame() } NS_IMETHODIMP -nsMathMLmphantomFrame::TransmitAutomaticData(nsIPresContext* aPresContext) +nsMathMLmphantomFrame::InheritAutomaticData(nsIPresContext* aPresContext, + nsIFrame* aParent) { - mEmbellishData.flags |= NS_MATHML_STRETCH_ALL_CHILDREN_VERTICALLY; + // let the base class get the default from our parent + nsMathMLContainerFrame::InheritAutomaticData(aPresContext, aParent); + + mPresentationData.flags |= NS_MATHML_STRETCH_ALL_CHILDREN_VERTICALLY; + return NS_OK; } diff --git a/layout/mathml/base/src/nsMathMLmphantomFrame.h b/layout/mathml/base/src/nsMathMLmphantomFrame.h index dba2631be5f5..b27aab791032 100644 --- a/layout/mathml/base/src/nsMathMLmphantomFrame.h +++ b/layout/mathml/base/src/nsMathMLmphantomFrame.h @@ -35,7 +35,8 @@ public: friend nsresult NS_NewMathMLmphantomFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame); NS_IMETHOD - TransmitAutomaticData(nsIPresContext* aPresContext); + InheritAutomaticData(nsIPresContext* aPresContext, + nsIFrame* aParent); NS_IMETHOD Paint(nsIPresContext* aPresContext, diff --git a/layout/mathml/base/src/nsMathMLmrootFrame.cpp b/layout/mathml/base/src/nsMathMLmrootFrame.cpp index b498cff23c77..4332740cd143 100644 --- a/layout/mathml/base/src/nsMathMLmrootFrame.cpp +++ b/layout/mathml/base/src/nsMathMLmrootFrame.cpp @@ -47,8 +47,8 @@ //NOTE: // The code assumes that TeX fonts are picked. -// There is not fall-back to draw the branches of the sqrt explicitly -// in the case where TeX fonts are not there. In general, there is not +// There is no fall-back to draw the branches of the sqrt explicitly +// in the case where TeX fonts are not there. In general, there are no // fall-back(s) in MathML when some (freely-downloadable) fonts are missing. // Otherwise, this will add much work and unnecessary complexity to the core // MathML engine. Assuming that authors have the free fonts is part of the @@ -91,17 +91,35 @@ nsMathMLmrootFrame::Init(nsIPresContext* aPresContext, nsIStyleContext* aContext, nsIFrame* aPrevInFlow) { - nsresult rv = NS_OK; - rv = nsMathMLContainerFrame::Init(aPresContext, aContent, aParent, - aContext, aPrevInFlow); + nsresult rv = nsMathMLContainerFrame::Init(aPresContext, aContent, aParent, + aContext, aPrevInFlow); + // No need to tract the style context given to our MathML char. + // The Style System will use Get/SetAdditionalStyleContext() to keep it + // up-to-date if dynamic changes arise. nsAutoString sqrChar; sqrChar.Assign(kSqrChar); mSqrChar.SetData(aPresContext, sqrChar); - ResolveMathMLCharStyle(aPresContext, mContent, mStyleContext, &mSqrChar); + ResolveMathMLCharStyle(aPresContext, mContent, mStyleContext, &mSqrChar, PR_TRUE); return rv; } +NS_IMETHODIMP +nsMathMLmrootFrame::TransmitAutomaticData(nsIPresContext* aPresContext) +{ + // 1. The REC says: + // The element increments scriptlevel by 2, and sets displaystyle to + // "false", within index, but leaves both attributes unchanged within base. + // 2. The TeXbook (Ch 17. p.141) says \sqrt is compressed + UpdatePresentationDataFromChildAt(aPresContext, 1, 1, 2, + ~NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED, + NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED); + UpdatePresentationDataFromChildAt(aPresContext, 0, 0, 0, + NS_MATHML_COMPRESSED, NS_MATHML_COMPRESSED); + + return NS_OK; +} + NS_IMETHODIMP nsMathMLmrootFrame::Paint(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, @@ -109,21 +127,17 @@ nsMathMLmrootFrame::Paint(nsIPresContext* aPresContext, nsFramePaintLayer aWhichLayer, PRUint32 aFlags) { - nsresult rv = NS_OK; - ///////////// // paint the content we are square-rooting - rv = nsMathMLContainerFrame::Paint(aPresContext, aRenderingContext, - aDirtyRect, aWhichLayer); + nsresult rv = nsMathMLContainerFrame::Paint(aPresContext, aRenderingContext, + aDirtyRect, aWhichLayer); ///////////// // paint the sqrt symbol - if (!NS_MATHML_HAS_ERROR(mPresentationData.flags)) - { + if (!NS_MATHML_HAS_ERROR(mPresentationData.flags)) { mSqrChar.Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer, this); - if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) - { + if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) { // paint the overline bar const nsStyleColor *color = NS_STATIC_CAST(const nsStyleColor*, mStyleContext->GetStyleData(eStyleStruct_Color)); @@ -133,8 +147,7 @@ nsMathMLmrootFrame::Paint(nsIPresContext* aPresContext, #if defined(NS_DEBUG) && defined(SHOW_BOUNDING_BOX) // for visual debug - if (NS_MATHML_PAINT_BOUNDING_METRICS(mPresentationData.flags)) - { + if (NS_MATHML_PAINT_BOUNDING_METRICS(mPresentationData.flags)) { nsRect rect; mSqrChar.GetRect(rect); diff --git a/layout/mathml/base/src/nsMathMLmrootFrame.h b/layout/mathml/base/src/nsMathMLmrootFrame.h index 7f9b1aed8ee9..abd1241f790a 100644 --- a/layout/mathml/base/src/nsMathMLmrootFrame.h +++ b/layout/mathml/base/src/nsMathMLmrootFrame.h @@ -50,22 +50,7 @@ public: nsIFrame* aPrevInFlow); NS_IMETHOD - TransmitAutomaticData(nsIPresContext* aPresContext) - { -#if defined(NS_DEBUG) && defined(SHOW_BOUNDING_BOX) - mPresentationData.flags |= NS_MATHML_SHOW_BOUNDING_METRICS; -#endif - // 1. The REC says: - // The element increments scriptlevel by 2, and sets displaystyle to - // "false", within index, but leaves both attributes unchanged within base. - // 2. The TeXbook (Ch 17. p.141) says \sqrt is compressed - UpdatePresentationDataFromChildAt(aPresContext, 1, 1, 2, - ~NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED, - NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED); - UpdatePresentationDataFromChildAt(aPresContext, 0, 0, 0, - NS_MATHML_COMPRESSED, NS_MATHML_COMPRESSED); - return NS_OK; - } + TransmitAutomaticData(nsIPresContext* aPresContext); NS_IMETHOD Reflow(nsIPresContext* aPresContext, diff --git a/layout/mathml/base/src/nsMathMLmrowFrame.cpp b/layout/mathml/base/src/nsMathMLmrowFrame.cpp index a7b52d3f1e53..cc898c779fe0 100644 --- a/layout/mathml/base/src/nsMathMLmrowFrame.cpp +++ b/layout/mathml/base/src/nsMathMLmrowFrame.cpp @@ -67,13 +67,13 @@ nsMathMLmrowFrame::~nsMathMLmrowFrame() } NS_IMETHODIMP -nsMathMLmrowFrame::TransmitAutomaticData(nsIPresContext* aPresContext) +nsMathMLmrowFrame::InheritAutomaticData(nsIPresContext* aPresContext, + nsIFrame* aParent) { -#if defined(NS_DEBUG) && defined(SHOW_BOUNDING_BOX) - mPresentationData.flags |= NS_MATHML_SHOW_BOUNDING_METRICS; -#endif + // let the base class get the default from our parent + nsMathMLContainerFrame::InheritAutomaticData(aPresContext, aParent); - mEmbellishData.flags |= NS_MATHML_STRETCH_ALL_CHILDREN_VERTICALLY; + mPresentationData.flags |= NS_MATHML_STRETCH_ALL_CHILDREN_VERTICALLY; return NS_OK; } diff --git a/layout/mathml/base/src/nsMathMLmrowFrame.h b/layout/mathml/base/src/nsMathMLmrowFrame.h index 9d2d6a887bc5..4a21ee8b749a 100644 --- a/layout/mathml/base/src/nsMathMLmrowFrame.h +++ b/layout/mathml/base/src/nsMathMLmrowFrame.h @@ -33,14 +33,15 @@ class nsMathMLmrowFrame : public nsMathMLContainerFrame { public: friend nsresult NS_NewMathMLmrowFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame); - + NS_IMETHOD - TransmitAutomaticData(nsIPresContext* aPresContext); + InheritAutomaticData(nsIPresContext* aPresContext, + nsIFrame* aParent); protected: nsMathMLmrowFrame(); virtual ~nsMathMLmrowFrame(); - + virtual PRIntn GetSkipSides() const { return 0; } }; diff --git a/layout/mathml/base/src/nsMathMLmsFrame.cpp b/layout/mathml/base/src/nsMathMLmsFrame.cpp index db94c98b8f4d..d2e872ac9859 100644 --- a/layout/mathml/base/src/nsMathMLmsFrame.cpp +++ b/layout/mathml/base/src/nsMathMLmsFrame.cpp @@ -37,6 +37,7 @@ #include "nsStyleUtil.h" #include "nsIDOMText.h" +#include "nsITextContent.h" #include "nsMathMLmsFrame.h" @@ -67,11 +68,8 @@ nsMathMLmsFrame::~nsMathMLmsFrame() { } - NS_IMETHODIMP -nsMathMLmsFrame::SetInitialChildList(nsIPresContext* aPresContext, - nsIAtom* aListName, - nsIFrame* aChildList) +nsMathMLmsFrame::TransmitAutomaticData(nsIPresContext* aPresContext) { // It is assumed that the mathml.css file contains two rules: // ms:before { content: open-quote; } @@ -86,48 +84,73 @@ nsMathMLmsFrame::SetInitialChildList(nsIPresContext* aPresContext, // But what if the mathml.css file wasn't loaded? // We also check that we are not relying on null pointers... - PRInt32 count = 0; nsIFrame* rightFrame = nsnull; - nsIFrame* leftFrame = nsnull; - nsIFrame* childFrame = aChildList; - while (childFrame) { - if (0 == count) leftFrame = childFrame; - // 1 == count is the the frame for the actual content of - else if (2 == count) rightFrame = childFrame; - count++; - childFrame->GetNextSibling(&childFrame); - } + nsIFrame* baseFrame = nsnull; + nsIFrame* leftFrame = mFrames.FirstChild(); + if (leftFrame) + leftFrame->GetNextSibling(&baseFrame); + if (baseFrame) + baseFrame->GetNextSibling(&rightFrame); + if (!leftFrame || !baseFrame || !rightFrame) + return NS_OK; - if (3 == count && leftFrame && rightFrame) { - nsAutoString value; - nsIFrame* textFrame; - nsCOMPtr quoteContent; - // lquote - if (NS_CONTENT_ATTR_HAS_VALUE == GetAttribute(mContent, mPresentationData.mstyle, - nsMathMLAtoms::lquote_, value)) { - leftFrame->FirstChild(aPresContext, nsnull, &textFrame); - if (textFrame) { - textFrame->GetContent(getter_AddRefs(quoteContent)); - if (quoteContent.get()) { - nsCOMPtr domText(do_QueryInterface(quoteContent)); - if (domText.get()) domText->SetData(value); + nsAutoString value; + nsIFrame* textFrame; + nsCOMPtr quoteContent; + // lquote + if (NS_CONTENT_ATTR_HAS_VALUE == GetAttribute(mContent, mPresentationData.mstyle, + nsMathMLAtoms::lquote_, value)) { + leftFrame->FirstChild(aPresContext, nsnull, &textFrame); + if (textFrame) { + textFrame->GetContent(getter_AddRefs(quoteContent)); + if (quoteContent.get()) { + nsCOMPtr domText(do_QueryInterface(quoteContent)); + if (domText.get()) { + nsCOMPtr tc(do_QueryInterface(quoteContent)); + if (tc) { + tc->SetText(value, PR_FALSE); // no notify since we don't want a reflow yet + } } } } - // rquote - if (NS_CONTENT_ATTR_HAS_VALUE == GetAttribute(mContent, mPresentationData.mstyle, - nsMathMLAtoms::rquote_, value)) { - rightFrame->FirstChild(aPresContext, nsnull, &textFrame); - if (textFrame) { - textFrame->GetContent(getter_AddRefs(quoteContent)); - if (quoteContent.get()) { - nsCOMPtr domText(do_QueryInterface(quoteContent)); - if (domText.get()) domText->SetData(value); + } + // rquote + if (NS_CONTENT_ATTR_HAS_VALUE == GetAttribute(mContent, mPresentationData.mstyle, + nsMathMLAtoms::rquote_, value)) { + rightFrame->FirstChild(aPresContext, nsnull, &textFrame); + if (textFrame) { + textFrame->GetContent(getter_AddRefs(quoteContent)); + if (quoteContent.get()) { + nsCOMPtr domText(do_QueryInterface(quoteContent)); + if (domText.get()) { + nsCOMPtr tc(do_QueryInterface(quoteContent)); + if (tc) { + tc->SetText(value, PR_FALSE); // no notify since we don't want a reflow yet + } } } } } - // let the base class take care of the rest - return nsMathMLContainerFrame::SetInitialChildList(aPresContext, aListName, aChildList); + return NS_OK; +} + +NS_IMETHODIMP +nsMathMLmsFrame::AttributeChanged(nsIPresContext* aPresContext, + nsIContent* aContent, + PRInt32 aNameSpaceID, + nsIAtom* aAttribute, + PRInt32 aModType, + PRInt32 aHint) +{ + if (nsMathMLAtoms::lquote_ == aAttribute || + nsMathMLAtoms::rquote_ == aAttribute) { + // When the automatic data to update are only within our + // children, we just re-layout them + return ReLayoutChildren(aPresContext, this); + } + + return nsMathMLContainerFrame:: + AttributeChanged(aPresContext, aContent, aNameSpaceID, + aAttribute, aModType, aHint); } diff --git a/layout/mathml/base/src/nsMathMLmsFrame.h b/layout/mathml/base/src/nsMathMLmsFrame.h index b91f6163b431..65ebd1284637 100644 --- a/layout/mathml/base/src/nsMathMLmsFrame.h +++ b/layout/mathml/base/src/nsMathMLmsFrame.h @@ -33,26 +33,17 @@ class nsMathMLmsFrame : public nsMathMLContainerFrame { public: friend nsresult NS_NewMathMLmsFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame); -#if 0 NS_IMETHOD - Init(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIFrame* aParent, - nsIStyleContext* aContext, - nsIFrame* aPrevInFlow); -#endif + TransmitAutomaticData(nsIPresContext* aPresContext); NS_IMETHOD - SetInitialChildList(nsIPresContext* aPresContext, - nsIAtom* aListName, - nsIFrame* aChildList); -#if 0 - NS_IMETHOD - Reflow(nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus); -#endif + AttributeChanged(nsIPresContext* aPresContext, + nsIContent* aChild, + PRInt32 aNameSpaceID, + nsIAtom* aAttribute, + PRInt32 aModType, + PRInt32 aHint); + protected: nsMathMLmsFrame(); virtual ~nsMathMLmsFrame(); diff --git a/layout/mathml/base/src/nsMathMLmspaceFrame.cpp b/layout/mathml/base/src/nsMathMLmspaceFrame.cpp index ec3f24981fa2..a77c7d49a85d 100644 --- a/layout/mathml/base/src/nsMathMLmspaceFrame.cpp +++ b/layout/mathml/base/src/nsMathMLmspaceFrame.cpp @@ -66,17 +66,9 @@ nsMathMLmspaceFrame::~nsMathMLmspaceFrame() { } -NS_IMETHODIMP -nsMathMLmspaceFrame::Init(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIFrame* aParent, - nsIStyleContext* aContext, - nsIFrame* aPrevInFlow) +void +nsMathMLmspaceFrame::ProcessAttributes(nsIPresContext* aPresContext) { - nsresult rv = nsMathMLContainerFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow); - -// mEmbellishData.flags = NS_MATHML_SPACELIKE; - /* parse the attributes @@ -85,9 +77,6 @@ nsMathMLmspaceFrame::Init(nsIPresContext* aPresContext, depth = number v-unit */ - // XXX Need to check what will happen in case of style changes - // These may have to be moved in Reflow() to capture style changes - nsAutoString value; nsCSSValue cssValue; @@ -123,8 +112,6 @@ nsMathMLmspaceFrame::Init(nsIPresContext* aPresContext, mDepth = CalcLength(aPresContext, mStyleContext, cssValue); } } - - return rv; } NS_IMETHODIMP @@ -132,7 +119,9 @@ nsMathMLmspaceFrame::Reflow(nsIPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) -{ +{ + ProcessAttributes(aPresContext); + mBoundingMetrics.Clear(); mBoundingMetrics.width = mWidth; mBoundingMetrics.ascent = mHeight; diff --git a/layout/mathml/base/src/nsMathMLmspaceFrame.h b/layout/mathml/base/src/nsMathMLmspaceFrame.h index e11af9d8cb87..04c511ab5faa 100644 --- a/layout/mathml/base/src/nsMathMLmspaceFrame.h +++ b/layout/mathml/base/src/nsMathMLmspaceFrame.h @@ -32,13 +32,6 @@ class nsMathMLmspaceFrame : public nsMathMLContainerFrame { public: friend nsresult NS_NewMathMLmspaceFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame); - - NS_IMETHOD - Init(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIFrame* aParent, - nsIStyleContext* aContext, - nsIFrame* aPrevInFlow); NS_IMETHOD Reflow(nsIPresContext* aPresContext, @@ -56,6 +49,10 @@ private: nscoord mWidth; nscoord mHeight; nscoord mDepth; + + // helper method to initialize our member data + void + ProcessAttributes(nsIPresContext* aPresContext); }; #endif /* nsMathMLmspaceFrame_h___ */ diff --git a/layout/mathml/base/src/nsMathMLmsqrtFrame.cpp b/layout/mathml/base/src/nsMathMLmsqrtFrame.cpp index c83fb5a66e6f..fc1e604e911f 100644 --- a/layout/mathml/base/src/nsMathMLmsqrtFrame.cpp +++ b/layout/mathml/base/src/nsMathMLmsqrtFrame.cpp @@ -47,8 +47,8 @@ //NOTE: // The code assumes that TeX fonts are picked. -// There is not fall-back to draw the branches of the sqrt explicitly -// in the case where TeX fonts are not there. In general, there is not +// There is no fall-back to draw the branches of the sqrt explicitly +// in the case where TeX fonts are not there. In general, there are no // fall-back(s) in MathML when some (freely-downloadable) fonts are missing. // Otherwise, this will add much work and unnecessary complexity to the core // MathML engine. Assuming that authors have the free fonts is part of the @@ -91,17 +91,45 @@ nsMathMLmsqrtFrame::Init(nsIPresContext* aPresContext, nsIStyleContext* aContext, nsIFrame* aPrevInFlow) { - nsresult rv = NS_OK; - rv = nsMathMLContainerFrame::Init(aPresContext, aContent, aParent, - aContext, aPrevInFlow); + nsresult rv = nsMathMLContainerFrame::Init(aPresContext, aContent, aParent, + aContext, aPrevInFlow); + // No need to tract the style context given to our MathML char. + // The Style System will use Get/SetAdditionalStyleContext() to keep it + // up-to-date if dynamic changes arise. nsAutoString sqrChar; sqrChar.Assign(kSqrChar); mSqrChar.SetData(aPresContext, sqrChar); - ResolveMathMLCharStyle(aPresContext, mContent, mStyleContext, &mSqrChar); + ResolveMathMLCharStyle(aPresContext, mContent, mStyleContext, &mSqrChar, PR_TRUE); return rv; } +NS_IMETHODIMP +nsMathMLmsqrtFrame::InheritAutomaticData(nsIPresContext* aPresContext, + nsIFrame* aParent) +{ + // let the base class get the default from our parent + nsMathMLContainerFrame::InheritAutomaticData(aPresContext, aParent); + + mPresentationData.flags |= NS_MATHML_STRETCH_ALL_CHILDREN_VERTICALLY; + + return NS_OK; +} + +NS_IMETHODIMP +nsMathMLmsqrtFrame::TransmitAutomaticData(nsIPresContext* aPresContext) +{ + // 1. The REC says: + // The element leaves both attributes [displaystyle and scriptlevel] + // unchanged within all its arguments. + // 2. The TeXBook (Ch 17. p.141) says that \sqrt is cramped + UpdatePresentationDataFromChildAt(aPresContext, 0, -1, 0, + NS_MATHML_COMPRESSED, + NS_MATHML_COMPRESSED); + + return NS_OK; +} + NS_IMETHODIMP nsMathMLmsqrtFrame::Paint(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, @@ -109,21 +137,17 @@ nsMathMLmsqrtFrame::Paint(nsIPresContext* aPresContext, nsFramePaintLayer aWhichLayer, PRUint32 aFlags) { - nsresult rv = NS_OK; - ///////////// // paint the content we are square-rooting - rv = nsMathMLContainerFrame::Paint(aPresContext, aRenderingContext, - aDirtyRect, aWhichLayer); + nsresult rv = nsMathMLContainerFrame::Paint(aPresContext, aRenderingContext, + aDirtyRect, aWhichLayer); ///////////// // paint the sqrt symbol - if (!NS_MATHML_HAS_ERROR(mPresentationData.flags)) - { + if (!NS_MATHML_HAS_ERROR(mPresentationData.flags)) { mSqrChar.Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer, this); - if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) - { + if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) { // paint the overline bar const nsStyleColor *color = NS_STATIC_CAST(const nsStyleColor*, mStyleContext->GetStyleData(eStyleStruct_Color)); @@ -133,8 +157,7 @@ nsMathMLmsqrtFrame::Paint(nsIPresContext* aPresContext, #if defined(NS_DEBUG) && defined(SHOW_BOUNDING_BOX) // for visual debug - if (NS_MATHML_PAINT_BOUNDING_METRICS(mPresentationData.flags)) - { + if (NS_MATHML_PAINT_BOUNDING_METRICS(mPresentationData.flags)) { nsRect rect; mSqrChar.GetRect(rect); @@ -160,18 +183,15 @@ nsMathMLmsqrtFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { - nsresult rv = NS_OK; - - nsBoundingMetrics bmSqr, bmBase; - /////////////// // Let the base class format our content like an inferred mrow nsHTMLReflowMetrics baseSize(aDesiredSize); - rv = nsMathMLContainerFrame::Reflow(aPresContext, baseSize, - aReflowState, aStatus); + nsresult rv = nsMathMLContainerFrame::Reflow(aPresContext, baseSize, + aReflowState, aStatus); //NS_ASSERTION(NS_FRAME_IS_COMPLETE(aStatus), "bad status"); if (NS_FAILED(rv)) return rv; + nsBoundingMetrics bmSqr, bmBase; bmBase = baseSize.mBoundingMetrics; //////////// diff --git a/layout/mathml/base/src/nsMathMLmsqrtFrame.h b/layout/mathml/base/src/nsMathMLmsqrtFrame.h index c1a4777c1215..47936a151d02 100644 --- a/layout/mathml/base/src/nsMathMLmsqrtFrame.h +++ b/layout/mathml/base/src/nsMathMLmsqrtFrame.h @@ -87,21 +87,10 @@ public: PRUint32 aFlags = 0); NS_IMETHOD - TransmitAutomaticData(nsIPresContext* aPresContext) - { -#if defined(NS_DEBUG) && defined(SHOW_BOUNDING_BOX) - mPresentationData.flags |= NS_MATHML_SHOW_BOUNDING_METRICS; -#endif - mEmbellishData.flags |= NS_MATHML_STRETCH_ALL_CHILDREN_VERTICALLY; - // 1. The REC says: - // The element leaves both attributes [displaystyle and scriptlevel] - // unchanged within all its arguments. - // 2. The TeXBook (Ch 17. p.141) says that \sqrt is cramped - UpdatePresentationDataFromChildAt(aPresContext, 0, -1, 0, - NS_MATHML_COMPRESSED, - NS_MATHML_COMPRESSED); - return NS_OK; - } + InheritAutomaticData(nsIPresContext* aPresContext, + nsIFrame* aParent); + NS_IMETHOD + TransmitAutomaticData(nsIPresContext* aPresContext); protected: nsMathMLmsqrtFrame(); diff --git a/layout/mathml/base/src/nsMathMLmstyleFrame.cpp b/layout/mathml/base/src/nsMathMLmstyleFrame.cpp index 8ef0316a864e..4e94f6a09c61 100644 --- a/layout/mathml/base/src/nsMathMLmstyleFrame.cpp +++ b/layout/mathml/base/src/nsMathMLmstyleFrame.cpp @@ -75,7 +75,7 @@ nsMathMLmstyleFrame::InheritAutomaticData(nsIPresContext* aPresContext, nsMathMLContainerFrame::InheritAutomaticData(aPresContext, aParent); // sync with our current state - + mPresentationData.flags |= NS_MATHML_STRETCH_ALL_CHILDREN_VERTICALLY; mPresentationData.mstyle = this; // see if the displaystyle attribute is there @@ -114,8 +114,6 @@ nsMathMLmstyleFrame::InheritAutomaticData(nsIPresContext* aPresContext, NS_IMETHODIMP nsMathMLmstyleFrame::TransmitAutomaticData(nsIPresContext* aPresContext) { - mEmbellishData.flags |= NS_MATHML_STRETCH_ALL_CHILDREN_VERTICALLY; - // Nothing particular to do here, the values that we computed in // InheritAutomaticData() are the values that we wanted to pass to // our children. Our children would have inherited these values in @@ -205,17 +203,10 @@ nsMathMLmstyleFrame::AttributeChanged(nsIPresContext* aPresContext, PRInt32 aModType, PRInt32 aHint) { - if (nsMathMLAtoms::displaystyle_ == aAttribute || - nsMathMLAtoms::scriptlevel_ == aAttribute) { - // These attributes can affect too many things, ask our parent to re-layout - // its children so that we can pick up changes in our attributes & transmit - // them in our subtree. However, our siblings will be re-laid too. We used - // to have a more speedier but more verbose alternative that didn't re-layout - // our siblings. See bug 114909 - attachment 67668. - return ReLayout(aPresContext, mParent); - } - - return nsMathMLContainerFrame:: - AttributeChanged(aPresContext, aContent, aNameSpaceID, - aAttribute, aModType, aHint); + // These attributes can affect too many things, ask our parent to re-layout + // its children so that we can pick up changes in our attributes & transmit + // them in our subtree. However, our siblings will be re-laid too. We used + // to have a more speedier but more verbose alternative that didn't re-layout + // our siblings. See bug 114909 - attachment 67668. + return ReLayoutChildren(aPresContext, mParent); } diff --git a/layout/mathml/base/src/nsMathMLmsubFrame.cpp b/layout/mathml/base/src/nsMathMLmsubFrame.cpp index 2bc07eaf6399..f57e0b10b26c 100644 --- a/layout/mathml/base/src/nsMathMLmsubFrame.cpp +++ b/layout/mathml/base/src/nsMathMLmsubFrame.cpp @@ -67,6 +67,26 @@ nsMathMLmsubFrame::~nsMathMLmsubFrame() { } +NS_IMETHODIMP +nsMathMLmsubFrame::TransmitAutomaticData(nsIPresContext* aPresContext) +{ + // if our base is an embellished operator, let its state bubble to us + nsIFrame* baseFrame = mFrames.FirstChild(); + GetEmbellishDataFrom(baseFrame, mEmbellishData); + if (NS_MATHML_IS_EMBELLISH_OPERATOR(mEmbellishData.flags)) + mEmbellishData.nextFrame = baseFrame; + + // 1. The REC says: + // The element increments scriptlevel by 1, and sets displaystyle to + // "false", within subscript, but leaves both attributes unchanged within base. + // 2. The TeXbook (Ch 17. p.141) says the subscript is compressed + UpdatePresentationDataFromChildAt(aPresContext, 1, -1, 1, + ~NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED, + NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED); + + return NS_OK; +} + NS_IMETHODIMP nsMathMLmsubFrame::Place (nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, @@ -107,13 +127,10 @@ nsMathMLmsubFrame::PlaceSubScript (nsIPresContext* aPresContext, nscoord aUserSubScriptShift, nscoord aScriptSpace) { - nsresult rv = NS_OK; - // the caller better be a mathml frame - nsIMathMLFrame* mathMLFrame = nsnull; - rv = aFrame->QueryInterface (NS_GET_IID(nsIMathMLFrame), - (void**)&mathMLFrame); - if (NS_FAILED(rv) || !mathMLFrame) return rv; + nsIMathMLFrame* mathMLFrame; + aFrame->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame); + if (!mathMLFrame) return NS_ERROR_INVALID_ARG; // force the scriptSpace to be atleast 1 pixel float p2t; @@ -123,38 +140,15 @@ nsMathMLmsubFrame::PlaceSubScript (nsIPresContext* aPresContext, //////////////////////////////////// // Get the children's desired sizes - PRInt32 count = 0; - nsHTMLReflowMetrics baseSize (nsnull); - nsHTMLReflowMetrics subScriptSize (nsnull); - nsIFrame* baseFrame = nsnull; - nsIFrame* subScriptFrame = nsnull; - // parameter v, Rule 18a, Appendix G of the TeXbook - nscoord minSubScriptShift = 0; - nsBoundingMetrics bmBase, bmSubScript; - - nsIFrame* childFrame = nsnull; - aFrame->FirstChild(aPresContext, nsnull, &childFrame); - while (childFrame) { - if (0 == count) { - // base - baseFrame = childFrame; - GetReflowAndBoundingMetricsFor(baseFrame, baseSize, bmBase); - } - else if (1 == count) { - // subscript - subScriptFrame = childFrame; - GetReflowAndBoundingMetricsFor(subScriptFrame, subScriptSize, bmSubScript); - // get the subdrop from the subscript font - nscoord subDrop; - GetSubDropFromChild (aPresContext, subScriptFrame, subDrop); - // parameter v, Rule 18a, App. G, TeXbook - minSubScriptShift = bmBase.descent + subDrop; - } - count++; - childFrame->GetNextSibling(&childFrame); - } - if (2 != count) { + nsHTMLReflowMetrics baseSize(nsnull); + nsHTMLReflowMetrics subScriptSize(nsnull); + nsIFrame* baseFrame; + aFrame->FirstChild(aPresContext, nsnull, &baseFrame); + nsIFrame* subScriptFrame = nsnull; + if (baseFrame) + baseFrame->GetNextSibling(&subScriptFrame); + if (!baseFrame || !subScriptFrame || HasNextSibling(subScriptFrame)) { // report an error, encourage people to get their markups in order NS_WARNING("invalid markup"); return NS_STATIC_CAST(nsMathMLContainerFrame*, @@ -162,6 +156,14 @@ nsMathMLmsubFrame::PlaceSubScript (nsIPresContext* aPresContext, aRenderingContext, aDesiredSize); } + GetReflowAndBoundingMetricsFor(baseFrame, baseSize, bmBase); + GetReflowAndBoundingMetricsFor(subScriptFrame, subScriptSize, bmSubScript); + + // get the subdrop from the subscript font + nscoord subDrop; + GetSubDropFromChild(aPresContext, subScriptFrame, subDrop); + // parameter v, Rule 18a, App. G, TeXbook + nscoord minSubScriptShift = bmBase.descent + subDrop; ////////////////// // Place Children @@ -171,9 +173,6 @@ nsMathMLmsubFrame::PlaceSubScript (nsIPresContext* aPresContext, nscoord xHeight = 0; nsCOMPtr fm; -// const nsStyleFont* aFont = -// (const nsStyleFont*) mStyleContext->GetStyleData (eStyleStruct_Font); - const nsStyleFont* font; baseFrame->GetStyleData(eStyleStruct_Font, (const nsStyleStruct *&)font); diff --git a/layout/mathml/base/src/nsMathMLmsubFrame.h b/layout/mathml/base/src/nsMathMLmsubFrame.h index 67e7eb39c835..488cd9b8243a 100644 --- a/layout/mathml/base/src/nsMathMLmsubFrame.h +++ b/layout/mathml/base/src/nsMathMLmsubFrame.h @@ -35,6 +35,9 @@ class nsMathMLmsubFrame : public nsMathMLContainerFrame { public: friend nsresult NS_NewMathMLmsubFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame); + NS_IMETHOD + TransmitAutomaticData(nsIPresContext* aPresContext); + NS_IMETHOD Place(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, @@ -50,25 +53,6 @@ public: nscoord aUserSubScriptShift = 0, nscoord aScriptSpace = NSFloatPointsToTwips(0.5f)); - NS_IMETHOD - TransmitAutomaticData(nsIPresContext* aPresContext) - { -#if defined(NS_DEBUG) && defined(SHOW_BOUNDING_BOX) - mPresentationData.flags |= NS_MATHML_SHOW_BOUNDING_METRICS; -#endif - - // check whether or not this is an embellished operator - EmbellishOperator(); - // 1. The REC says: - // The element increments scriptlevel by 1, and sets displaystyle to - // "false", within subscript, but leaves both attributes unchanged within base. - // 2. The TeXbook (Ch 17. p.141) says the subscript is compressed - UpdatePresentationDataFromChildAt(aPresContext, 1, -1, 1, - ~NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED, - NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED); - return NS_OK; - } - protected: nsMathMLmsubFrame(); virtual ~nsMathMLmsubFrame(); diff --git a/layout/mathml/base/src/nsMathMLmsubsupFrame.cpp b/layout/mathml/base/src/nsMathMLmsubsupFrame.cpp index 5c4b25796030..33b1067ef966 100644 --- a/layout/mathml/base/src/nsMathMLmsubsupFrame.cpp +++ b/layout/mathml/base/src/nsMathMLmsubsupFrame.cpp @@ -68,10 +68,35 @@ nsMathMLmsubsupFrame::~nsMathMLmsubsupFrame() } NS_IMETHODIMP -nsMathMLmsubsupFrame::Place (nsIPresContext* aPresContext, - nsIRenderingContext& aRenderingContext, - PRBool aPlaceOrigin, - nsHTMLReflowMetrics& aDesiredSize) +nsMathMLmsubsupFrame::TransmitAutomaticData(nsIPresContext* aPresContext) +{ + // if our base is an embellished operator, let its state bubble to us + nsIFrame* baseFrame = mFrames.FirstChild(); + GetEmbellishDataFrom(baseFrame, mEmbellishData); + if (NS_MATHML_IS_EMBELLISH_OPERATOR(mEmbellishData.flags)) + mEmbellishData.nextFrame = baseFrame; + + // 1. The REC says: + // The element increments scriptlevel by 1, and sets displaystyle to + // "false", within subscript and superscript, but leaves both attributes + // unchanged within base. + // 2. The TeXbook (Ch 17. p.141) says the superscript inherits the compression + // while the subscript is compressed + UpdatePresentationDataFromChildAt(aPresContext, 1, -1, 1, + ~NS_MATHML_DISPLAYSTYLE, + NS_MATHML_DISPLAYSTYLE); + UpdatePresentationDataFromChildAt(aPresContext, 1, 1, 0, + NS_MATHML_COMPRESSED, + NS_MATHML_COMPRESSED); + + return NS_OK; +} + +NS_IMETHODIMP +nsMathMLmsubsupFrame::Place(nsIPresContext* aPresContext, + nsIRenderingContext& aRenderingContext, + PRBool aPlaceOrigin, + nsHTMLReflowMetrics& aDesiredSize) { // extra spacing between base and sup/subscript nscoord scriptSpace = 0; @@ -96,90 +121,55 @@ nsMathMLmsubsupFrame::Place (nsIPresContext* aPresContext, } } - return nsMathMLmsubsupFrame::PlaceSubSupScript (aPresContext, - aRenderingContext, - aPlaceOrigin, - aDesiredSize, - this, - subScriptShift, - supScriptShift, - scriptSpace); + return nsMathMLmsubsupFrame::PlaceSubSupScript(aPresContext, + aRenderingContext, + aPlaceOrigin, + aDesiredSize, + this, + subScriptShift, + supScriptShift, + scriptSpace); } // exported routine that both munderover and msubsup share. // munderover uses this when movablelimits is set. nsresult -nsMathMLmsubsupFrame::PlaceSubSupScript (nsIPresContext* aPresContext, - nsIRenderingContext& aRenderingContext, - PRBool aPlaceOrigin, - nsHTMLReflowMetrics& aDesiredSize, - nsIFrame* aFrame, - nscoord aUserSubScriptShift, - nscoord aUserSupScriptShift, - nscoord aScriptSpace) +nsMathMLmsubsupFrame::PlaceSubSupScript(nsIPresContext* aPresContext, + nsIRenderingContext& aRenderingContext, + PRBool aPlaceOrigin, + nsHTMLReflowMetrics& aDesiredSize, + nsIFrame* aFrame, + nscoord aUserSubScriptShift, + nscoord aUserSupScriptShift, + nscoord aScriptSpace) { - nsresult rv = NS_OK; - // the caller better be a mathml frame - nsIMathMLFrame* mathMLFrame = nsnull; - rv = aFrame->QueryInterface (NS_GET_IID(nsIMathMLFrame), - (void**)&mathMLFrame); - if (NS_FAILED(rv) || !mathMLFrame) return rv; + nsIMathMLFrame* mathMLFrame; + aFrame->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame); + if (!mathMLFrame) return NS_ERROR_INVALID_ARG; // force the scriptSpace to be atleast 1 pixel float p2t; aPresContext->GetScaledPixelsToTwips(&p2t); - aScriptSpace = PR_MAX(NSIntPixelsToTwips(1, p2t), aScriptSpace); + nscoord onePixel = NSIntPixelsToTwips(1, p2t); + aScriptSpace = PR_MAX(onePixel, aScriptSpace); //////////////////////////////////// // Get the children's desired sizes - PRInt32 count = 0; nsHTMLReflowMetrics baseSize (nsnull); nsHTMLReflowMetrics subScriptSize (nsnull); nsHTMLReflowMetrics supScriptSize (nsnull); + nsBoundingMetrics bmBase, bmSubScript, bmSupScript; nsIFrame* baseFrame = nsnull; nsIFrame* subScriptFrame = nsnull; nsIFrame* supScriptFrame = nsnull; - // parameter v, Rule 18a, Appendix G of the TeXbook - nscoord minSubScriptShift = 0; - // parameter u in Rule 18a, Appendix G of the TeXbook - nscoord minSupScriptShift = 0; - - nsBoundingMetrics bmBase, bmSubScript, bmSupScript; - - nsIFrame* childFrame = nsnull; - aFrame->FirstChild (aPresContext, nsnull, &childFrame); - while (childFrame) { - if (0 == count) { - // base - baseFrame = childFrame; - GetReflowAndBoundingMetricsFor(baseFrame, baseSize, bmBase); - } - else if (1 == count) { - // subscript - subScriptFrame = childFrame; - GetReflowAndBoundingMetricsFor(subScriptFrame, subScriptSize, bmSubScript); - // get the subdrop from the subscript font - nscoord aSubDrop; - GetSubDropFromChild (aPresContext, subScriptFrame, aSubDrop); - // parameter v, Rule 18a, App. G, TeXbook - minSubScriptShift = bmBase.descent + aSubDrop; - } - else if (2 == count) { - // superscript - supScriptFrame = childFrame; - GetReflowAndBoundingMetricsFor(supScriptFrame, supScriptSize, bmSupScript); - // get the supdrop from the supscript font - nscoord aSupDrop; - GetSupDropFromChild (aPresContext, supScriptFrame, aSupDrop); - // parameter u, Rule 18a, App. G, TeXbook - minSupScriptShift = bmBase.ascent - aSupDrop; - } - count++; - childFrame->GetNextSibling(&childFrame); - } - if (3 != count) { + aFrame->FirstChild(aPresContext, nsnull, &baseFrame); + if (baseFrame) + baseFrame->GetNextSibling(&subScriptFrame); + if (subScriptFrame) + subScriptFrame->GetNextSibling(&supScriptFrame); + if (!baseFrame || !subScriptFrame || !supScriptFrame || HasNextSibling(supScriptFrame)) { // report an error, encourage people to get their markups in order NS_WARNING("invalid markup"); return NS_STATIC_CAST(nsMathMLContainerFrame*, @@ -187,6 +177,21 @@ nsMathMLmsubsupFrame::PlaceSubSupScript (nsIPresContext* aPresContext, aRenderingContext, aDesiredSize); } + GetReflowAndBoundingMetricsFor(baseFrame, baseSize, bmBase); + GetReflowAndBoundingMetricsFor(subScriptFrame, subScriptSize, bmSubScript); + GetReflowAndBoundingMetricsFor(supScriptFrame, supScriptSize, bmSupScript); + + // get the subdrop from the subscript font + nscoord subDrop; + GetSubDropFromChild(aPresContext, subScriptFrame, subDrop); + // parameter v, Rule 18a, App. G, TeXbook + nscoord minSubScriptShift = bmBase.descent + subDrop; + + // get the supdrop from the supscript font + nscoord supDrop; + GetSupDropFromChild(aPresContext, supScriptFrame, supDrop); + // parameter u, Rule 18a, App. G, TeXbook + nscoord minSupScriptShift = bmBase.ascent - supDrop; ////////////////// // Place Children @@ -203,9 +208,6 @@ nsMathMLmsubsupFrame::PlaceSubSupScript (nsIPresContext* aPresContext, // subScriptShift1 = subscriptshift attribute * x-height nscoord subScriptShift1, subScriptShift2; -// const nsStyleFont* aFont = -// (const nsStyleFont*) mStyleContext->GetStyleData (eStyleStruct_Font); - const nsStyleFont* font; baseFrame->GetStyleData(eStyleStruct_Font, (const nsStyleStruct *&)font); aRenderingContext.SetFont(font->mFont); diff --git a/layout/mathml/base/src/nsMathMLmsubsupFrame.h b/layout/mathml/base/src/nsMathMLmsubsupFrame.h index 3bb24b97e921..9c45004b58b5 100644 --- a/layout/mathml/base/src/nsMathMLmsubsupFrame.h +++ b/layout/mathml/base/src/nsMathMLmsubsupFrame.h @@ -35,6 +35,9 @@ class nsMathMLmsubsupFrame : public nsMathMLContainerFrame { public: friend nsresult NS_NewMathMLmsubsupFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame); + NS_IMETHOD + TransmitAutomaticData(nsIPresContext* aPresContext); + NS_IMETHOD Place(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, @@ -51,30 +54,6 @@ public: nscoord aUserSupScriptShift = 0, nscoord aScriptSpace = NSFloatPointsToTwips(0.5f)); - NS_IMETHOD - TransmitAutomaticData(nsIPresContext* aPresContext) - { -#if defined(NS_DEBUG) && defined(SHOW_BOUNDING_BOX) - mPresentationData.flags |= NS_MATHML_SHOW_BOUNDING_METRICS; -#endif - - // check whether or not this is an embellished operator - EmbellishOperator(); - // 1. The REC says: - // The element increments scriptlevel by 1, and sets displaystyle to - // "false", within subscript and superscript, but leaves both attributes - // unchanged within base. - // 2. The TeXbook (Ch 17. p.141) says the superscript inherits the compression - // while the subscript is compressed - UpdatePresentationDataFromChildAt(aPresContext, 1, -1, 1, - ~NS_MATHML_DISPLAYSTYLE, - NS_MATHML_DISPLAYSTYLE); - UpdatePresentationDataFromChildAt(aPresContext, 1, 1, 0, - NS_MATHML_COMPRESSED, - NS_MATHML_COMPRESSED); - return NS_OK; - } - protected: nsMathMLmsubsupFrame(); virtual ~nsMathMLmsubsupFrame(); diff --git a/layout/mathml/base/src/nsMathMLmsupFrame.cpp b/layout/mathml/base/src/nsMathMLmsupFrame.cpp index 3a92ddf5d33e..2673c1ffe84e 100644 --- a/layout/mathml/base/src/nsMathMLmsupFrame.cpp +++ b/layout/mathml/base/src/nsMathMLmsupFrame.cpp @@ -67,10 +67,31 @@ nsMathMLmsupFrame::~nsMathMLmsupFrame() } NS_IMETHODIMP -nsMathMLmsupFrame::Place (nsIPresContext* aPresContext, - nsIRenderingContext& aRenderingContext, - PRBool aPlaceOrigin, - nsHTMLReflowMetrics& aDesiredSize) +nsMathMLmsupFrame::TransmitAutomaticData(nsIPresContext* aPresContext) +{ + // if our base is an embellished operator, its flags bubble to us + nsIFrame* baseFrame = mFrames.FirstChild(); + GetEmbellishDataFrom(baseFrame, mEmbellishData); + if (NS_MATHML_IS_EMBELLISH_OPERATOR(mEmbellishData.flags)) + mEmbellishData.nextFrame = baseFrame; + + // 1. The REC says: + // The element increments scriptlevel by 1, and sets displaystyle to + // "false", within superscript, but leaves both attributes unchanged within base. + // 2. The TeXbook (Ch 17. p.141) says the superscript *inherits* the compression, + // so we don't set the compression flag. Our parent will propagate its own. + UpdatePresentationDataFromChildAt(aPresContext, 1, -1, 1, + ~NS_MATHML_DISPLAYSTYLE, + NS_MATHML_DISPLAYSTYLE); + + return NS_OK; +} + +NS_IMETHODIMP +nsMathMLmsupFrame::Place(nsIPresContext* aPresContext, + nsIRenderingContext& aRenderingContext, + PRBool aPlaceOrigin, + nsHTMLReflowMetrics& aDesiredSize) { // extra spacing between base and sup/subscript nscoord scriptSpace = NSFloatPointsToTwips(0.5f); // 0.5pt as in plain TeX @@ -86,13 +107,13 @@ nsMathMLmsupFrame::Place (nsIPresContext* aPresContext, } } - return nsMathMLmsupFrame::PlaceSuperScript (aPresContext, - aRenderingContext, - aPlaceOrigin, - aDesiredSize, - this, - supScriptShift, - scriptSpace); + return nsMathMLmsupFrame::PlaceSuperScript(aPresContext, + aRenderingContext, + aPlaceOrigin, + aDesiredSize, + this, + supScriptShift, + scriptSpace); } // exported routine that both mover and msup share. @@ -106,13 +127,10 @@ nsMathMLmsupFrame::PlaceSuperScript(nsIPresContext* aPresContext, nscoord aUserSupScriptShift, nscoord aScriptSpace) { - nsresult rv = NS_OK; - // the caller better be a mathml frame - nsIMathMLFrame* mathMLFrame = nsnull; - rv = aFrame->QueryInterface (NS_GET_IID(nsIMathMLFrame), - (void**)&mathMLFrame); - if (NS_FAILED(rv) || !mathMLFrame) return rv; + nsIMathMLFrame* mathMLFrame; + aFrame->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame); + if (!mathMLFrame) return NS_ERROR_INVALID_ARG; // force the scriptSpace to be at least 1 pixel float p2t; @@ -123,38 +141,15 @@ nsMathMLmsupFrame::PlaceSuperScript(nsIPresContext* aPresContext, //////////////////////////////////// // Get the children's desired sizes - PRInt32 count = 0; nsHTMLReflowMetrics baseSize (nsnull); nsHTMLReflowMetrics supScriptSize (nsnull); + nsBoundingMetrics bmBase, bmSupScript; nsIFrame* baseFrame = nsnull; nsIFrame* supScriptFrame = nsnull; - // parameter u in Rule 18a, Appendix G of the TeXbook - nscoord minSupScriptShift = 0; - - nsBoundingMetrics bmBase, bmSupScript; - - nsIFrame* childFrame = nsnull; - aFrame->FirstChild(aPresContext, nsnull, &childFrame); - while (childFrame) { - if (0 == count) { - // base - baseFrame = childFrame; - GetReflowAndBoundingMetricsFor(baseFrame, baseSize, bmBase); - } - else if (1 == count) { - // superscript - supScriptFrame = childFrame; - GetReflowAndBoundingMetricsFor(supScriptFrame, supScriptSize, bmSupScript); - // get the supdrop from the supscript font - nscoord supDrop; - GetSupDropFromChild (aPresContext, supScriptFrame, supDrop); - // parameter u, Rule 18a, App. G, TeXbook - minSupScriptShift = bmBase.ascent - supDrop; - } - count++; - childFrame->GetNextSibling(&childFrame); - } - if (2 != count) { + aFrame->FirstChild(aPresContext, nsnull, &baseFrame); + if (baseFrame) + baseFrame->GetNextSibling(&supScriptFrame); + if (!baseFrame || !supScriptFrame || HasNextSibling(supScriptFrame)) { // report an error, encourage people to get their markups in order NS_WARNING("invalid markup"); return NS_STATIC_CAST(nsMathMLContainerFrame*, @@ -162,6 +157,14 @@ nsMathMLmsupFrame::PlaceSuperScript(nsIPresContext* aPresContext, aRenderingContext, aDesiredSize); } + GetReflowAndBoundingMetricsFor(baseFrame, baseSize, bmBase); + GetReflowAndBoundingMetricsFor(supScriptFrame, supScriptSize, bmSupScript); + + // get the supdrop from the supscript font + nscoord supDrop; + GetSupDropFromChild(aPresContext, supScriptFrame, supDrop); + // parameter u, Rule 18a, App. G, TeXbook + nscoord minSupScriptShift = bmBase.ascent - supDrop; ////////////////// // Place Children @@ -171,9 +174,6 @@ nsMathMLmsupFrame::PlaceSuperScript(nsIPresContext* aPresContext, nscoord xHeight = 0; nsCOMPtr fm; -// const nsStyleFont* aFont = -// (const nsStyleFont*) aStyleContext->GetStyleData (eStyleStruct_Font); - const nsStyleFont *font; baseFrame->GetStyleData(eStyleStruct_Font, (const nsStyleStruct *&)font); diff --git a/layout/mathml/base/src/nsMathMLmsupFrame.h b/layout/mathml/base/src/nsMathMLmsupFrame.h index 1614023ee255..6bbdfd218a45 100644 --- a/layout/mathml/base/src/nsMathMLmsupFrame.h +++ b/layout/mathml/base/src/nsMathMLmsupFrame.h @@ -35,6 +35,9 @@ class nsMathMLmsupFrame : public nsMathMLContainerFrame { public: friend nsresult NS_NewMathMLmsupFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame); + NS_IMETHOD + TransmitAutomaticData(nsIPresContext* aPresContext); + NS_IMETHOD Place(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, @@ -50,26 +53,6 @@ public: nscoord aUserSupScriptShift = 0, nscoord aScriptSpace = NSFloatPointsToTwips(0.5f)); - NS_IMETHOD - TransmitAutomaticData(nsIPresContext* aPresContext) - { -#if defined(NS_DEBUG) && defined(SHOW_BOUNDING_BOX) - mPresentationData.flags |= NS_MATHML_SHOW_BOUNDING_METRICS; -#endif - - // check whether or not this is an embellished operator - EmbellishOperator(); - // 1. The REC says: - // The element increments scriptlevel by 1, and sets displaystyle to - // "false", within superscript, but leaves both attributes unchanged within base. - // 2. The TeXbook (Ch 17. p.141) says the superscript *inherits* the compression, - // so we don't set the compression flag. Our parent will propagate its own. - UpdatePresentationDataFromChildAt(aPresContext, 1, -1, 1, - ~NS_MATHML_DISPLAYSTYLE, - NS_MATHML_DISPLAYSTYLE); - return NS_OK; - } - protected: nsMathMLmsupFrame(); virtual ~nsMathMLmsupFrame(); diff --git a/layout/mathml/base/src/nsMathMLmtableFrame.cpp b/layout/mathml/base/src/nsMathMLmtableFrame.cpp index 2bb7812dbd17..b7b9d731fa3f 100644 --- a/layout/mathml/base/src/nsMathMLmtableFrame.cpp +++ b/layout/mathml/base/src/nsMathMLmtableFrame.cpp @@ -422,12 +422,7 @@ nsMathMLmtableOuterFrame::Init(nsIPresContext* aPresContext, nsIStyleContext* aContext, nsIFrame* aPrevInFlow) { - nsresult rv = nsTableOuterFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow); - - // now, inherit the scriptlevel and displaystyle from our parent - InheritAutomaticData(aPresContext, aParent); - - return rv; + return nsTableOuterFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow); } nsIFrame* @@ -695,15 +690,11 @@ nsMathMLmtdInnerFrame::Init(nsIPresContext* aPresContext, nsIStyleContext* aContext, nsIFrame* aPrevInFlow) { - nsresult rv; - rv = nsBlockFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow); + nsresult rv = nsBlockFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow); // record that children that are ignorable whitespace should be excluded mState |= NS_FRAME_EXCLUDE_IGNORABLE_WHITESPACE; - // now, inherit the scriptlevel and displaystyle from our parent - InheritAutomaticData(aPresContext, aParent); - return rv; } diff --git a/layout/mathml/base/src/nsMathMLmtextFrame.cpp b/layout/mathml/base/src/nsMathMLmtextFrame.cpp index af8db7e8dae1..7ec5645004aa 100644 --- a/layout/mathml/base/src/nsMathMLmtextFrame.cpp +++ b/layout/mathml/base/src/nsMathMLmtextFrame.cpp @@ -64,18 +64,6 @@ nsMathMLmtextFrame::~nsMathMLmtextFrame() { } -NS_IMETHODIMP -nsMathMLmtextFrame::Init(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIFrame* aParent, - nsIStyleContext* aContext, - nsIFrame* aPrevInFlow) -{ - nsresult rv = NS_OK; - rv = nsMathMLContainerFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow); - return rv; -} - NS_IMETHODIMP nsMathMLmtextFrame::Reflow(nsIPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, diff --git a/layout/mathml/base/src/nsMathMLmtextFrame.h b/layout/mathml/base/src/nsMathMLmtextFrame.h index 85ba221e6003..72335be3371b 100644 --- a/layout/mathml/base/src/nsMathMLmtextFrame.h +++ b/layout/mathml/base/src/nsMathMLmtextFrame.h @@ -32,13 +32,6 @@ class nsMathMLmtextFrame : public nsMathMLContainerFrame { public: friend nsresult NS_NewMathMLmtextFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame); - - NS_IMETHOD - Init(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIFrame* aParent, - nsIStyleContext* aContext, - nsIFrame* aPrevInFlow); NS_IMETHOD Reflow(nsIPresContext* aPresContext, diff --git a/layout/mathml/base/src/nsMathMLmunderFrame.cpp b/layout/mathml/base/src/nsMathMLmunderFrame.cpp index a0a59f71a602..ff84ef5df98f 100644 --- a/layout/mathml/base/src/nsMathMLmunderFrame.cpp +++ b/layout/mathml/base/src/nsMathMLmunderFrame.cpp @@ -69,6 +69,25 @@ nsMathMLmunderFrame::~nsMathMLmunderFrame() { } +NS_IMETHODIMP +nsMathMLmunderFrame::AttributeChanged(nsIPresContext* aPresContext, + nsIContent* aContent, + PRInt32 aNameSpaceID, + nsIAtom* aAttribute, + PRInt32 aModType, + PRInt32 aHint) +{ + if (nsMathMLAtoms::accentunder_ == aAttribute) { + // When we have automatic data to update within ourselves, we ask our + // parent to re-layout its children + return ReLayoutChildren(aPresContext, mParent); + } + + return nsMathMLContainerFrame:: + AttributeChanged(aPresContext, aContent, aNameSpaceID, + aAttribute, aModType, aHint); +} + NS_IMETHODIMP nsMathMLmunderFrame::UpdatePresentationData(nsIPresContext* aPresContext, PRInt32 aScriptLevelIncrement, @@ -78,12 +97,12 @@ nsMathMLmunderFrame::UpdatePresentationData(nsIPresContext* aPresContext, 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) && + if ( NS_MATHML_EMBELLISH_IS_MOVABLELIMITS(mEmbellishData.flags) && !NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags)) { - mEmbellishData.flags &= ~NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY; + mPresentationData.flags &= ~NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY; } else { - mEmbellishData.flags |= NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY; + mPresentationData.flags |= NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY; } return NS_OK; } @@ -124,24 +143,29 @@ nsMathMLmunderFrame::UpdatePresentationDataFromChildAt(nsIPresContext* aPresCont } return NS_OK; - // XXX For #2, if the inner changes, is has to trigger - // XXX a re-computation of all flags that depend on its state - // XXX in the entire embellished hierarchy + // For #2, the base class will trigger a re-build of all automatic data + // in the embellished hierarchy when an accent attribute is changed +} + +NS_IMETHODIMP +nsMathMLmunderFrame::InheritAutomaticData(nsIPresContext* aPresContext, + nsIFrame* aParent) +{ + // let the base class get the default from our parent + nsMathMLContainerFrame::InheritAutomaticData(aPresContext, aParent); + + mPresentationData.flags |= NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY; + + return NS_OK; } NS_IMETHODIMP nsMathMLmunderFrame::TransmitAutomaticData(nsIPresContext* aPresContext) { -#if defined(NS_DEBUG) && defined(SHOW_BOUNDING_BOX) - mPresentationData.flags |= NS_MATHML_SHOW_BOUNDING_METRICS; -#endif + // At this stage, all our children are in sync and we can fully + // resolve our own mEmbellishData struct + //--------------------------------------------------------------------- - mEmbellishData.flags = NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY; - - // check whether or not this is an embellished operator - EmbellishOperator(); - - // set our accentunder flag /* The REC says: The default value of accentunder is false, unless underscript is an element or an embellished operator. If underscript is @@ -158,99 +182,61 @@ XXX The winner is the outermost setting in conflicting settings like these: */ - PRInt32 count = 0; - nsIFrame* baseFrame = nsnull; nsIFrame* underscriptFrame = nsnull; - nsIFrame* childFrame = mFrames.FirstChild(); - while (childFrame) { - if (0 == count) baseFrame = childFrame; - if (1 == count) { underscriptFrame = childFrame; break; } - count++; - childFrame->GetNextSibling(&childFrame); - } + nsIFrame* baseFrame = mFrames.FirstChild(); + if (baseFrame) + baseFrame->GetNextSibling(&underscriptFrame); + if (!baseFrame || !underscriptFrame) + return NS_OK; // a visual error indicator will be reported later during layout + + // if our base is an embellished operator, let its state bubble to us (in particular, + // this is where we get the flag for NS_MATHML_EMBELLISH_MOVABLELIMITS). Our flags + // are reset to the default values of false if the base frame isn't embellished. + GetEmbellishDataFrom(baseFrame, mEmbellishData); + if (NS_MATHML_IS_EMBELLISH_OPERATOR(mEmbellishData.flags)) + mEmbellishData.nextFrame = baseFrame; - nsIMathMLFrame* underscriptMathMLFrame = nsnull; - nsIMathMLFrame* mathMLFrame = nsnull; - nsEmbellishData embellishData; nsAutoString value; - mPresentationData.flags &= ~NS_MATHML_MOVABLELIMITS; // default is false - mPresentationData.flags &= ~NS_MATHML_ACCENTUNDER; // default of accentunder is false + // The default value of accentunder is false, unless the underscript is embellished + // and its core is an accent + nsEmbellishData embellishData; + GetEmbellishDataFrom(underscriptFrame, embellishData); + if (NS_MATHML_EMBELLISH_IS_ACCENT(embellishData.flags)) + mEmbellishData.flags |= NS_MATHML_EMBELLISH_ACCENTUNDER; + else + mEmbellishData.flags &= ~NS_MATHML_EMBELLISH_ACCENTUNDER; - // see if the baseFrame has movablelimits="true" or if it is an - // embellished operator whose movablelimits attribute is set to true - if (baseFrame && NS_MATHML_IS_EMBELLISH_OPERATOR(mEmbellishData.flags)) { - nsCOMPtr baseContent; - baseFrame->GetContent(getter_AddRefs(baseContent)); - if (NS_CONTENT_ATTR_HAS_VALUE == baseContent->GetAttr(kNameSpaceID_None, - nsMathMLAtoms::movablelimits_, value)) { - if (value.Equals(NS_LITERAL_STRING("true"))) { - mPresentationData.flags |= NS_MATHML_MOVABLELIMITS; - } - } - else { // no attribute, get the value from the core - mEmbellishData.coreFrame->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame); - if (mathMLFrame) { - mathMLFrame->GetEmbellishData(embellishData); - if (NS_MATHML_EMBELLISH_IS_MOVABLELIMITS(embellishData.flags)) { - mPresentationData.flags |= NS_MATHML_MOVABLELIMITS; - } - } - } + // if we have an accentunder attribute, it overrides what the underscript said + if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttr(kNameSpaceID_None, + nsMathMLAtoms::accentunder_, value)) { + if (value.Equals(NS_LITERAL_STRING("true"))) + mEmbellishData.flags |= NS_MATHML_EMBELLISH_ACCENTUNDER; + else if (value.Equals(NS_LITERAL_STRING("false"))) + mEmbellishData.flags &= ~NS_MATHML_EMBELLISH_ACCENTUNDER; } - // see if the underscriptFrame is or an embellished operator - if (underscriptFrame) { - underscriptFrame->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&underscriptMathMLFrame); - if (underscriptMathMLFrame) { - underscriptMathMLFrame->GetEmbellishData(embellishData); - // core of the underscriptFrame - if (NS_MATHML_IS_EMBELLISH_OPERATOR(embellishData.flags) && embellishData.coreFrame) { - embellishData.coreFrame->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame); - if (mathMLFrame) { - mathMLFrame->GetEmbellishData(embellishData); - // if we have the accentunder attribute, tell the core to behave as - // requested (otherwise leave the core with its default behavior) - if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttr(kNameSpaceID_None, - nsMathMLAtoms::accentunder_, value)) - { - if (value.Equals(NS_LITERAL_STRING("true"))) embellishData.flags |= NS_MATHML_EMBELLISH_ACCENT; - else if (value.Equals(NS_LITERAL_STRING("false"))) embellishData.flags &= ~NS_MATHML_EMBELLISH_ACCENT; - mathMLFrame->SetEmbellishData(embellishData); - } + // disable the stretch-all flag if we are going to act like a superscript + if ( NS_MATHML_EMBELLISH_IS_MOVABLELIMITS(mEmbellishData.flags) && + !NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags)) + mPresentationData.flags &= ~NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY; - // sync the presentation data: record whether we have an accentunder - if (NS_MATHML_EMBELLISH_IS_ACCENT(embellishData.flags)) - mPresentationData.flags |= NS_MATHML_ACCENTUNDER; - } - } - } - } + // Now transmit any change that we want to our children so that they + // can update their mPresentationData structs + //--------------------------------------------------------------------- /* The REC says: Within underscript, always sets displaystyle to "false", but increments scriptlevel by 1 only when accentunder is "false". - */ - /* + The TeXBook treats 'under' like a subscript, so p.141 or Rule 13a say it should be compressed */ - if (underscriptMathMLFrame) { - PRInt32 increment; - increment = NS_MATHML_IS_ACCENTUNDER(mPresentationData.flags)? 0 : 1; - underscriptMathMLFrame->UpdatePresentationData(aPresContext, increment, - ~NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED, - NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED); - underscriptMathMLFrame->UpdatePresentationDataFromChildAt(aPresContext, 0, -1, increment, - ~NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED, - NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED); - } - - // 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; - } + PRInt32 increment = NS_MATHML_EMBELLISH_IS_ACCENTUNDER(mEmbellishData.flags) + ? 0 : 1; + PropagatePresentationDataFor(aPresContext, underscriptFrame, increment, + ~NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED, + NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED); return NS_OK; } @@ -265,7 +251,7 @@ The REC says: for limits on symbols such as ∑. i.e.,: - if ( NS_MATHML_IS_MOVABLELIMITS(mPresentationData.flags) && + if ( NS_MATHML_EMBELLISH_IS_MOVABLELIMITS(mEmbellishData.flags) && !NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags)) { // place like subscript } @@ -280,9 +266,7 @@ nsMathMLmunderFrame::Place(nsIPresContext* aPresContext, PRBool aPlaceOrigin, nsHTMLReflowMetrics& aDesiredSize) { - nsresult rv = NS_OK; - - if ( NS_MATHML_IS_MOVABLELIMITS(mPresentationData.flags) && + if ( NS_MATHML_EMBELLISH_IS_MOVABLELIMITS(mEmbellishData.flags) && !NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags)) { // place like subscript return nsMathMLmsubFrame::PlaceSubScript(aPresContext, @@ -295,33 +279,20 @@ nsMathMLmunderFrame::Place(nsIPresContext* aPresContext, //////////////////////////////////// // Get the children's desired sizes - PRInt32 count = 0; nsBoundingMetrics bmBase, bmUnder; nsHTMLReflowMetrics baseSize (nsnull); nsHTMLReflowMetrics underSize (nsnull); - nsIFrame* baseFrame = nsnull; nsIFrame* underFrame = nsnull; - - nsIFrame* childFrame = mFrames.FirstChild(); - while (childFrame) { - if (0 == count) { - // base - baseFrame = childFrame; - GetReflowAndBoundingMetricsFor(baseFrame, baseSize, bmBase); - } - else if (1 == count) { - // under - underFrame = childFrame; - GetReflowAndBoundingMetricsFor(underFrame, underSize, bmUnder); - } - count++; - childFrame->GetNextSibling(&childFrame); - } - if (2 != count) { + nsIFrame* baseFrame = mFrames.FirstChild(); + if (baseFrame) + baseFrame->GetNextSibling(&underFrame); + if (!baseFrame || !underFrame || HasNextSibling(underFrame)) { // report an error, encourage people to get their markups in order NS_WARNING("invalid markup"); return ReflowError(aPresContext, aRenderingContext, aDesiredSize); } + GetReflowAndBoundingMetricsFor(baseFrame, baseSize, bmBase); + GetReflowAndBoundingMetricsFor(underFrame, underSize, bmUnder); //////////////////// // Place Children @@ -344,7 +315,7 @@ nsMathMLmunderFrame::Place(nsIPresContext* aPresContext, nscoord italicCorrection = 0; nscoord delta1 = 0; // gap between base and underscript nscoord delta2 = 0; // extra space beneath underscript - if (!NS_MATHML_IS_ACCENTUNDER(mPresentationData.flags)) { + if (!NS_MATHML_EMBELLISH_IS_ACCENTUNDER(mEmbellishData.flags)) { // Rule 13a, App. G, TeXbook GetItalicCorrection (bmBase, italicCorrection); nscoord bigOpSpacing2, bigOpSpacing4, bigOpSpacing5, dummy; diff --git a/layout/mathml/base/src/nsMathMLmunderFrame.h b/layout/mathml/base/src/nsMathMLmunderFrame.h index 2a5c60db8299..59c8afb77364 100644 --- a/layout/mathml/base/src/nsMathMLmunderFrame.h +++ b/layout/mathml/base/src/nsMathMLmunderFrame.h @@ -41,6 +41,10 @@ public: PRBool aPlaceOrigin, nsHTMLReflowMetrics& aDesiredSize); + NS_IMETHOD + InheritAutomaticData(nsIPresContext* aPresContext, + nsIFrame* aParent); + NS_IMETHOD TransmitAutomaticData(nsIPresContext* aPresContext); @@ -58,6 +62,14 @@ public: PRUint32 aFlagsValues, PRUint32 aFlagsToUpdate); + NS_IMETHOD + AttributeChanged(nsIPresContext* aPresContext, + nsIContent* aChild, + PRInt32 aNameSpaceID, + nsIAtom* aAttribute, + PRInt32 aModType, + PRInt32 aHint); + protected: nsMathMLmunderFrame(); virtual ~nsMathMLmunderFrame(); diff --git a/layout/mathml/base/src/nsMathMLmunderoverFrame.cpp b/layout/mathml/base/src/nsMathMLmunderoverFrame.cpp index 0c5d2cce1ee3..6aba45a9506a 100644 --- a/layout/mathml/base/src/nsMathMLmunderoverFrame.cpp +++ b/layout/mathml/base/src/nsMathMLmunderoverFrame.cpp @@ -69,6 +69,26 @@ nsMathMLmunderoverFrame::~nsMathMLmunderoverFrame() { } +NS_IMETHODIMP +nsMathMLmunderoverFrame::AttributeChanged(nsIPresContext* aPresContext, + nsIContent* aContent, + PRInt32 aNameSpaceID, + nsIAtom* aAttribute, + PRInt32 aModType, + PRInt32 aHint) +{ + if (nsMathMLAtoms::accent_ == aAttribute || + nsMathMLAtoms::accentunder_ == aAttribute) { + // When we have automatic data to update within ourselves, we ask our + // parent to re-layout its children + return ReLayoutChildren(aPresContext, mParent); + } + + return nsMathMLContainerFrame:: + AttributeChanged(aPresContext, aContent, aNameSpaceID, + aAttribute, aModType, aHint); +} + NS_IMETHODIMP nsMathMLmunderoverFrame::UpdatePresentationData(nsIPresContext* aPresContext, PRInt32 aScriptLevelIncrement, @@ -78,12 +98,12 @@ nsMathMLmunderoverFrame::UpdatePresentationData(nsIPresContext* aPresContext, 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) && + if ( NS_MATHML_EMBELLISH_IS_MOVABLELIMITS(mEmbellishData.flags) && !NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags)) { - mEmbellishData.flags &= ~NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY; + mPresentationData.flags &= ~NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY; } else { - mEmbellishData.flags |= NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY; + mPresentationData.flags |= NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY; } return NS_OK; } @@ -129,24 +149,29 @@ nsMathMLmunderoverFrame::UpdatePresentationDataFromChildAt(nsIPresContext* aPres } return NS_OK; - // XXX For #2, if the inner changes, is has to trigger - // XXX a re-computation of all flags that depend on its state - // XXX in the entire embellished hierarchy + // For #2, the base class will trigger a re-build of all automatic data + // in the embellished hierarchy when an accent attribute is changed +} + +NS_IMETHODIMP +nsMathMLmunderoverFrame::InheritAutomaticData(nsIPresContext* aPresContext, + nsIFrame* aParent) +{ + // let the base class get the default from our parent + nsMathMLContainerFrame::InheritAutomaticData(aPresContext, aParent); + + mPresentationData.flags |= NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY; + + return NS_OK; } NS_IMETHODIMP nsMathMLmunderoverFrame::TransmitAutomaticData(nsIPresContext* aPresContext) { -#if defined(NS_DEBUG) && defined(SHOW_BOUNDING_BOX) - mPresentationData.flags |= NS_MATHML_SHOW_BOUNDING_METRICS; -#endif + // At this stage, all our children are in sync and we can fully + // resolve our own mEmbellishData struct + //--------------------------------------------------------------------- - mEmbellishData.flags |= NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY; - - // check whether or not this is an embellished operator - EmbellishOperator(); - - // set our accent and accentunder flags /* The REC says: @@ -158,156 +183,98 @@ nsMathMLmunderoverFrame::TransmitAutomaticData(nsIPresContext* aPresContext) of accentunder depending on underscript. */ - // get our overscript and underscript frames - PRInt32 count = 0; - nsIFrame* baseFrame = nsnull; - nsIFrame* underscriptFrame = nsnull; nsIFrame* overscriptFrame = nsnull; - nsIFrame* childFrame = mFrames.FirstChild(); - while (childFrame) { - if (0 == count) baseFrame = childFrame; - if (1 == count) underscriptFrame = childFrame; - if (2 == count) { overscriptFrame = childFrame; break; } - count++; - childFrame->GetNextSibling(&childFrame); - } + nsIFrame* underscriptFrame = nsnull; + nsIFrame* baseFrame = mFrames.FirstChild(); + if (baseFrame) + baseFrame->GetNextSibling(&underscriptFrame); + if (underscriptFrame) + underscriptFrame->GetNextSibling(&overscriptFrame); + if (!baseFrame || !underscriptFrame || !overscriptFrame) + return NS_OK; // a visual error indicator will be reported later during layout + + // if our base is an embellished operator, let its state bubble to us (in particular, + // this is where we get the flag for NS_MATHML_EMBELLISH_MOVABLELIMITS). Our flags + // are reset to the default values of false if the base frame isn't embellished. + GetEmbellishDataFrom(baseFrame, mEmbellishData); + if (NS_MATHML_IS_EMBELLISH_OPERATOR(mEmbellishData.flags)) + mEmbellishData.nextFrame = baseFrame; - nsIMathMLFrame* underscriptMathMLFrame = nsnull; - nsIMathMLFrame* overscriptMathMLFrame = nsnull; - nsIMathMLFrame* mathMLFrame; - nsEmbellishData embellishData; nsAutoString value; - mPresentationData.flags &= ~NS_MATHML_MOVABLELIMITS; // default is false - mPresentationData.flags &= ~NS_MATHML_ACCENTUNDER; // default of accentunder is false - mPresentationData.flags &= ~NS_MATHML_ACCENTOVER; // default of accent is false + // The default value of accentunder is false, unless the underscript is embellished + // and its core is an accent + nsEmbellishData embellishData; + GetEmbellishDataFrom(underscriptFrame, embellishData); + if (NS_MATHML_EMBELLISH_IS_ACCENT(embellishData.flags)) + mEmbellishData.flags |= NS_MATHML_EMBELLISH_ACCENTUNDER; + else + mEmbellishData.flags &= ~NS_MATHML_EMBELLISH_ACCENTUNDER; - // see if the baseFrame has movablelimits="true" or if it is an - // embellished operator whose movablelimits attribute is set to true - if (baseFrame && NS_MATHML_IS_EMBELLISH_OPERATOR(mEmbellishData.flags)) { - nsCOMPtr baseContent; - baseFrame->GetContent(getter_AddRefs(baseContent)); - if (NS_CONTENT_ATTR_HAS_VALUE == baseContent->GetAttr(kNameSpaceID_None, - nsMathMLAtoms::movablelimits_, value)) { - if (value.Equals(NS_LITERAL_STRING("true"))) { - mPresentationData.flags |= NS_MATHML_MOVABLELIMITS; - } - } - else { // no attribute, get the value from the core - mEmbellishData.coreFrame->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame); - if (mathMLFrame) { - mathMLFrame->GetEmbellishData(embellishData); - if (NS_MATHML_EMBELLISH_IS_MOVABLELIMITS(embellishData.flags)) { - mPresentationData.flags |= NS_MATHML_MOVABLELIMITS; - } - } - } + // if we have an accentunder attribute, it overrides what the underscript said + if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttr(kNameSpaceID_None, + nsMathMLAtoms::accentunder_, value)) { + if (value.Equals(NS_LITERAL_STRING("true"))) + mEmbellishData.flags |= NS_MATHML_EMBELLISH_ACCENTUNDER; + else if (value.Equals(NS_LITERAL_STRING("false"))) + mEmbellishData.flags &= ~NS_MATHML_EMBELLISH_ACCENTUNDER; } - // see if the underscriptFrame is or an embellished operator - if (underscriptFrame) { - underscriptFrame->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&underscriptMathMLFrame); - if (underscriptMathMLFrame) { - underscriptMathMLFrame->GetEmbellishData(embellishData); - // core of the underscriptFrame - if (NS_MATHML_IS_EMBELLISH_OPERATOR(embellishData.flags) && embellishData.coreFrame) { - embellishData.coreFrame->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame); - if (mathMLFrame) { - mathMLFrame->GetEmbellishData(embellishData); - // if we have the accentunder attribute, tell the core to behave as - // requested (otherwise leave the core with its default behavior) - if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttr(kNameSpaceID_None, - nsMathMLAtoms::accentunder_, value)) - { - if (value.Equals(NS_LITERAL_STRING("true"))) embellishData.flags |= NS_MATHML_EMBELLISH_ACCENT; - else if (value.Equals(NS_LITERAL_STRING("false"))) embellishData.flags &= ~NS_MATHML_EMBELLISH_ACCENT; - mathMLFrame->SetEmbellishData(embellishData); - } + // The default value of accent is false, unless the overscript is embellished + // and its core is an accent + GetEmbellishDataFrom(overscriptFrame, embellishData); + if (NS_MATHML_EMBELLISH_IS_ACCENT(embellishData.flags)) + mEmbellishData.flags |= NS_MATHML_EMBELLISH_ACCENTOVER; + else + mEmbellishData.flags &= ~NS_MATHML_EMBELLISH_ACCENTOVER; - // sync the presentation data: record whether we have an accentunder - if (NS_MATHML_EMBELLISH_IS_ACCENT(embellishData.flags)) - mPresentationData.flags |= NS_MATHML_ACCENTUNDER; - } - } - } - } - - // see if the overscriptFrame is or an embellished operator - if (overscriptFrame) { - overscriptFrame->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&overscriptMathMLFrame); - if (overscriptMathMLFrame) { - overscriptMathMLFrame->GetEmbellishData(embellishData); - // core of the overscriptFrame - if (NS_MATHML_IS_EMBELLISH_OPERATOR(embellishData.flags) && embellishData.coreFrame) { - embellishData.coreFrame->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame); - if (mathMLFrame) { - mathMLFrame->GetEmbellishData(embellishData); - // if we have the accent attribute, tell the core to behave as - // requested (otherwise leave the core with its default behavior) - if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttr(kNameSpaceID_None, - nsMathMLAtoms::accent_, value)) - { - if (value.Equals(NS_LITERAL_STRING("true"))) embellishData.flags |= NS_MATHML_EMBELLISH_ACCENT; - else if (value.Equals(NS_LITERAL_STRING("false"))) embellishData.flags &= ~NS_MATHML_EMBELLISH_ACCENT; - mathMLFrame->SetEmbellishData(embellishData); - } - - // sync the presentation data: record whether we have an accent - if (NS_MATHML_EMBELLISH_IS_ACCENT(embellishData.flags)) - mPresentationData.flags |= NS_MATHML_ACCENTOVER; - } - } - } + // if we have an accent attribute, it overrides what the overscript said + if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttr(kNameSpaceID_None, + nsMathMLAtoms::accent_, value)) { + if (value.Equals(NS_LITERAL_STRING("true"))) + mEmbellishData.flags |= NS_MATHML_EMBELLISH_ACCENTOVER; + else if (value.Equals(NS_LITERAL_STRING("false"))) + mEmbellishData.flags &= ~NS_MATHML_EMBELLISH_ACCENTOVER; } - //The REC says: - /* - Within underscript, always sets displaystyle to "false", - but increments scriptlevel by 1 only when accentunder is "false". + // disable the stretch-all flag if we are going to act like a superscript + if ( NS_MATHML_EMBELLISH_IS_MOVABLELIMITS(mEmbellishData.flags) && + !NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags)) + mPresentationData.flags &= ~NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY; - Within overscript, always sets displaystyle to "false", - but increments scriptlevel by 1 only when accent is "false". - */ + // Now transmit any change that we want to our children so that they + // can update their mPresentationData structs + //--------------------------------------------------------------------- - /* + /* The REC says: + Within underscript, always sets displaystyle to "false", + but increments scriptlevel by 1 only when accentunder is "false". + + Within overscript, always sets displaystyle to "false", + but increments scriptlevel by 1 only when accent is "false". + The TeXBook treats 'over' like a superscript, so p.141 or Rule 13a say it shouldn't be compressed. However, The TeXBook says that math accents and \overline change uncramped styles to their cramped counterparts. */ - if (overscriptMathMLFrame) - { - PRInt32 increment = NS_MATHML_IS_ACCENTOVER(mPresentationData.flags) - ? 0 : 1; - PRUint32 compress = NS_MATHML_IS_ACCENTOVER(mPresentationData.flags) - ? NS_MATHML_COMPRESSED : 0; - overscriptMathMLFrame->UpdatePresentationData(aPresContext, increment, - ~NS_MATHML_DISPLAYSTYLE | compress, - NS_MATHML_DISPLAYSTYLE | compress); - overscriptMathMLFrame->UpdatePresentationDataFromChildAt(aPresContext, 0, -1, increment, - ~NS_MATHML_DISPLAYSTYLE | compress, - NS_MATHML_DISPLAYSTYLE | compress); - } + PRInt32 increment = NS_MATHML_EMBELLISH_IS_ACCENTOVER(mEmbellishData.flags) + ? 0 : 1; + PRUint32 compress = NS_MATHML_EMBELLISH_IS_ACCENTOVER(mEmbellishData.flags) + ? NS_MATHML_COMPRESSED : 0; + PropagatePresentationDataFor(aPresContext, overscriptFrame, increment, + ~NS_MATHML_DISPLAYSTYLE | compress, + NS_MATHML_DISPLAYSTYLE | compress); /* The TeXBook treats 'under' like a subscript, so p.141 or Rule 13a say it should be compressed */ - if (underscriptMathMLFrame) { - PRInt32 increment = NS_MATHML_IS_ACCENTUNDER(mPresentationData.flags)? 0 : 1; - underscriptMathMLFrame->UpdatePresentationData(aPresContext, increment, - ~NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED, - NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED); - underscriptMathMLFrame->UpdatePresentationDataFromChildAt(aPresContext, 0, -1, increment, - ~NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED, - NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED); - } - - // 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; - } + increment = NS_MATHML_EMBELLISH_IS_ACCENTUNDER(mEmbellishData.flags) + ? 0 : 1; + PropagatePresentationDataFor(aPresContext, underscriptFrame, increment, + ~NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED, + NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED); return NS_OK; } @@ -322,7 +289,7 @@ The REC says: used for limits on symbols such as ∑. i.e.,: - if ( NS_MATHML_IS_MOVABLELIMITS(mPresentationData.flags) && + if ( NS_MATHML_EMBELLISH_IS_MOVABLELIMITS(mEmbellishDataflags) && !NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags)) { // place like subscript-superscript pair } @@ -331,16 +298,13 @@ i.e.,: } */ - NS_IMETHODIMP nsMathMLmunderoverFrame::Place(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, PRBool aPlaceOrigin, nsHTMLReflowMetrics& aDesiredSize) { - nsresult rv = NS_OK; - - if ( NS_MATHML_IS_MOVABLELIMITS(mPresentationData.flags) && + if ( NS_MATHML_EMBELLISH_IS_MOVABLELIMITS(mEmbellishData.flags) && !NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags)) { // place like sub-superscript pair return nsMathMLmsubsupFrame::PlaceSubSupScript(aPresContext, @@ -353,40 +317,25 @@ nsMathMLmunderoverFrame::Place(nsIPresContext* aPresContext, //////////////////////////////////// // Get the children's desired sizes - PRInt32 count = 0; nsBoundingMetrics bmBase, bmUnder, bmOver; nsHTMLReflowMetrics baseSize (nsnull); nsHTMLReflowMetrics underSize (nsnull); nsHTMLReflowMetrics overSize (nsnull); - nsIFrame* baseFrame = nsnull; nsIFrame* overFrame = nsnull; nsIFrame* underFrame = nsnull; - - nsIFrame* childFrame = mFrames.FirstChild(); - while (childFrame) { - if (0 == count) { - // base - baseFrame = childFrame; - GetReflowAndBoundingMetricsFor(baseFrame, baseSize, bmBase); - } - else if (1 == count) { - // under - underFrame = childFrame; - GetReflowAndBoundingMetricsFor(underFrame, underSize, bmUnder); - } - else if (2 == count) { - // over - overFrame = childFrame; - GetReflowAndBoundingMetricsFor(overFrame, overSize, bmOver); - } - count++; - childFrame->GetNextSibling(&childFrame); - } - if (3 != count) { + nsIFrame* baseFrame = mFrames.FirstChild(); + if (baseFrame) + baseFrame->GetNextSibling(&underFrame); + if (underFrame) + underFrame->GetNextSibling(&overFrame); + if (!baseFrame || !underFrame || !overFrame || HasNextSibling(overFrame)) { // report an error, encourage people to get their markups in order NS_WARNING("invalid markup"); return ReflowError(aPresContext, aRenderingContext, aDesiredSize); } + GetReflowAndBoundingMetricsFor(baseFrame, baseSize, bmBase); + GetReflowAndBoundingMetricsFor(underFrame, underSize, bmUnder); + GetReflowAndBoundingMetricsFor(overFrame, overSize, bmOver); //////////////////// // Place Children @@ -410,7 +359,7 @@ nsMathMLmunderoverFrame::Place(nsIPresContext* aPresContext, nscoord underDelta1 = 0; // gap between base and underscript nscoord underDelta2 = 0; // extra space beneath underscript - if (!NS_MATHML_IS_ACCENTUNDER(mPresentationData.flags)) { + if (!NS_MATHML_EMBELLISH_IS_ACCENTUNDER(mEmbellishData.flags)) { // Rule 13a, App. G, TeXbook GetItalicCorrection (bmBase, italicCorrection); nscoord bigOpSpacing2, bigOpSpacing4, bigOpSpacing5, dummy; @@ -436,7 +385,7 @@ nsMathMLmunderoverFrame::Place(nsIPresContext* aPresContext, nscoord overDelta1 = 0; // gap between base and overscript nscoord overDelta2 = 0; // extra space above overscript - if (!NS_MATHML_IS_ACCENTOVER(mPresentationData.flags)) { + if (!NS_MATHML_EMBELLISH_IS_ACCENTOVER(mEmbellishData.flags)) { // Rule 13a, App. G, TeXbook GetItalicCorrection (bmBase, italicCorrection); nscoord bigOpSpacing1, bigOpSpacing3, bigOpSpacing5, dummy; diff --git a/layout/mathml/base/src/nsMathMLmunderoverFrame.h b/layout/mathml/base/src/nsMathMLmunderoverFrame.h index b9e76d2ae70b..b42dd5882877 100644 --- a/layout/mathml/base/src/nsMathMLmunderoverFrame.h +++ b/layout/mathml/base/src/nsMathMLmunderoverFrame.h @@ -41,6 +41,10 @@ public: PRBool aPlaceOrigin, nsHTMLReflowMetrics& aDesiredSize); + NS_IMETHOD + InheritAutomaticData(nsIPresContext* aPresContext, + nsIFrame* aParent); + NS_IMETHOD TransmitAutomaticData(nsIPresContext* aPresContext); @@ -58,6 +62,14 @@ public: PRUint32 aFlagsValues, PRUint32 aFlagsToUpdate); + NS_IMETHOD + AttributeChanged(nsIPresContext* aPresContext, + nsIContent* aChild, + PRInt32 aNameSpaceID, + nsIAtom* aAttribute, + PRInt32 aModType, + PRInt32 aHint); + protected: nsMathMLmunderoverFrame(); virtual ~nsMathMLmunderoverFrame();