Bug 781494 - Remove support for composite char from nsMathMLChar. r=karlt
authorFrédéric Wang <fred.wang@free.fr>
Mon, 20 Aug 2012 20:14:20 -0400
changeset 102862 f9094ef74bf369e3112887164afc9e8a6fdfb799
parent 102861 17ddc4d169e1f9d54cfc005e5e67a4ea8e97146a
child 102863 313eb51d2b577436f8ca590b6890085b0d87b6da
push id13685
push userryanvm@gmail.com
push dateTue, 21 Aug 2012 00:21:46 +0000
treeherdermozilla-inbound@f9094ef74bf3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskarlt
bugs781494
milestone17.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 781494 - Remove support for composite char from nsMathMLChar. r=karlt
layout/mathml/MathJaxFonts.html
layout/mathml/mathfont.properties
layout/mathml/mathfontMathJax_Main.properties
layout/mathml/nsMathMLChar.cpp
layout/mathml/nsMathMLChar.h
--- a/layout/mathml/MathJaxFonts.html
+++ b/layout/mathml/MathJaxFonts.html
@@ -48,30 +48,17 @@
           hexacode = "0" + hexacode;
         }
         return "\\u" + hexacode + f;
       }
 
       function codePoint2(aList)
       {
         if (aList) {
-          if (Array.isArray(aList[0])) {
-            // Generate a string representation for a composite character.
-            // (the syntax may not match the parser in nsMathMLChar, but 
-            // support for composite character is broken anyway).
-            var str = "(";
-            str += codePoint(aList[0][0], aList[1]);
-            for (var i = 1; i < aList[0].length; i++) {
-              str += "," + codePoint(aList[0][i], aList[1]);
-            }
-            str += ")";
-            return str;
-          } else {
-            return codePoint(aList[0], aList[1]);
-          }
+          return codePoint(aList[0], aList[1]);
         } else {
           return noChar;
         }
       }
 
       function isSupported(aStretch)
       {
         for (var x in aStretch) {
@@ -124,18 +111,19 @@
             v = delimiters[v.alias];
           } else {
             // It is an alias to a non-stretchy char. Ignore it.
             continue;
           }
         }
 
         if (v.stretch && !isSupported(v.stretch)) {
-          // This construction is not supported. Comment the line.
-          t.value += "# ";
+          // This construction is not supported.
+          t.value += "# " + codePoint(u) + " = [not supported]\n";
+          continue;
         }
 
         t.value += codePoint(u);
         t.value += " = ";
         if (v.stretch) {
           if (v.dir == "V") {
             t.value += codePoint2(v.stretch.top);
             t.value += codePoint2(v.stretch.mid);
--- a/layout/mathml/mathfont.properties
+++ b/layout/mathml/mathfont.properties
@@ -1217,16 +1217,8 @@ operator.\uFE38.postfix = lspace:0 rspac
 # the "Symbol" font and the "MT Extra" font are in "mathfontSymbol.properties"
 # and "mathfontMTExtra.properties", respectively. The font property file is a
 # set of all the stretchy MathML characters that can be rendered with that font
 # using larger and/or partial glyphs. Each stretchy character is associated to
 # a list in the font property file which gives, in that order, the 4 partial
 # glyphs: top (or left), middle, bottom (or right), glue; and the variants of
 # bigger sizes (if any). A position that is not relevant to a particular character
 # is indicated there with the UNICODE REPLACEMENT CHARACTER 0xFFFD.
-#
-# Characters that need to be built from other characters are said to be composite.
-# For example, characters like over/underbrace in CMEX10 have to be built from two
-# half stretchy chars and joined in the middle (TeXbook, p.225). Several (i.e., 2
-# or more) child characters can be composed in order to render another chararacter.
-# To specify such characters, their list of glyphs in the property file should be
-# given as space-separated segments of glyphs. Each segment gives the 4 partial glyphs
-# with which to build the child character that will be joined with its other siblings.
--- a/layout/mathml/mathfontMathJax_Main.properties
+++ b/layout/mathml/mathfontMathJax_Main.properties
@@ -4,17 +4,17 @@
 
 # Content below is generated from MathJaxFonts.html. Do not edit.
 
 external.1 = MathJax_Size1
 external.2 = MathJax_Size2
 external.3 = MathJax_Size3
 external.4 = MathJax_Size4
 external.5 = MathJax_AMS
-# external.6 = MathJax_Main-Bold
+# external.6 = MathJax_Main-bold
 
 \u0028 = \u239B@4\uFFFD\u239D@4\u239C@4\u0028\u0028@1\u0028@2\u0028@3\u0028@4
 \u0029 = \u239E@4\uFFFD\u23A0@4\u239F@4\u0029\u0029@1\u0029@2\u0029@3\u0029@4
 \u002F = \uFFFD\uFFFD\uFFFD\uFFFD\u002F\u002F@1\u002F@2\u002F@3\u002F@4
 \u005B = \u23A1@4\uFFFD\u23A3@4\u23A2@4\u005B\u005B@1\u005B@2\u005B@3\u005B@4
 \u005C = \uFFFD\uFFFD\uFFFD\uFFFD\u005C\u005C@1\u005C@2\u005C@3\u005C@4
 \u005D = \u23A4@4\uFFFD\u23A6@4\u23A5@4\u005D\u005D@1\u005D@2\u005D@3\u005D@4
 \u007B = \u23A7@4\u23A8@4\u23A9@4\u23AA@4\u007B\u007B@1\u007B@2\u007B@3\u007B@4
@@ -43,18 +43,18 @@ external.5 = MathJax_AMS
 \u2308 = \u23A1@4\uFFFD\uFFFD\u23A2@4\u2308\u2308@1\u2308@2\u2308@3\u2308@4
 \u2309 = \u23A4@4\uFFFD\uFFFD\u23A5@4\u2309\u2309@1\u2309@2\u2309@3\u2309@4
 \u230A = \uFFFD\uFFFD\u23A3@4\u23A2@4\u230A\u230A@1\u230A@2\u230A@3\u230A@4
 \u230B = \uFFFD\uFFFD\u23A6@4\u23A5@4\u230B\u230B@1\u230B@2\u230B@3\u230B@4
 \u23AA = \u23AA@4\uFFFD\u23AA@4\u23AA@4\u23AA@4
 \u23B0 = \u23A7@4\uFFFD\u23AD@4\u23AA@4\u23B0
 \u23B1 = \u23AB@4\uFFFD\u23A9@4\u23AA@4\u23B1
 \u23D0 = \uFFFD\uFFFD\uFFFD\u2223\u23D0@1\u23D0
-# \u23DE = \uE150@4(\uE153@4,\uE152@4)\uE151@4\uE154@4
-# \u23DF = \uE152@4(\uE151@4,\uE150@4)\uE153@4\uE154@4
+# \u23DE = [not supported]
+# \u23DF = [not supported]
 \u27E8 = \uFFFD\uFFFD\uFFFD\uFFFD\u27E8\u27E8@1\u27E8@2\u27E8@3\u27E8@4
 \u27E9 = \uFFFD\uFFFD\uFFFD\uFFFD\u27E9\u27E9@1\u27E9@2\u27E9@3\u27E9@4
 \u27EE = \u23A7@4\uFFFD\u23A9@4\u23AA@4\u27EE
 \u27EF = \u23AB@4\uFFFD\u23AD@4\u23AA@4\u27EF
 \u002D = \uFFFD\uFFFD\uFFFD\u2212\u002D
 \u005E = \uFFFD\uFFFD\uFFFD\uFFFD\u005E\u005E@1\u005E@2\u005E@3\u005E@4
 \u005F = \uFFFD\uFFFD\uFFFD\u2212\u005F
 \u007E = \uFFFD\uFFFD\uFFFD\uFFFD\u007E\u007E@1\u007E@2\u007E@3\u007E@4
@@ -68,67 +68,67 @@ external.5 = MathJax_AMS
 \u2215 = \uFFFD\uFFFD\uFFFD\uFFFD\u2215\u2215@1\u2215@2\u2215@3\u2215@4
 \u2329 = \uFFFD\uFFFD\uFFFD\uFFFD\u2329\u2329@1\u2329@2\u2329@3\u2329@4
 \u232A = \uFFFD\uFFFD\uFFFD\uFFFD\u232A\u232A@1\u232A@2\u232A@3\u232A@4
 \u23AF = \uFFFD\uFFFD\uFFFD\u2212\u23AF
 \u2500 = \uFFFD\uFFFD\uFFFD\u2212\u2500
 \u2758 = \uFFFD\uFFFD\uFFFD\u2223\u2758
 \u3008 = \uFFFD\uFFFD\uFFFD\uFFFD\u3008\u3008@1\u3008@2\u3008@3\u3008@4
 \u3009 = \uFFFD\uFFFD\uFFFD\uFFFD\u3009\u3009@1\u3009@2\u3009@3\u3009@4
-# \uFE37 = \uE150@4(\uE153@4,\uE152@4)\uE151@4\uE154@4
-# \uFE38 = \uE152@4(\uE151@4,\uE150@4)\uE153@4\uE154@4
+# \uFE37 = [not supported]
+# \uFE38 = [not supported]
 \u003D = \uFFFD\uFFFD\uFFFD\u003D\u003D
 \u219E = \u219E@5\uFFFD\uFFFD\u2212\u219E@5
 \u21A0 = \uFFFD\uFFFD\u21A0@5\u2212\u21A0@5
-# \u21A4 = \u2190\uFFFD\u2223@1\u2212
-# \u21A5 = \u2191@1\uFFFD\u22A5@6\u23D0@1
-# \u21A6 = \u2223@1\uFFFD\u2192\u2212\u21A6
-# \u21A7 = \u22A4@6\uFFFD\u2193@1\u23D0@1
-# \u21B0 = \u21B0@5\uFFFD\uFFFD\u23D0@1\u21B0@5
-# \u21B1 = \u21B1@5\uFFFD\uFFFD\u23D0@1\u21B1@5
+# \u21A4 = [not supported]
+# \u21A5 = [not supported]
+# \u21A6 = [not supported]
+# \u21A7 = [not supported]
+# \u21B0 = [not supported]
+# \u21B1 = [not supported]
 \u21BC = \u21BC\uFFFD\uFFFD\u2212\u21BC
 \u21BD = \u21BD\uFFFD\uFFFD\u2212\u21BD
-# \u21BE = \u21BE@5\uFFFD\uFFFD\u23D0@1\u21BE@5
-# \u21BF = \u21BF@5\uFFFD\uFFFD\u23D0@1\u21BF@5
+# \u21BE = [not supported]
+# \u21BF = [not supported]
 \u21C0 = \uFFFD\uFFFD\u21C0\u2212\u21C0
 \u21C1 = \uFFFD\uFFFD\u21C1\u2212\u21C1
-# \u21C2 = \uFFFD\uFFFD\u21C2@5\u23D0@1\u21C2@5
-# \u21C3 = \uFFFD\uFFFD\u21C3@5\u23D0@1\u21C3@5
+# \u21C2 = [not supported]
+# \u21C3 = [not supported]
 \u21DA = \u21DA@5\uFFFD\uFFFD\u2261\u21DA@5
 \u21DB = \uFFFD\uFFFD\u21DB@5\u2261\u21DB@5
-# \u23B4 = \u250C@5\uFFFD\u2510@5\u2212
-# \u23B5 = \u2514@5\uFFFD\u2518@5\u2212
+# \u23B4 = [not supported]
+# \u23B5 = [not supported]
 \u23DC = \uE150@4\uFFFD\uE151@4\uE154@4\u23DC@5\u23DC
 \u23DD = \uE152@4\uFFFD\uE153@4\uE154@4\u23DD@5\u23DD
-# \u23E0 = \u02CA\uFFFD\u02CB\u02C9
-# \u23E1 = \u02CB\uFFFD\u02CA\u02C9
-# \u2906 = \u21D0\uFFFD\u2223@1\u003D
-# \u2907 = \u22A8@5\uFFFD\u21D2\u003D
+# \u23E0 = [not supported]
+# \u23E1 = [not supported]
+# \u2906 = [not supported]
+# \u2907 = [not supported]
 \u294E = \u21BC\uFFFD\u21C0\u2212
-# \u294F = \u21BE@5\uFFFD\u21C2@5\u23D0@1
+# \u294F = [not supported]
 \u2950 = \u21BD\uFFFD\u21C1\u2212
-# \u2951 = \u21BF@5\uFFFD\u21C3@5\u23D0@1
-# \u295A = \u21BC\uFFFD\u2223@1\u2212
-# \u295B = \u2223@1\uFFFD\u21C0\u2212
-# \u295C = \u21BE@5\uFFFD\u22A5@6\u23D0@1
-# \u295D = \u22A4@6\uFFFD\u21C2@5\u23D0@1
-# \u295E = \u21BD\uFFFD\u2223@1\u2212
-# \u295F = \u2223@1\uFFFD\u21C1\u2212
-# \u2960 = \u21BF@5\uFFFD\u22A5@6\u23D0@1
-# \u2961 = \u22A4@6\uFFFD\u21C3@5\u23D0@1
+# \u2951 = [not supported]
+# \u295A = [not supported]
+# \u295B = [not supported]
+# \u295C = [not supported]
+# \u295D = [not supported]
+# \u295E = [not supported]
+# \u295F = [not supported]
+# \u2960 = [not supported]
+# \u2961 = [not supported]
 \u27F5 = \u2190\uFFFD\uFFFD\u2212\u27F5
 \u27F6 = \uFFFD\uFFFD\u2192\u2212\u27F6
 \u27F7 = \u2190\uFFFD\u2192\u2212\u27F7
 \u27F8 = \u21D0\uFFFD\uFFFD\u003D\u27F8
 \u27F9 = \uFFFD\uFFFD\u21D2\u003D\u27F9
 \u27FA = \u21D0\uFFFD\u21D2\u003D\u27FA
-# \u27FB = \u2190\uFFFD\u2223@1\u2212
-# \u27FC = \u2223@1\uFFFD\u2192\u2212\u27FC
-# \u27FD = \u21D0\uFFFD\u2223@1\u003D
-# \u27FE = \u22A8@5\uFFFD\u21D2\u003D
+# \u27FB = [not supported]
+# \u27FC = [not supported]
+# \u27FD = [not supported]
+# \u27FE = [not supported]
 \u0020 = \uFFFD\uFFFD\uFFFD\uFFFD\u0020@1\u0020@2
 \u00A0 = \uFFFD\uFFFD\uFFFD\uFFFD\u00A0@1\u00A0@2
 \u220F = \uFFFD\uFFFD\uFFFD\uFFFD\u220F@1\u220F@2
 \u2210 = \uFFFD\uFFFD\uFFFD\uFFFD\u2210@1\u2210@2
 \u2211 = \uFFFD\uFFFD\uFFFD\uFFFD\u2211@1\u2211@2
 \u222B = \uFFFD\uFFFD\uFFFD\uFFFD\u222B@1\u222B@2
 \u222C = \uFFFD\uFFFD\uFFFD\uFFFD\u222C@1\u222C@2
 \u222D = \uFFFD\uFFFD\uFFFD\uFFFD\u222D@1\u222D@2
--- a/layout/mathml/nsMathMLChar.cpp
+++ b/layout/mathml/nsMathMLChar.cpp
@@ -66,32 +66,16 @@ typedef enum {eExtension_base, eExtensio
 // and "mathfontMTExtra.properties", respectively. The mathfont property file
 // is a set of all the stretchy MathML characters that can be rendered with that
 // font using larger and/or partial glyphs. The entry of each stretchy character
 // in the mathfont property file gives, in that order, the 4 partial glyphs:
 // Top (or Left), Middle, Bottom (or Right), Glue; and the variants of bigger
 // sizes (if any).
 // A position that is not relevant to a particular character is indicated there
 // with the UNICODE REPLACEMENT CHARACTER 0xFFFD.
-// Characters that need to be built recursively from other characters are said
-// to be composite. For example, chars like over/underbrace in CMEX10 have to
-// be built from two half stretchy chars and joined in the middle
-// (TeXbook, p.225).
-// Such chars are handled in a special manner by the nsMathMLChar class, which
-// allows several (2 or more) child chars to be composed in order to render
-// another char.
-// To specify such chars, their list of glyphs in the property file should be
-// given as space-separated segments of glyphs. Each segment gives the 4 partial
-// glyphs with which to build the child char that will be joined with its other
-// siblings. In this code, when this situation happens (see the detailed
-// description of Stretch() below), the original char (referred to as "parent")
-// creates a singly-linked list of child chars, asking them to stretch in an
-// equally divided space. The nsGlyphTable embeds the necessary logic to
-// guarantee correctness in a recursive stretch (and in the use of TopOf(),
-// GlueOf(), etc) on these child chars.
 // -----------------------------------------------------------------------------
 
 #define NS_TABLE_TYPE_UNICODE       0
 #define NS_TABLE_TYPE_GLYPH_INDEX   1
 
 #define NS_TABLE_STATE_ERROR       -1
 #define NS_TABLE_STATE_EMPTY        0
 #define NS_TABLE_STATE_READY        1
@@ -152,25 +136,19 @@ public:
 
   // True if this table contains some glyphs (variants and/or parts)
   // or contains child chars that can be used to render this char
   bool Has(nsPresContext* aPresContext, nsMathMLChar* aChar);
 
   // True if this table contains variants of larger sizes to render this char
   bool HasVariantsOf(nsPresContext* aPresContext, nsMathMLChar* aChar);
 
-  // True if this table contains parts (or composite parts) to render this char
+  // True if this table contains parts to render this char
   bool HasPartsOf(nsPresContext* aPresContext, nsMathMLChar* aChar);
 
-  // True if aChar is to be assembled from other child chars in this table
-  bool IsComposite(nsPresContext* aPresContext, nsMathMLChar* aChar);
-
-  // The number of child chars to assemble in order to render aChar
-  PRInt32 ChildCountOf(nsPresContext* aPresContext, nsMathMLChar* aChar);
-
   // Getters for the parts
   nsGlyphCode TopOf(nsPresContext* aPresContext, nsMathMLChar* aChar) {
     return ElementAt(aPresContext, aChar, 0);
   }
   nsGlyphCode MiddleOf(nsPresContext* aPresContext, nsMathMLChar* aChar) {
     return ElementAt(aPresContext, aChar, 1);
   }
   nsGlyphCode BottomOf(nsPresContext* aPresContext, nsMathMLChar* aChar) {
@@ -264,20 +242,16 @@ nsGlyphTable::ElementAt(nsPresContext* a
       key.AppendInt(i, 10);
       rv = mGlyphProperties->GetStringProperty(key, value);
       if (NS_FAILED(rv)) break;
       Clean(value);
       mFontName.AppendElement(value); // i.e., mFontName[i] holds this font name
     }
   }
 
-  // If aChar is a child char to be used by a parent composite char, make
-  // sure that it is really attached to this table
-  if (aChar->mParent && (aChar->mGlyphTable != this)) return kNullGlyph;
-
   // Update our cache if it is not associated to this character
   PRUnichar uchar = aChar->mData[0];
   if (mCharCache != uchar) {
     // The key in the property file is interpreted as ASCII and kept
     // as such ...
     char key[10]; PR_snprintf(key, sizeof(key), "\\u%04X", uchar);
     nsAutoString value;
     nsresult rv = mGlyphProperties->GetStringProperty(nsDependentCString(key),
@@ -291,26 +265,20 @@ nsGlyphTable::ElementAt(nsPresContext* a
     // codes as combined pairs of 'code@font', excluding the '@' separator. This
     // means that mGlyphCache[3*k],mGlyphCache[3*k+1] will later be rendered
     // with mFontName[mGlyphCache[3*k+2]]
     // Note: font identifier is internally an ASCII digit to avoid the null
     // char issue
     nsAutoString buffer;
     PRInt32 length = value.Length();
     PRInt32 i = 0; // index in value
-    PRInt32 j = 0; // part/variant index
     while (i < length) {
       PRUnichar code = value[i];
       ++i;
       buffer.Append(code);
-      // see if we are at the beginning of a child char
-      if (code == kSpaceCh) {
-        // reset the annotation indicator to be 0 for the next code point
-        j = -1;
-      }
       // Read the next word if we have a non-BMP character.
       if (i < length && NS_IS_HIGH_SURROGATE(code)) {
         code = value[i];
         ++i;
       } else {
         code = PRUnichar('\0');
       }
       buffer.Append(code);
@@ -328,79 +296,33 @@ nsGlyphTable::ElementAt(nsPresContext* a
           return kNullGlyph;
         }
         // The char cannot be handled if this font is not installed
         if (!mFontName[font].Length()) {
           return kNullGlyph;
         }
       }
       buffer.Append(font);
-      ++j;
     }
     // update our cache with the new settings
     mGlyphCache.Assign(buffer);
     mCharCache = uchar;
   }
 
-  // If aChar is a composite char, only its children are allowed
-  // to use its glyphs in this table, i.e., the parent char itself
-  // is disabled and cannot be stretched directly with these glyphs.
-  // This guarantees a coherent behavior in Stretch().
-  if (!aChar->mParent && (kNotFound != mGlyphCache.FindChar(kSpaceCh))) {
-    return kNullGlyph;
-  }
-
-  // If aChar is a child char, the index of the glyph is relative to
-  // the offset of the list of glyphs corresponding to the child char.
-  PRUint32 offset = 0;
-  PRUint32 length = mGlyphCache.Length();
-  if (aChar->mParent) {
-    nsMathMLChar* child = aChar->mParent->mSibling;
-    // XXXkt composite chars can't have size variants
-    while (child && (child != aChar)) {
-      offset += 5; // skip the 4 partial glyphs + the whitespace separator
-      child = child->mSibling;
-    }
-    // stay confined in the 4 partial glyphs of this child
-    length = 3*(offset + 4);
-  }
   // 3* is to account for the code@font pairs
-  PRUint32 index = 3*(offset + aPosition);
-  if (index+2 >= length) return kNullGlyph;
+  PRUint32 index = 3*aPosition;
+  if (index+2 >= mGlyphCache.Length()) return kNullGlyph;
   nsGlyphCode ch;
   ch.code[0] = mGlyphCache.CharAt(index);
   ch.code[1] = mGlyphCache.CharAt(index + 1);
   ch.font = mGlyphCache.CharAt(index + 2);
   return ch.code[0] == PRUnichar(0xFFFD) ? kNullGlyph : ch;
 }
 
 bool
-nsGlyphTable::IsComposite(nsPresContext* aPresContext, nsMathMLChar* aChar)
-{
-  // there is only one level of recursion in our model. a child
-  // cannot be composite because it cannot have its own children
-  if (aChar->mParent) return false;
-  // shortcut to sync the cache with this char...
-  mCharCache = 0; mGlyphCache.Truncate(); ElementAt(aPresContext, aChar, 0);
-  // the cache remained empty if the char wasn't found in this table
-  if (4*3 >= mGlyphCache.Length()) return false;
-  // the lists of glyphs of a composite char are space-separated
-  return (kSpaceCh == mGlyphCache.CharAt(4*3));
-}
-
-PRInt32
-nsGlyphTable::ChildCountOf(nsPresContext* aPresContext, nsMathMLChar* aChar)
-{
-  // this will sync the cache as well ...
-  if (!IsComposite(aPresContext, aChar)) return 0;
-  // the lists of glyphs of a composite char are space-separated
-  return 1 + mGlyphCache.CountChar(kSpaceCh);
-}
-
-bool
 nsGlyphTable::Has(nsPresContext* aPresContext, nsMathMLChar* aChar)
 {
   return HasVariantsOf(aPresContext, aChar) || HasPartsOf(aPresContext, aChar);
 }
 
 bool
 nsGlyphTable::HasVariantsOf(nsPresContext* aPresContext, nsMathMLChar* aChar)
 {
@@ -409,18 +331,17 @@ nsGlyphTable::HasVariantsOf(nsPresContex
 }
 
 bool
 nsGlyphTable::HasPartsOf(nsPresContext* aPresContext, nsMathMLChar* aChar)
 {
   return GlueOf(aPresContext, aChar).Exists() ||
     TopOf(aPresContext, aChar).Exists() ||
     BottomOf(aPresContext, aChar).Exists() ||
-    MiddleOf(aPresContext, aChar).Exists() ||
-    IsComposite(aPresContext, aChar);
+    MiddleOf(aPresContext, aChar).Exists();
 }
 
 // -----------------------------------------------------------------------------
 // This is the list of all the applicable glyph tables.
 // We will maintain a single global instance that will only reveal those
 // glyph tables that are associated to fonts currently installed on the
 // user' system. The class is an XPCOM shutdown observer to allow us to
 // free its allocated data at shutdown
@@ -692,48 +613,38 @@ InitGlobals(nsPresContext* aPresContext)
 }
 
 // -----------------------------------------------------------------------------
 // And now the implementation of nsMathMLChar
 
 nsStyleContext*
 nsMathMLChar::GetStyleContext() const
 {
-  NS_ASSERTION(!mParent, "invalid call - not allowed for child chars");
   NS_ASSERTION(mStyleContext, "chars should always have style context");
   return mStyleContext;
 }
 
 void
 nsMathMLChar::SetStyleContext(nsStyleContext* aStyleContext)
 {
-  NS_ASSERTION(!mParent, "invalid call - not allowed for child chars");
   NS_PRECONDITION(aStyleContext, "null ptr");
   if (aStyleContext != mStyleContext) {
     if (mStyleContext)
       mStyleContext->Release();
     if (aStyleContext) {
       mStyleContext = aStyleContext;
       aStyleContext->AddRef();
-
-      // Sync the pointers of child chars.
-      nsMathMLChar* child = mSibling;
-      while (child) {
-        child->mStyleContext = mStyleContext;
-        child = child->mSibling;
-      }
     }
   }
 }
 
 void
 nsMathMLChar::SetData(nsPresContext* aPresContext,
                       nsString&       aData)
 {
-  NS_ASSERTION(!mParent, "invalid call - not allowed for child chars");
   if (!gInitialized) {
     InitGlobals(aPresContext);
   }
   mData = aData;
   // some assumptions until proven otherwise
   // note that mGlyph is not initialized
   mDirection = NS_STRETCH_DIRECTION_UNSUPPORTED;
   mBoundingMetrics = nsBoundingMetrics();
@@ -798,26 +709,18 @@ nsMathMLChar::SetData(nsPresContext* aPr
        smaller variants already fit the container' size.
     b) if it is a largeopOnly request (i.e., a displaystyle operator
        with largeop=true and stretchy=false), we break after finding
        the first starting variant, regardless of whether that
        variant fits the container's size.
 
  3) If a variant of appropriate size wasn't found, we see if the char
     can be built by parts using the same glyph table.
-    Issues:
-    a) Certain chars like over/underbrace in CMEX10 have to be built
-       from two half stretchy chars and joined in the middle. Such
-       chars are handled in a special manner. When this situation is
-       detected, the initial char (referred to as "parent") creates a
-       singly-linked list of child chars, asking them to stretch in
-       a divided space. A convention is used in the setup of
-       nsGlyphTable to express that a composite parent char can be built
-       from child chars.
-    b) There are some chars that have no middle and glue glyphs. For
+    Issue:
+       There are chars that have no middle and glue glyphs. For
        such chars, the parts need to be joined using the rule.
        By convention (TeXbook p.225), the descent of the parts is
        zero while their ascent gives the thickness of the rule that
        should be used to join them.
 
  4) If a match was not found in that glyph table, repeat from 2 to search the
     ordered list of stretchy fonts for the first font with a glyph table that
     provides a fit to the container size.  If no fit is found, the closest fit
