Changeset 203896 in webkit


Ignore:
Timestamp:
Jul 29, 2016 12:21:57 AM (8 years ago)
Author:
fred.wang@free.fr
Message:

Parse the operator text on the MathMLOperatorElement class.
https://bugs.webkit.org/show_bug.cgi?id=160241

Patch by Frederic Wang <fwang@igalia.com> on 2016-07-29
Reviewed by Darin Adler.

The text of the MathML operators is important to determine form or dictionary properties and
hence provide default values when no explicit attributes are privided. Since that text only
depends on the MathML DOM content, it makes sense to move its parsing into
MathMLOperatorElement. Anonymous operators created by the mfenced elements still need to be
handled specially and this will be true for all the operator properties that can just be
determined in MathMLOperatorElement. Hence in a follow-up patch we will introduce a class
to move all the code specific to mfenced in a class derived from RenderMathMLOperator while
we continue to move the corresponding code for non-anonymous into MathMLOperatorElement.

No new tests, behavior is unchanged.

  • mathml/MathMLOperatorElement.cpp: Include header for hyphenMinus/minusSign characters.

(WebCore::MathMLOperatorElement::parseOperatorText): Move that code from rebuildTokenContent
(WebCore::MathMLOperatorElement::operatorText): Helper function to get the cached text.
(WebCore::MathMLOperatorElement::childrenChanged): Make the cached text dirty.

  • mathml/MathMLOperatorElement.h: Update defitions and add a member for the operator text.
  • mathml/MathMLTextElement.h: Make childrenChanged overridable.
  • rendering/mathml/RenderMathMLOperator.cpp:

(WebCore::RenderMathMLOperator::element): Helper function to cast to a MathMLOperatorElement.
(WebCore::RenderMathMLOperator::textContent): Helper function to call
MathMLOperatorElement::operatorText or fallback to m_textContent for anonymous operators.
m_textContent and this special case can be moved into a derived class later.
(WebCore::RenderMathMLOperator::setOperatorProperties): Call textContent().
(WebCore::RenderMathMLOperator::computePreferredLogicalWidths): Ditto.
(WebCore::RenderMathMLOperator::rebuildTokenContent): Remove the string parameter and the
parsing of the operator text.
(WebCore::RenderMathMLOperator::updateTokenContent): Call textContent(). The special function
for anonymous operators also parses the text content but this could be moved into a derived
class later.
(WebCore::RenderMathMLOperator::shouldAllowStretching): Call textContent().
(WebCore::RenderMathMLOperator::useMathOperator): Ditto.
(WebCore::RenderMathMLOperator::RenderMathMLOperator): No need to initialize m_textContent
as it is not used anymore for non-anonymous renderers.

  • rendering/mathml/RenderMathMLOperator.h: Update definitions and call textContent().
