Bug 442637 - MathML changes to support ssty setting. r=fredw
authorJames Kitchener <jkitch.bug@gmail.com>
Wed, 15 Jan 2014 09:49:00 -0500
changeset 163589 a0b1c4cf207a6ee001773c6d44120f467a394503
parent 163588 12ec0bd6b782bbea922a4735a0f43c4f997e65b8
child 163590 10b9624cde2b998f9083dfd736d1cf1968b21154
push id26002
push userryanvm@gmail.com
push dateWed, 15 Jan 2014 19:34:12 +0000
treeherdermozilla-central@09a8ed7cbb0b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfredw
bugs442637
milestone29.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 442637 - MathML changes to support ssty setting. r=fredw
layout/mathml/moz.build
layout/mathml/nsIMathMLFrame.h
layout/mathml/nsMathMLContainerFrame.cpp
layout/mathml/nsMathMLContainerFrame.h
layout/mathml/nsMathMLFrame.h
layout/mathml/nsMathMLmfracFrame.cpp
layout/mathml/nsMathMLmfracFrame.h
layout/mathml/nsMathMLmmultiscriptsFrame.cpp
layout/mathml/nsMathMLmmultiscriptsFrame.h
layout/mathml/nsMathMLmrootFrame.cpp
layout/mathml/nsMathMLmrootFrame.h
layout/mathml/nsMathMLmunderoverFrame.cpp
layout/mathml/nsMathMLmunderoverFrame.h
--- a/layout/mathml/moz.build
+++ b/layout/mathml/moz.build
@@ -24,16 +24,21 @@ UNIFIED_SOURCES += [
     'nsMathMLmtableFrame.cpp',
     'nsMathMLmunderoverFrame.cpp',
     'nsMathMLOperators.cpp',
     'nsMathMLSelectedFrame.cpp',
     'nsMathMLsemanticsFrame.cpp',
     'nsMathMLTokenFrame.cpp',
 ]
 
+EXPORTS += [
+    'nsIMathMLFrame.h',
+    'nsMathMLOperators.h'
+]
+
 FAIL_ON_WARNINGS = True
 
 FINAL_LIBRARY = 'gklayout'
 LOCAL_INCLUDES += [
     '../base',
     '../generic',
     '../style',
     '../tables',
--- a/layout/mathml/nsIMathMLFrame.h
+++ b/layout/mathml/nsIMathMLFrame.h
@@ -2,16 +2,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 //#define SHOW_BOUNDING_BOX 1
 #ifndef nsIMathMLFrame_h___
 #define nsIMathMLFrame_h___
 
 #include "nsQueryFrame.h"
+#include "nsMathMLOperators.h"
 
 struct nsPresentationData;
 struct nsEmbellishData;
 struct nsHTMLReflowMetrics;
 class nsRenderingContext;
 class nsIFrame;
 
 // For MathML, this 'type' will be used to determine the spacing between frames
@@ -187,16 +188,23 @@ public:
   *        The flags that are relevant to this call. See UpdatePresentationData()
   *        for more details about this parameter.
   */
   NS_IMETHOD
   UpdatePresentationDataFromChildAt(int32_t         aFirstIndex,
                                     int32_t         aLastIndex,
                                     uint32_t        aFlagsValues,
                                     uint32_t        aWhichFlags) = 0;
+
+  // If aFrame is a child frame, returns the script increment which this frame
+  // imposes on the specified frame, ignoring any artificial adjustments to
+  // scriptlevel.
+  // Returns 0 if the specified frame isn't a child frame.
+  virtual uint8_t
+  ScriptIncrement(nsIFrame* aFrame) = 0;
 };
 
 // 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 {
--- a/layout/mathml/nsMathMLContainerFrame.cpp
+++ b/layout/mathml/nsMathMLContainerFrame.cpp
@@ -1525,16 +1525,31 @@ nsMathMLContainerFrame::TransmitAutomati
   if (childFrame || embellishedOpFound) {
     // The element is not space-like
     mPresentationData.flags &= ~NS_MATHML_SPACE_LIKE;
   }
 
   return NS_OK;
 }
 