@@ -1188,40 +1091,16 @@ nsMathMLChar::StretchEnumContext::TryVar
 // Always updates the char if a better match is found.
 bool
 nsMathMLChar::StretchEnumContext::TryParts(nsGlyphTable*    aGlyphTable,
                                            const nsAString& aFamily)
 {
   if (!aGlyphTable->HasPartsOf(mPresContext, mChar))
     return false; // to next table
 
-  // See if this is a composite character /////////////////////////////////////
-  if (aGlyphTable->IsComposite(mPresContext, mChar)) {
-    // let the child chars do the job
-    nsBoundingMetrics compositeSize;
-    nsresult rv =
-      mChar->ComposeChildren(mPresContext, mRenderingContext, aGlyphTable,
-                             mTargetSize, compositeSize, mStretchHint);
-#ifdef NOISY_SEARCH
-    printf("    Composing %d chars in font %s %s!\n",
-           aGlyphTable->ChildCountOf(mPresContext, mChar),
-           NS_LossyConvertUTF16toASCII(fontName).get(),
-           NS_SUCCEEDED(rv)? "OK" : "Rejected");
-#endif
-    if (NS_FAILED(rv))
-      return false; // to next table
-
-    // all went well, painting will be delegated from now on to children
-    mChar->mGlyph = kNullGlyph; // this will tell paint to build by parts
-    mGlyphFound = true;
-    mChar->mGlyphTable = aGlyphTable;
-    mBoundingMetrics = compositeSize;
-    return true; // no more searching
-  }
-
   // See if the parts of this table fit in the desired space //////////////////
 
   // Use our stretchy style context now that stretching is in progress
   nsFont font = mChar->mStyleContext->GetStyleFont()->mFont;
   // Ensure mRenderingContext.SetFont will be called:
   font.name.Truncate();
 
   // Compute the bounding metrics of all partial glyphs
@@ -1712,99 +1591,16 @@ nsMathMLChar::GetMaxWidth(nsPresContext*
   const nsBoundingMetrics container; // zero target size
 
   StretchInternal(aPresContext, aRenderingContext, direction, container,
                   bm, aStretchHint | NS_STRETCH_MAXWIDTH);
 
   return NS_MAX(bm.width, bm.rightBearing) - NS_MIN(0, bm.leftBearing);
 }
 
-nsresult
-nsMathMLChar::ComposeChildren(nsPresContext*      aPresContext,
-                              nsRenderingContext& aRenderingContext,
-                              nsGlyphTable*        aGlyphTable,
-                              nscoord              aTargetSize,
-                              nsBoundingMetrics&   aCompositeSize,
-                              PRUint32             aStretchHint)
-{
-  PRInt32 i = 0;
-  nsMathMLChar* child;
-  PRInt32 count = aGlyphTable->ChildCountOf(aPresContext, this);
-  NS_ASSERTION(count, "something is wrong somewhere");
-  if (!count) return NS_ERROR_FAILURE;
-  // if we haven't been here before, create the linked list of children now
-  // otherwise, use what we have, adding more children as needed or deleting
-  // the extra
-  nsMathMLChar* last = this;
-  while ((i < count) && last->mSibling) {
-    i++;
-    last = last->mSibling;
-  }
-  while (i < count) {
-    child = new nsMathMLChar(this);
-    last->mSibling = child;
-    last = child;
-    i++;
-  }
-  if (last->mSibling) {
-    delete last->mSibling;
-    last->mSibling = nullptr;
-  }
-  // let children stretch in an equal space
-  nsBoundingMetrics splitSize;
-  if (NS_STRETCH_DIRECTION_HORIZONTAL == mDirection)
-    splitSize.width = aTargetSize / count;
-  else {
-    splitSize.ascent = aTargetSize / (count * 2);
-    splitSize.descent = splitSize.ascent;
-  }
-  nscoord dx = 0, dy = 0;
-  for (i = 0, child = mSibling; child; child = child->mSibling, i++) {
-    // child chars should just inherit our values - which may change between
-    // calls...
-    child->mData = mData;
-    child->mDirection = mDirection;
-    child->mStyleContext = mStyleContext;
-    child->mGlyphTable = aGlyphTable; // the child is associated to this table
-    child->mMirrored = mMirrored;
-    // there goes the Stretch() ...
-    nsBoundingMetrics childSize;
-    nsresult rv = child->Stretch(aPresContext, aRenderingContext, mDirection,
-                                 splitSize, childSize, aStretchHint, mMirrored);
-    // check if something went wrong or the child couldn't fit in the alloted
-    // space
-    if (NS_FAILED(rv) ||
-        (NS_STRETCH_DIRECTION_UNSUPPORTED == child->mDirection)) {
-      delete mSibling; // don't leave a dangling list behind ...
-      mSibling = nullptr;
-      return NS_ERROR_FAILURE;
-    }
-    child->SetRect(nsRect(dx, dy, childSize.width,
-                          childSize.ascent+childSize.descent));
-    if (0 == i)
-      aCompositeSize = childSize;
-    else {
-      if (NS_STRETCH_DIRECTION_HORIZONTAL == mDirection)
-        aCompositeSize += childSize;
-      else {
-        aCompositeSize.descent += childSize.ascent + childSize.descent;
-        if (aCompositeSize.leftBearing > childSize.leftBearing)
-          aCompositeSize.leftBearing = childSize.leftBearing;
-        if (aCompositeSize.rightBearing < childSize.rightBearing)
-          aCompositeSize.rightBearing = childSize.rightBearing;
-      }
-    }
-    if (NS_STRETCH_DIRECTION_HORIZONTAL == mDirection)
-      dx += childSize.width;
-    else
-      dy += childSize.ascent + childSize.descent;
-  }
-  return NS_OK;
-}
-
 class nsDisplayMathMLSelectionRect : public nsDisplayItem {
 public:
   nsDisplayMathMLSelectionRect(nsDisplayListBuilder* aBuilder,
                                nsIFrame* aFrame, const nsRect& aRect)
     : nsDisplayItem(aBuilder, aFrame), mRect(aRect) {
     MOZ_COUNT_CTOR(nsDisplayMathMLSelectionRect);
   }
 #ifdef NS_BUILD_REFCNT_LOGGING
--- a/layout/mathml/nsMathMLChar.h
+++ b/layout/mathml/nsMathMLChar.h
@@ -52,51 +52,33 @@ struct nsGlyphCode {
   bool operator!=(const nsGlyphCode& other) const
   {
     return ! operator==(other);
   }
 };
 
 // Class used to handle stretchy symbols (accent, delimiter and boundary
 // symbols).
-// There are composite characters that need to be built recursively from other
-// characters. Since these are rare we use a light-weight mechanism to handle
-// them. Specifically, as need arises we append a singly-linked list of child
-// chars with their mParent pointing to the first element in the list, except in
-// the originating first element itself where it points to null. mSibling points
-// to the next element in the list. Since the originating first element is the
-// parent of the others, we call it the "root" char of the list. Testing
-// !mParent tells whether you are that "root" during the recursion. The parent
-// delegates most of the tasks to the children.
 class nsMathMLChar
 {
 public:
   // constructor and destructor
-  nsMathMLChar(nsMathMLChar* aParent = nullptr) {
+  nsMathMLChar() {
     MOZ_COUNT_CTOR(nsMathMLChar);
     mStyleContext = nullptr;
-    mSibling = nullptr;
-    mParent = aParent;
     mUnscaledAscent = 0;
     mScaleX = mScaleY = 1.0;
     mDrawNormal = true;
     mMirrored = false;
   }
 
   // not a virtual destructor: this class is not intended to be subclassed
   ~nsMathMLChar() {
     MOZ_COUNT_DTOR(nsMathMLChar);
-    // there is only one style context owned by the "root" char
-    // and it may be used by child chars as well
-    if (!mParent && mStyleContext) { // only the "root" need to release it
-      mStyleContext->Release();
-    }
-    if (mSibling) {
-      delete mSibling;
-    }
+    mStyleContext->Release();
   }
 
   nsresult
   Display(nsDisplayListBuilder*   aBuilder,
           nsIFrame*               aForFrame,
           const nsDisplayListSet& aLists,
           PRUint32                aIndex,
           const nsRect*           aSelectedRect = nullptr);
@@ -147,26 +129,16 @@ public:
   void
   GetRect(nsRect& aRect) {
     aRect = mRect;
   }
 
   void
   SetRect(const nsRect& aRect) {
     mRect = aRect;
-    // shift the orgins of child chars if any 
-    if (!mParent && mSibling) { // only a "root" having child chars can
-                                // enter here
-      for (nsMathMLChar* child = mSibling; child; child = child->mSibling) {
-        nsRect rect; 
-        child->GetRect(rect);
-        rect.MoveBy(mRect.x, mRect.y);
-        child->SetRect(rect);
-      }
-    }
   }
 
   // Get the maximum width that the character might have after a vertical
   // Stretch().
   //
   // @param aStretchHint can be the value that will be passed to Stretch().
   // It is used to determine whether the operator is stretchy or a largeop.
   // @param aMaxSize is the value of the "maxsize" attribute.
@@ -204,20 +176,16 @@ public:
   nsStyleContext* GetStyleContext() const;
 
   void SetStyleContext(nsStyleContext* aStyleContext);
 
 protected:
   friend class nsGlyphTable;
   nsString           mData;
 
-  // support for handling composite stretchy chars like TeX over/under braces
-  nsMathMLChar*      mSibling;
-  nsMathMLChar*      mParent;
-
 private:
   nsRect             mRect;
   nsStretchDirection mDirection;
   nsBoundingMetrics  mBoundingMetrics;
   nsStyleContext*    mStyleContext;
   nsGlyphTable*      mGlyphTable;
   nsGlyphCode        mGlyph;
   // mFamily is non-empty when the family for the current size is different
@@ -242,24 +210,16 @@ private:
                   nsStretchDirection&      aStretchDirection,
                   const nsBoundingMetrics& aContainerSize,
                   nsBoundingMetrics&       aDesiredStretchSize,
                   PRUint32                 aStretchHint,
                   float           aMaxSize = NS_MATHML_OPERATOR_SIZE_INFINITY,
                   bool            aMaxSizeIsAbsolute = false);
 
   nsresult
-  ComposeChildren(nsPresContext*       aPresContext,
-                  nsRenderingContext& aRenderingContext,
-                  nsGlyphTable*        aGlyphTable,
-                  nscoord              aTargetSize,
-                  nsBoundingMetrics&   aCompositeSize,
-                  PRUint32             aStretchHint);
-
-  nsresult
   PaintVertically(nsPresContext*       aPresContext,
                   nsRenderingContext& aRenderingContext,
                   nsFont&              aFont,
                   nsStyleContext*      aStyleContext,
                   nsGlyphTable*        aGlyphTable,
                   nsRect&              aRect);
 
   nsresult