MathML internals - embellished operators, getBase() accessor functions
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 17 Feb 2012 23:33:05 +0000 (23:33 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 17 Feb 2012 23:33:05 +0000 (23:33 +0000)
https://bugs.webkit.org/show_bug.cgi?id=78617

Patch by David Barton <dbarton@mathscribe.com> on 2012-02-17
Reviewed by Eric Seidel.

Define functions that return an unembellished "base", by omitting
subscripts/superscripts, underscripts/overscripts, or denominators. This is needed in
subsequent patches both for correct operator stretching and simple code factoring.

No new tests.

* rendering/mathml/RenderMathMLBlock.h:
(WebCore):
(RenderMathMLBlock):
(WebCore::RenderMathMLBlock::unembellishedOperator):
* rendering/mathml/RenderMathMLFraction.cpp:
(WebCore::RenderMathMLFraction::unembellishedOperator):
(WebCore):
* rendering/mathml/RenderMathMLFraction.h:
(RenderMathMLFraction):
* rendering/mathml/RenderMathMLOperator.h:
(WebCore::RenderMathMLOperator::unembellishedOperator):
* rendering/mathml/RenderMathMLSubSup.cpp:
(WebCore::RenderMathMLSubSup::base):
(WebCore):
(WebCore::RenderMathMLSubSup::unembellishedOperator):
(WebCore::RenderMathMLSubSup::stretchToHeight):
    - renamed a variable for clarity, especially in later patches
(WebCore::RenderMathMLSubSup::layout):
    - renamed a variable for clarity, especially in later patches
* rendering/mathml/RenderMathMLSubSup.h:
(RenderMathMLSubSup):
* rendering/mathml/RenderMathMLUnderOver.cpp:
(WebCore::RenderMathMLUnderOver::base):
(WebCore):
(WebCore::RenderMathMLUnderOver::unembellishedOperator):
(WebCore::RenderMathMLUnderOver::stretchToHeight):
* rendering/mathml/RenderMathMLUnderOver.h:
(RenderMathMLUnderOver):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@108136 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/rendering/mathml/RenderMathMLBlock.h
Source/WebCore/rendering/mathml/RenderMathMLFraction.cpp
Source/WebCore/rendering/mathml/RenderMathMLFraction.h
Source/WebCore/rendering/mathml/RenderMathMLOperator.h
Source/WebCore/rendering/mathml/RenderMathMLSubSup.cpp
Source/WebCore/rendering/mathml/RenderMathMLSubSup.h
Source/WebCore/rendering/mathml/RenderMathMLUnderOver.cpp
Source/WebCore/rendering/mathml/RenderMathMLUnderOver.h

index 9ebcd42..48c500b 100644 (file)
@@ -1,3 +1,45 @@
+2012-02-17  David Barton  <dbarton@mathscribe.com>
+
+        MathML internals - embellished operators, getBase() accessor functions
+        https://bugs.webkit.org/show_bug.cgi?id=78617
+
+        Reviewed by Eric Seidel.
+
+        Define functions that return an unembellished "base", by omitting
+        subscripts/superscripts, underscripts/overscripts, or denominators. This is needed in
+        subsequent patches both for correct operator stretching and simple code factoring.
+
+        No new tests.
+
+        * rendering/mathml/RenderMathMLBlock.h:
+        (WebCore):
+        (RenderMathMLBlock):
+        (WebCore::RenderMathMLBlock::unembellishedOperator):
+        * rendering/mathml/RenderMathMLFraction.cpp:
+        (WebCore::RenderMathMLFraction::unembellishedOperator):
+        (WebCore):
+        * rendering/mathml/RenderMathMLFraction.h:
+        (RenderMathMLFraction):
+        * rendering/mathml/RenderMathMLOperator.h:
+        (WebCore::RenderMathMLOperator::unembellishedOperator):
+        * rendering/mathml/RenderMathMLSubSup.cpp:
+        (WebCore::RenderMathMLSubSup::base):
+        (WebCore):
+        (WebCore::RenderMathMLSubSup::unembellishedOperator):
+        (WebCore::RenderMathMLSubSup::stretchToHeight):
+            - renamed a variable for clarity, especially in later patches
+        (WebCore::RenderMathMLSubSup::layout):
+            - renamed a variable for clarity, especially in later patches
+        * rendering/mathml/RenderMathMLSubSup.h:
+        (RenderMathMLSubSup):
+        * rendering/mathml/RenderMathMLUnderOver.cpp:
+        (WebCore::RenderMathMLUnderOver::base):
+        (WebCore):
+        (WebCore::RenderMathMLUnderOver::unembellishedOperator):
+        (WebCore::RenderMathMLUnderOver::stretchToHeight):
+        * rendering/mathml/RenderMathMLUnderOver.h:
+        (RenderMathMLUnderOver):
+
 2012-02-17  No'am Rosenthal  <noam.rosenthal@nokia.com>
 
         [Qt][WK2] Allow opaque tiles
index e556459..2a7c28b 100644 (file)
@@ -34,6 +34,8 @@
 
 namespace WebCore {
     
+class RenderMathMLOperator;
+
 class RenderMathMLBlock : public RenderBlock {
 public:
     RenderMathMLBlock(Node* container);
@@ -43,6 +45,15 @@ public:
     virtual bool isRenderMathMLOperator() const { return false; }
     virtual bool isRenderMathMLRow() const { return false; }
     virtual bool isRenderMathMLMath() const { return false; }
+    
+    // MathML defines an "embellished operator" as roughly an <mo> that may have subscripts,
+    // superscripts, underscripts, overscripts, or a denominator (as in d/dx, where "d" is some
+    // differential operator). The padding, precedence, and stretchiness of the base <mo> should
+    // apply to the embellished operator as a whole. unembellishedOperator() checks for being an
+    // embellished operator, and omits any embellishments.
+    // FIXME: We don't yet handle all the cases in the MathML spec. See
+    // https://bugs.webkit.org/show_bug.cgi?id=78617.
+    virtual RenderMathMLOperator* unembellishedOperator() { return 0; }
     virtual bool hasBase() const { return false; }
     virtual int nonOperatorHeight() const;
     virtual void stretchToHeight(int height);
index d30161a..dd59bb9 100644 (file)
@@ -119,6 +119,17 @@ void RenderMathMLFraction::addChild(RenderObject* child, RenderObject* beforeChi
     updateFromElement();
 }
 
+RenderMathMLOperator* RenderMathMLFraction::unembellishedOperator()
+{
+    RenderObject* numeratorWrapper = firstChild();
+    if (!numeratorWrapper)
+        return 0;
+    RenderObject* numerator = numeratorWrapper->firstChild();
+    if (!numerator || !numerator->isRenderMathMLBlock())
+        return 0;
+    return toRenderMathMLBlock(numerator)->unembellishedOperator();
+}
+
 void RenderMathMLFraction::layout()
 {
     updateFromElement();
index 946dbcb..4756583 100644 (file)
@@ -38,10 +38,14 @@ public:
     RenderMathMLFraction(Element*);
     virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0);
     virtual void updateFromElement();
+    
+    virtual RenderMathMLOperator* unembellishedOperator();
+    
     virtual LayoutUnit baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const; 
     virtual void paint(PaintInfo&, const LayoutPoint&);
 protected:
     virtual void layout();
+    
 private:
     virtual const char* renderName() const { return "RenderMathMLFraction"; }
     
index cf4b318..4270872 100644 (file)
@@ -38,6 +38,7 @@ public:
     RenderMathMLOperator(Element*);
     RenderMathMLOperator(Node*, UChar operatorChar);
     virtual bool isRenderMathMLOperator() const { return true; }
+    virtual RenderMathMLOperator* unembellishedOperator() { return this; }
     virtual void stretchToHeight(int pixelHeight);
     virtual void updateFromElement(); 
     virtual bool isChildAllowed(RenderObject*, RenderStyle*) const;
index 7249e60..bc45d24 100644 (file)
@@ -54,6 +54,17 @@ RenderMathMLSubSup::RenderMathMLSubSup(Element* element)
     }
 }
 
+RenderBoxModelObject* RenderMathMLSubSup::base() const
+{
+    RenderObject* baseWrapper = firstChild();
+    if (!baseWrapper)
+        return 0;
+    RenderObject* base = baseWrapper->firstChild();
+    if (!base || !base->isBoxModelObject())
+        return 0;
+    return toRenderBoxModelObject(base);
+}
+
 void RenderMathMLSubSup::addChild(RenderObject* child, RenderObject* beforeChild)
 {
     // Note: The RenderMathMLBlock only allows element children to be added.
@@ -104,14 +115,22 @@ void RenderMathMLSubSup::addChild(RenderObject* child, RenderObject* beforeChild
     }
 }
 
+RenderMathMLOperator* RenderMathMLSubSup::unembellishedOperator()
+{
+    RenderBoxModelObject* base = this->base();
+    if (!base || !base->isRenderMathMLBlock())
+        return 0;
+    return toRenderMathMLBlock(base)->unembellishedOperator();
+}
+
 void RenderMathMLSubSup::stretchToHeight(int height)
 {
-    RenderObject* base = firstChild();
-    if (!base || !base->firstChild())
+    RenderObject* baseWrapper = firstChild();
+    if (!baseWrapper || !baseWrapper->firstChild())
         return;
     
-    if (base->firstChild() && base->firstChild()->isRenderMathMLBlock()) {
-        RenderMathMLBlock* block = toRenderMathMLBlock(base->firstChild());
+    if (baseWrapper->firstChild() && baseWrapper->firstChild()->isRenderMathMLBlock()) {
+        RenderMathMLBlock* block = toRenderMathMLBlock(baseWrapper->firstChild());
         block->stretchToHeight(static_cast<int>(gSubSupStretch * height));
         
         // Adjust the script placement after we stretch
@@ -153,9 +172,9 @@ void RenderMathMLSubSup::layout()
     RenderBlock::layout();
     
     if (m_kind == SubSup) {
-        if (RenderObject* base = firstChild()) {
+        if (RenderObject* baseWrapper = firstChild()) {
             LayoutUnit maxHeight = 0;
-            RenderObject* current = base->firstChild();
+            RenderObject* current = baseWrapper->firstChild();
             while (current) {
                 LayoutUnit height = getBoxModelObjectHeight(current);
                 if (height > maxHeight)
@@ -165,8 +184,8 @@ void RenderMathMLSubSup::layout()
             LayoutUnit heightDiff = m_scripts ? (m_scripts->offsetHeight() - maxHeight) / 2 : zeroLayoutUnit;
             if (heightDiff < 0) 
                 heightDiff = 0;
-            base->style()->setPaddingTop(Length(heightDiff, Fixed));
-            base->setNeedsLayout(true);
+            baseWrapper->style()->setPaddingTop(Length(heightDiff, Fixed));
+            baseWrapper->setNeedsLayout(true);
         }
         setNeedsLayout(true);
         RenderBlock::layout();
index 110ee8a..64f13f1 100644 (file)
@@ -36,6 +36,8 @@ class RenderMathMLSubSup : public RenderMathMLBlock {
 public:
     RenderMathMLSubSup(Element*);
     virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0);
+    
+    virtual RenderMathMLOperator* unembellishedOperator();
     virtual bool hasBase() const { return true; }
     virtual int nonOperatorHeight() const;
     virtual void stretchToHeight(int pixelHeight);
@@ -47,6 +49,10 @@ protected:
 private:
     virtual const char* renderName() const { return "RenderMathMLSubSup"; }
 
+    // Omit our subscript and/or superscript. This may return 0 for a non-MathML base (which
+    // won't occur in valid MathML).
+    RenderBoxModelObject* base() const;
+    
     enum SubSupType { Sub, Sup, SubSup };
     SubSupType m_kind;
     RenderBlock* m_scripts;
index 1ba1eda..7bafe55 100644 (file)
@@ -52,6 +52,19 @@ RenderMathMLUnderOver::RenderMathMLUnderOver(Element* element)
     }
 }
 
+RenderBoxModelObject* RenderMathMLUnderOver::base() const
+{
+    RenderObject* baseWrapper = firstChild();
+    if ((m_kind == Over || m_kind == UnderOver) && baseWrapper)
+        baseWrapper = baseWrapper->nextSibling();
+    if (!baseWrapper)
+        return 0;
+    RenderObject* base = baseWrapper->firstChild();
+    if (!base || !base->isBoxModelObject())
+        return 0;
+    return toRenderBoxModelObject(base);
+}
+
 void RenderMathMLUnderOver::addChild(RenderObject* child, RenderObject* beforeChild)
 {    
     RenderMathMLBlock* row = new (renderArena()) RenderMathMLBlock(node());
@@ -106,6 +119,14 @@ void RenderMathMLUnderOver::addChild(RenderObject* child, RenderObject* beforeCh
     row->addChild(child);    
 }
 
+RenderMathMLOperator* RenderMathMLUnderOver::unembellishedOperator()
+{
+    RenderBoxModelObject* base = this->base();
+    if (!base || !base->isRenderMathMLBlock())
+        return 0;
+    return toRenderMathMLBlock(base)->unembellishedOperator();
+}
+
 inline int getOffsetHeight(RenderObject* obj) 
 {
     if (obj->isBoxModelObject()) {
@@ -118,21 +139,7 @@ inline int getOffsetHeight(RenderObject* obj)
 
 void RenderMathMLUnderOver::stretchToHeight(int height)
 {
-
-    RenderObject* base = firstChild();
-    if (!base)
-        return;
-        
-    // For over or underover, the base is the sibling of the first child
-    if (m_kind != Under) 
-        base = base->nextSibling();
-        
-    if (!base)
-        return;
-        
-    // use the child of the row which is the actual base
-    base = base->firstChild();
-    
+    RenderBoxModelObject* base = this->base();
     if (base && base->isRenderMathMLBlock()) {
         RenderMathMLBlock* block = toRenderMathMLBlock(base);
         block->stretchToHeight(height);
index 9768fbb..67810da 100644 (file)
@@ -36,14 +36,21 @@ class RenderMathMLUnderOver : public RenderMathMLBlock {
 public:
     RenderMathMLUnderOver(Element*);
     virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0);
+    
+    virtual RenderMathMLOperator* unembellishedOperator();
     virtual void layout();
     virtual bool hasBase() const { return true; }
     virtual int nonOperatorHeight() const;
     virtual LayoutUnit baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const;
     virtual void stretchToHeight(int pixelHeight);
+    
 private:
     virtual const char* renderName() const { return "RenderMathMLUnderOver"; }
 
+    // Omit our underscript and/or overscript. This may return 0 for a non-MathML base (which
+    // won't occur in valid MathML).
+    RenderBoxModelObject* base() const;
+    
     enum UnderOverType { Under, Over, UnderOver };
     UnderOverType m_kind;
 };