+/*static*/ void
+nsMathMLContainerFrame::PropagateFrameFlagFor(nsIFrame* aFrame,
+                                              uint64_t  aFlags)
+{
+  if (!aFrame || !aFlags)
+    return;
+
+  aFrame->AddStateBits(aFlags);
+  nsIFrame* childFrame = aFrame->GetFirstPrincipalChild();
+  while (childFrame) {
+    PropagateFrameFlagFor(childFrame, aFlags);
+    childFrame = childFrame->GetNextSibling();
+  }
+}
+
 nsresult
 nsMathMLContainerFrame::ReportErrorToConsole(const char*       errorMsgId,
                                              const char16_t** aParams,
                                              uint32_t          aParamCount)
 {
   return nsContentUtils::ReportToConsole(nsIScriptError::errorFlag,
                                          NS_LITERAL_CSTRING("MathML"), mContent->OwnerDoc(),
                                          nsContentUtils::eMATHML_PROPERTIES,
--- a/layout/mathml/nsMathMLContainerFrame.h
+++ b/layout/mathml/nsMathMLContainerFrame.h
@@ -334,16 +334,21 @@ protected:
 public:
   static void
   PropagatePresentationDataFromChildAt(nsIFrame*       aParentFrame,
                                        int32_t         aFirstChildIndex,
                                        int32_t         aLastChildIndex,
                                        uint32_t        aFlagsValues,
                                        uint32_t        aFlagsToUpdate);
 
+  // Sets flags on aFrame and all descendant frames
+  static void
+  PropagateFrameFlagFor(nsIFrame* aFrame,
+                        uint64_t  aFlags);
+
   // helper to let the rebuild of automatic data (presentation data
   // and embellishement data) walk through a subtree that may contain
   // 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 <mfrac> who knows
--- a/layout/mathml/nsMathMLFrame.h
+++ b/layout/mathml/nsMathMLFrame.h
@@ -87,16 +87,22 @@ public:
   UpdatePresentationDataFromChildAt(int32_t         aFirstIndex,
                                     int32_t         aLastIndex,
                                     uint32_t        aFlagsValues,
                                     uint32_t        aFlagsToUpdate) MOZ_OVERRIDE
   {
     return NS_OK;
   }
 
+  uint8_t
+  ScriptIncrement(nsIFrame* aFrame) MOZ_OVERRIDE
+  {
+    return 0;
+  }
+
   // 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.
   static void
   ResolveMathMLCharStyle(nsPresContext*  aPresContext,
                          nsIContent*      aContent,
                          nsStyleContext*  aParenStyleContext,
                          nsMathMLChar*    aMathMLChar,
--- a/layout/mathml/nsMathMLmfracFrame.cpp
+++ b/layout/mathml/nsMathMLmfracFrame.cpp
@@ -38,25 +38,45 @@ nsMathMLmfracFrame::~nsMathMLmfracFrame(
 
 eMathMLFrameType
 nsMathMLmfracFrame::GetMathMLFrameType()
 {
   // frac is "inner" in TeXBook, Appendix G, rule 15e. See also page 170.
   return eMathMLFrameType_Inner;
 }
 
+uint8_t
+nsMathMLmfracFrame::ScriptIncrement(nsIFrame* aFrame)
+{
+  if (!StyleFont()->mMathDisplay &&
+      aFrame && (mFrames.FirstChild() == aFrame ||
+                 mFrames.LastChild() == aFrame)) {
+    return 1;
+  }
+  return 0;
+}
+
 NS_IMETHODIMP
 nsMathMLmfracFrame::TransmitAutomaticData()
 {
   // The TeXbook (Ch 17. p.141) says the numerator inherits the compression
   //  while the denominator is compressed
   UpdatePresentationDataFromChildAt(1,  1,
      NS_MATHML_COMPRESSED,
      NS_MATHML_COMPRESSED);
 
+  // If displaystyle is false, then scriptlevel is incremented, so notify the
+  // children of this.
+  if (!StyleFont()->mMathDisplay) {
+    PropagateFrameFlagFor(mFrames.FirstChild(),
+                          NS_FRAME_MATHML_SCRIPT_DESCENDANT);
+    PropagateFrameFlagFor(mFrames.LastChild(),
+                          NS_FRAME_MATHML_SCRIPT_DESCENDANT);
+  }
+
   // 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 <mfrac> won't fire
     // Stretch() on its embellished child
     mEmbellishData.direction = NS_STRETCH_DIRECTION_UNSUPPORTED;
   }
 
--- a/layout/mathml/nsMathMLmfracFrame.h
+++ b/layout/mathml/nsMathMLmfracFrame.h
@@ -80,16 +80,19 @@ public:
   // helper to translate the thickness attribute into a usable form
   static nscoord 
   CalcLineThickness(nsPresContext*  aPresContext,
                     nsStyleContext*  aStyleContext,
                     nsString&        aThicknessAttribute,
                     nscoord          onePixel,
                     nscoord          aDefaultRuleThickness);
 
+  uint8_t
+  ScriptIncrement(nsIFrame* aFrame) MOZ_OVERRIDE;
+
 protected:
   nsMathMLmfracFrame(nsStyleContext* aContext) : nsMathMLContainerFrame(aContext) {}
   virtual ~nsMathMLmfracFrame();
   
   nsresult PlaceInternal(nsRenderingContext& aRenderingContext,
                          bool                 aPlaceOrigin,
                          nsHTMLReflowMetrics& aDesiredSize,
                          bool                 aWidthOnly);
--- a/layout/mathml/nsMathMLmmultiscriptsFrame.cpp
+++ b/layout/mathml/nsMathMLmmultiscriptsFrame.cpp
@@ -25,48 +25,61 @@ NS_NewMathMLmmultiscriptsFrame(nsIPresSh
 }
 
 NS_IMPL_FRAMEARENA_HELPERS(nsMathMLmmultiscriptsFrame)
 
 nsMathMLmmultiscriptsFrame::~nsMathMLmmultiscriptsFrame()
 {
 }
 
+uint8_t
+nsMathMLmmultiscriptsFrame::ScriptIncrement(nsIFrame* aFrame)
+{
+  if (!aFrame)
+    return 0;
+  if (mFrames.ContainsFrame(aFrame)) {
+    if (mFrames.FirstChild() == aFrame ||
+        aFrame->GetContent()->Tag() == nsGkAtoms::mprescripts_) {
+      return 0; // No script increment for base frames or prescript markers
+    }
+    return 1;
+  }
+  return 0; //not a child
+}
+
 NS_IMETHODIMP
 nsMathMLmmultiscriptsFrame::TransmitAutomaticData()
 {
   // if our base is an embellished operator, let its state bubble to us
   mPresentationData.baseFrame = mFrames.FirstChild();
   GetEmbellishDataFrom(mPresentationData.baseFrame, mEmbellishData);
 
   // 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.
 
-  if (mContent->Tag() == nsGkAtoms::msup_)
-    return NS_OK;
-
   int32_t count = 0;
-  bool isSubScript = true;
+  bool isSubScript = mContent->Tag() != nsGkAtoms::msup_;
 
   nsAutoTArray<nsIFrame*, 8> subScriptFrames;
   nsIFrame* childFrame = mFrames.FirstChild();
   while (childFrame) {
     if (childFrame->GetContent()->Tag() == nsGkAtoms::mprescripts_) {
       // mprescripts frame
     } else if (0 == count) {
       // base frame
     } else {
       // super/subscript block
       if (isSubScript) {
         // subscript
         subScriptFrames.AppendElement(childFrame);
       } else {
         // superscript
       }
+      PropagateFrameFlagFor(childFrame, NS_FRAME_MATHML_SCRIPT_DESCENDANT);
       isSubScript = !isSubScript;
     }
     count++;
     childFrame = childFrame->GetNextSibling();
   }
   for (int32_t i = subScriptFrames.Length() - 1; i >= 0; i--) {
     childFrame = subScriptFrames[i];
     PropagatePresentationDataFor(childFrame,
--- a/layout/mathml/nsMathMLmmultiscriptsFrame.h
+++ b/layout/mathml/nsMathMLmmultiscriptsFrame.h
@@ -35,16 +35,19 @@ public:
                     nsRenderingContext& aRenderingContext,
                     bool                 aPlaceOrigin,
                     nsHTMLReflowMetrics& aDesiredSize,
                     nsMathMLContainerFrame* aForFrame,
                     nscoord              aUserSubScriptShift,
                     nscoord              aUserSupScriptShift,
                     nscoord              aScriptSpace);
 
+  uint8_t
+  ScriptIncrement(nsIFrame* aFrame) MOZ_OVERRIDE;
+
 protected:
   nsMathMLmmultiscriptsFrame(nsStyleContext* aContext) : nsMathMLContainerFrame(aContext) {}
   virtual ~nsMathMLmmultiscriptsFrame();
   
 
 };
 
 #endif /* nsMathMLmmultiscriptsFrame_h___ */
--- a/layout/mathml/nsMathMLmrootFrame.cpp
+++ b/layout/mathml/nsMathMLmrootFrame.cpp
@@ -70,16 +70,19 @@ nsMathMLmrootFrame::TransmitAutomaticDat
   //    "false", within index, but leaves both attributes unchanged within base.
   // 2. The TeXbook (Ch 17. p.141) says \sqrt is compressed
   UpdatePresentationDataFromChildAt(1, 1,
                                     NS_MATHML_COMPRESSED,
                                     NS_MATHML_COMPRESSED);
   UpdatePresentationDataFromChildAt(0, 0,
      NS_MATHML_COMPRESSED, NS_MATHML_COMPRESSED);
 
+  PropagateFrameFlagFor(mFrames.LastChild(),
+                        NS_FRAME_MATHML_SCRIPT_DESCENDANT);
+
   return NS_OK;
 }
 
 void
 nsMathMLmrootFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                      const nsRect&           aDirtyRect,
                                      const nsDisplayListSet& aLists)
 {
--- a/layout/mathml/nsMathMLmrootFrame.h
+++ b/layout/mathml/nsMathMLmrootFrame.h
@@ -43,16 +43,22 @@ public:
   virtual void
   GetIntrinsicWidthMetrics(nsRenderingContext* aRenderingContext,
                            nsHTMLReflowMetrics& aDesiredSize) MOZ_OVERRIDE;
 
   virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                 const nsRect&           aDirtyRect,
                                 const nsDisplayListSet& aLists) MOZ_OVERRIDE;
 
+  uint8_t
+  ScriptIncrement(nsIFrame* aFrame) MOZ_OVERRIDE
+  {
+    return (aFrame && aFrame == mFrames.LastChild()) ? 2 : 0;
+  }
+
 protected:
   nsMathMLmrootFrame(nsStyleContext* aContext);
   virtual ~nsMathMLmrootFrame();
   
   nsMathMLChar mSqrChar;
   nsRect       mBarRect;
 };
 
--- a/layout/mathml/nsMathMLmunderoverFrame.cpp
+++ b/layout/mathml/nsMathMLmunderoverFrame.cpp
@@ -65,16 +65,37 @@ nsMathMLmunderoverFrame::InheritAutomati
   // let the base class get the default from our parent
   nsMathMLContainerFrame::InheritAutomaticData(aParent);
 
   mPresentationData.flags |= NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY;
 
   return NS_OK;
 }
 
+uint8_t
+nsMathMLmunderoverFrame::ScriptIncrement(nsIFrame* aFrame)
+{
+  nsIFrame* child = mFrames.FirstChild();
+  if (!aFrame || aFrame == child) {
+    return 0;
+  }
+  child = child->GetNextSibling();
+  if (aFrame == child) {
+    if (mContent->Tag() == nsGkAtoms::mover_) {
+      return mIncrementOver ? 1 : 0;
+    }
+    return mIncrementUnder ? 1 : 0;
+  }
+  if (child && aFrame == child->GetNextSibling()) {
+    // must be a over frame of munderover
+    return mIncrementOver ? 1 : 0;
+  }
+  return 0;  // frame not found
+}
+
 NS_IMETHODIMP
 nsMathMLmunderoverFrame::TransmitAutomaticData()
 {
   // At this stage, all our children are in sync and we can fully
   // resolve our own mEmbellishData struct
   //---------------------------------------------------------------------
 
   /* 
@@ -204,27 +225,40 @@ XXX The winner is the outermost setting 
      say it shouldn't be compressed. However, The TeXBook says
      that math accents and \overline change uncramped styles to their
      cramped counterparts.
   */
   if (tag == nsGkAtoms::mover_ ||
       tag == nsGkAtoms::munderover_) {
     uint32_t compress = NS_MATHML_EMBELLISH_IS_ACCENTOVER(mEmbellishData.flags)
       ? NS_MATHML_COMPRESSED : 0;
-    SetIncrementScriptLevel(tag == nsGkAtoms::mover_ ? 1 : 2,
-                            !NS_MATHML_EMBELLISH_IS_ACCENTOVER(mEmbellishData.flags) || subsupDisplay);
+    mIncrementOver =
+      !NS_MATHML_EMBELLISH_IS_ACCENTOVER(mEmbellishData.flags) ||
+      subsupDisplay;
+    SetIncrementScriptLevel(tag == nsGkAtoms::mover_ ? 1 : 2, mIncrementOver);
+    if (mIncrementOver) {
+      PropagateFrameFlagFor(overscriptFrame,
+                            NS_FRAME_MATHML_SCRIPT_DESCENDANT);
+    }
     PropagatePresentationDataFor(overscriptFrame, compress, compress);
   }
   /*
      The TeXBook treats 'under' like a subscript, so p.141 or Rule 13a 
      say it should be compressed
   */
   if (tag == nsGkAtoms::munder_ ||
       tag == nsGkAtoms::munderover_) {
-    SetIncrementScriptLevel(1, !NS_MATHML_EMBELLISH_IS_ACCENTUNDER(mEmbellishData.flags) || subsupDisplay);
+    mIncrementUnder =
+      !NS_MATHML_EMBELLISH_IS_ACCENTUNDER(mEmbellishData.flags) ||
+      subsupDisplay;
+    SetIncrementScriptLevel(1, mIncrementUnder);
+    if (mIncrementUnder) {
+      PropagateFrameFlagFor(underscriptFrame,
+                            NS_FRAME_MATHML_SCRIPT_DESCENDANT);
+    }
     PropagatePresentationDataFor(underscriptFrame,
                                  NS_MATHML_COMPRESSED,
                                  NS_MATHML_COMPRESSED);
   }
   return NS_OK;
 }
 
 /*
--- a/layout/mathml/nsMathMLmunderoverFrame.h
+++ b/layout/mathml/nsMathMLmunderoverFrame.h
@@ -34,15 +34,24 @@ public:
   UpdatePresentationData(uint32_t        aFlagsValues,
                          uint32_t        aFlagsToUpdate) MOZ_OVERRIDE;
 
   NS_IMETHOD
   AttributeChanged(int32_t         aNameSpaceID,
                    nsIAtom*        aAttribute,
                    int32_t         aModType) MOZ_OVERRIDE;
 
+  uint8_t
+  ScriptIncrement(nsIFrame* aFrame) MOZ_OVERRIDE;
+
 protected:
-  nsMathMLmunderoverFrame(nsStyleContext* aContext) : nsMathMLContainerFrame(aContext) {}
+  nsMathMLmunderoverFrame(nsStyleContext* aContext) : nsMathMLContainerFrame(aContext),
+                                                      mIncrementUnder(false),
+                                                      mIncrementOver(false) {}
   virtual ~nsMathMLmunderoverFrame();
+
+private:
+  bool mIncrementUnder;
+  bool mIncrementOver;
 };
 
 
 #endif /* nsMathMLmunderoverFrame_h___ */