Location:
trunk/Source/WebCore
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r203858 r203896  
     12016-07-29  Frederic Wang  <fwang@igalia.com>
     2
     3        Parse the operator text on the MathMLOperatorElement class.
     4        https://bugs.webkit.org/show_bug.cgi?id=160241
     5
     6        Reviewed by Darin Adler.
     7
     8        The text of the MathML operators is important to determine form or dictionary properties and
     9        hence provide default values when no explicit attributes are privided. Since that text only
     10        depends on the MathML DOM content, it makes sense to move its parsing into
     11        MathMLOperatorElement. Anonymous operators created by the mfenced elements still need to be
     12        handled specially and this will be true for all the operator properties that can just be
     13        determined in MathMLOperatorElement. Hence in a follow-up patch we will introduce a class
     14        to move all the code specific to mfenced in a class derived from RenderMathMLOperator while
     15        we continue to move the corresponding code for non-anonymous into MathMLOperatorElement.
     16
     17        No new tests, behavior is unchanged.
     18
     19        * mathml/MathMLOperatorElement.cpp: Include header for hyphenMinus/minusSign characters.
     20        (WebCore::MathMLOperatorElement::parseOperatorText): Move that code from rebuildTokenContent
     21        (WebCore::MathMLOperatorElement::operatorText): Helper function to get the cached text.
     22        (WebCore::MathMLOperatorElement::childrenChanged): Make the cached text dirty.
     23        * mathml/MathMLOperatorElement.h: Update defitions and add a member for the operator text.
     24        * mathml/MathMLTextElement.h: Make childrenChanged overridable.
     25        * rendering/mathml/RenderMathMLOperator.cpp:
     26        (WebCore::RenderMathMLOperator::element): Helper function to cast to a MathMLOperatorElement.
     27        (WebCore::RenderMathMLOperator::textContent): Helper function to call
     28        MathMLOperatorElement::operatorText or fallback to m_textContent for anonymous operators.
     29        m_textContent and this special case can be moved into a derived class later.
     30        (WebCore::RenderMathMLOperator::setOperatorProperties): Call textContent().
     31        (WebCore::RenderMathMLOperator::computePreferredLogicalWidths): Ditto.
     32        (WebCore::RenderMathMLOperator::rebuildTokenContent): Remove the string parameter and the
     33        parsing of the operator text.
     34        (WebCore::RenderMathMLOperator::updateTokenContent): Call textContent(). The special function
     35        for anonymous operators also parses the text content but this could be moved into a derived
     36        class later.
     37        (WebCore::RenderMathMLOperator::shouldAllowStretching): Call textContent().
     38        (WebCore::RenderMathMLOperator::useMathOperator): Ditto.
     39        (WebCore::RenderMathMLOperator::RenderMathMLOperator): No need to initialize m_textContent
     40        as it is not used anymore for non-anonymous renderers.
     41        * rendering/mathml/RenderMathMLOperator.h: Update definitions and call textContent().
     42
    1432016-07-28  Youenn Fablet  <youenn@apple.com>
    244
  • trunk/Source/WebCore/mathml/MathMLOperatorElement.cpp

    r203688 r203896  
    3131
    3232#include "RenderMathMLOperator.h"
     33#include <wtf/unicode/CharacterNames.h>
    3334
    3435namespace WebCore {
     
    4445{
    4546    return adoptRef(*new MathMLOperatorElement(tagName, document));
     47}
     48
     49UChar MathMLOperatorElement::parseOperatorText(const String& string)
     50{
     51    // We collapse the whitespace and replace the hyphens by minus signs.
     52    AtomicString textContent = string.stripWhiteSpace().simplifyWhiteSpace().replace(hyphenMinus, minusSign).impl();
     53
     54    // We verify whether the operator text can be represented by a single UChar.
     55    // FIXME: This is a really inefficient way to extract a character from a string (https://webkit.org/b/160241#c7).
     56    // FIXME: This does not handle surrogate pairs (https://webkit.org/b/122296).
     57    // FIXME: This does not handle <mo> operators with multiple characters (https://webkit.org/b/124828).
     58    return textContent.length() == 1 ? textContent[0] : 0;
     59}
     60
     61UChar MathMLOperatorElement::operatorText()
     62{
     63    if (m_operatorText)
     64        return m_operatorText.value();
     65
     66    m_operatorText = Optional<UChar>(parseOperatorText(textContent()));
     67    return m_operatorText.value();
     68}
     69
     70void MathMLOperatorElement::childrenChanged(const ChildChange& change)
     71{
     72    m_operatorText = Optional<UChar>();
     73    MathMLTextElement::childrenChanged(change);
    4674}
    4775
  • trunk/Source/WebCore/mathml/MathMLOperatorElement.h

    r203688 r203896  
    3434public:
    3535    static Ref<MathMLOperatorElement> create(const QualifiedName& tagName, Document&);
     36    static UChar parseOperatorText(const String&);
     37    UChar operatorText();
     38
    3639private:
    3740    MathMLOperatorElement(const QualifiedName& tagName, Document&);
    3841    RenderPtr<RenderElement> createElementRenderer(RenderStyle&&, const RenderTreePosition&) final;
     42    void childrenChanged(const ChildChange&) final;
    3943    void parseAttribute(const QualifiedName&, const AtomicString&) final;
     44
     45    Optional<UChar> m_operatorText;
    4046};
    4147
  • trunk/Source/WebCore/mathml/MathMLTextElement.h

    r203688 r203896  
    4040protected:
    4141    MathMLTextElement(const QualifiedName& tagName, Document&);
     42    void childrenChanged(const ChildChange&) override;
    4243    void parseAttribute(const QualifiedName&, const AtomicString&) override;
    4344
     
    4647    bool childShouldCreateRenderer(const Node&) const final;
    4748
    48     void childrenChanged(const ChildChange&) final;
    4949    void didAttachRenderers() final;
    5050
  • trunk/Source/WebCore/rendering/mathml/RenderMathMLOperator.cpp

    r203688 r203896  
    5252    , m_stretchHeightAboveBaseline(0)
    5353    , m_stretchDepthBelowBaseline(0)
    54     , m_textContent(0)
    5554    , m_isVertical(true)
    5655{
     
    7069}
    7170
     71MathMLOperatorElement& RenderMathMLOperator::element() const
     72{
     73    return static_cast<MathMLOperatorElement&>(nodeForNonAnonymous());
     74}
     75
     76UChar RenderMathMLOperator::textContent() const
     77{
     78    return isAnonymous() ? m_textContent : element().operatorText();
     79}
     80
    7281void RenderMathMLOperator::setOperatorFlagFromAttribute(MathMLOperatorDictionary::Flag flag, const QualifiedName& name)
    7382{
     
    102111{
    103112    // We determine the stretch direction (default is vertical).
    104     m_isVertical = MathMLOperatorDictionary::isVertical(m_textContent);
     113    m_isVertical = MathMLOperatorDictionary::isVertical(textContent());
    105114
    106115    // We determine the form of the operator.
     
    138147    m_maxSize = intMaxForLayoutUnit; // This sets maxsize to "infinity".
    139148
    140     if (m_textContent) {
     149    if (textContent()) {
    141150        // Then we try to find the default values from the operator dictionary.
    142         if (const MathMLOperatorDictionary::Entry* entry = MathMLOperatorDictionary::getEntry(m_textContent, m_operatorForm))
     151        if (const MathMLOperatorDictionary::Entry* entry = MathMLOperatorDictionary::getEntry(textContent(), m_operatorForm))
    143152            setOperatorPropertiesFromOpDictEntry(entry);
    144153        else if (!explicitForm) {
    145154            // If we did not find the desired operator form and if it was not set explicitely, we use the first one in the following order: Infix, Prefix, Postfix.
    146155            // This is to handle bad MathML markup without explicit <mrow> delimiters like "<mo>(</mo><mi>a</mi><mo>)</mo><mo>(</mo><mi>b</mi><mo>)</mo>" where the inner parenthesis should not be considered infix.
    147             if (const MathMLOperatorDictionary::Entry* entry = MathMLOperatorDictionary::getEntry(m_textContent)) {
     156            if (const MathMLOperatorDictionary::Entry* entry = MathMLOperatorDictionary::getEntry(textContent())) {
    148157                m_operatorForm = static_cast<MathMLOperatorDictionary::Form>(entry->form); // We override the form previously determined.
    149158                setOperatorPropertiesFromOpDictEntry(entry);
     
    247256        if (isInvisibleOperator()) {
    248257            // In some fonts, glyphs for invisible operators have nonzero width. Consequently, we subtract that width here to avoid wide gaps.
    249             GlyphData data = style().fontCascade().glyphDataForCharacter(m_textContent, false);
     258            GlyphData data = style().fontCascade().glyphDataForCharacter(textContent(), false);
    250259            float glyphWidth = data.font ? data.font->widthForGlyph(data.glyph) : 0;
    251260            ASSERT(glyphWidth <= preferredWidth);
     
    293302}
    294303
    295 void RenderMathMLOperator::rebuildTokenContent(const String& operatorString)
    296 {
    297     // We collapse the whitespace and replace the hyphens by minus signs.
    298     AtomicString textContent = operatorString.stripWhiteSpace().simplifyWhiteSpace().replace(hyphenMinus, minusSign).impl();
    299 
    300     // We verify whether the operator text can be represented by a single UChar.
    301     // FIXME: This does not handle surrogate pairs (https://bugs.webkit.org/show_bug.cgi?id=122296).
    302     // FIXME: This does not handle <mo> operators with multiple characters (https://bugs.webkit.org/show_bug.cgi?id=124828).
    303     m_textContent = textContent.length() == 1 ? textContent[0] : 0;
     304void RenderMathMLOperator::rebuildTokenContent()
     305{
    304306    setOperatorProperties();
    305307
     
    312314        else
    313315            type = m_isVertical ? MathOperator::Type::VerticalOperator : MathOperator::Type::HorizontalOperator;
    314         m_mathOperator.setOperator(style(), m_textContent, type);
     316        m_mathOperator.setOperator(style(), textContent(), type);
    315317    }
    316318
     
    321323{
    322324    ASSERT(isAnonymous());
    323     rebuildTokenContent(operatorString);
     325    m_textContent = MathMLOperatorElement::parseOperatorText(operatorString);
     326    rebuildTokenContent();
    324327}
    325328
     
    328331    ASSERT(!isAnonymous());
    329332    RenderMathMLToken::updateTokenContent();
    330     rebuildTokenContent(element().textContent());
     333    rebuildTokenContent();
    331334}
    332335
     
    344347bool RenderMathMLOperator::shouldAllowStretching() const
    345348{
    346     return m_textContent && (hasOperatorFlag(MathMLOperatorDictionary::Stretchy) || isLargeOperatorInDisplayStyle());
     349    return textContent() && (hasOperatorFlag(MathMLOperatorDictionary::Stretchy) || isLargeOperatorInDisplayStyle());
    347350}
    348351
     
    353356    // 2) The minus sign, since it can be obtained from a hyphen in the DOM.
    354357    // 3) The anonymous operators created by mfenced, since they do not have text content in the DOM.
    355     return shouldAllowStretching() || m_textContent == minusSign || isAnonymous();
     358    return shouldAllowStretching() || textContent() == minusSign || isAnonymous();
    356359}
    357360
  • trunk/Source/WebCore/rendering/mathml/RenderMathMLOperator.h

    r203688 r203896  
    4141    RenderMathMLOperator(MathMLOperatorElement&, RenderStyle&&);
    4242    RenderMathMLOperator(Document&, RenderStyle&&, const String& operatorString, MathMLOperatorDictionary::Form, unsigned short flags = 0);
     43    MathMLOperatorElement& element() const;
    4344
    4445    void stretchTo(LayoutUnit heightAboveBaseline, LayoutUnit depthBelowBaseline);
     
    5758    void updateOperatorProperties();
    5859    void updateFromElement() final;
    59     UChar textContent() const { return m_textContent; }
     60    UChar textContent() const;
    6061
    6162private:
     
    7374    bool isRenderMathMLOperator() const final { return true; }
    7475    // The following operators are invisible: U+2061 FUNCTION APPLICATION, U+2062 INVISIBLE TIMES, U+2063 INVISIBLE SEPARATOR, U+2064 INVISIBLE PLUS.
    75     bool isInvisibleOperator() const { return 0x2061 <= m_textContent && m_textContent <= 0x2064; }
     76    bool isInvisibleOperator() { return 0x2061 <= textContent() && textContent() <= 0x2064; }
    7677
    7778    Optional<int> firstLineBaseline() const final;
    7879    RenderMathMLOperator* unembellishedOperator() final { return this; }
    79     void rebuildTokenContent(const String& operatorString);
     80    void rebuildTokenContent();
    8081
    8182    bool shouldAllowStretching() const;
Note: See TracChangeset for help on using the changeset viewer.