Changeset 199980 in webkit


Ignore:
Timestamp:
Apr 25, 2016 2:46:31 AM (8 years ago)
Author:
fred.wang@free.fr
Message:

Refactor RenderMathMLMenclose.
https://bugs.webkit.org/show_bug.cgi?id=155019

Patch by Frederic Wang <fwang@igalia.com> on 2016-04-25
Reviewed by Sergio Villar Senin.

Source/WebCore:

Tests: mathml/presentation/menclose-notation-equivalence.html

mathml/presentation/menclose-notation-values.html

We rewrite RenderMathMLMenclose so that layout functions correctly override the
behavior of RenderMathMLRow. We try and rely on the draft of the MathML in HTML5
implementation note, to make easier to get consistency with other rendering engines
in the future. All notations are now drawn with GraphicContext functions instead of
mixing them with CSS style. To save memory space, the list of known notations are
now saved on a short integer using bit masks instead of a vector of string names.
Finally, we remove support for the radical notation so that we no longer need to
create an anonymous RenderMathMLRoot.

  • mathml/MathMLMencloseElement.cpp: Remove code for some special notations and just

reimplement parsing of the notation attribute.
(WebCore::MathMLMencloseElement::MathMLMencloseElement): By default, the notation is longdiv.
(WebCore::MathMLMencloseElement::parseAttribute): By default, the list of notation is empty.
If there is no notation attribute, the default value longdiv is used.
Otherwise, we parse the notation attribute and add each notation, using some equivalences
for box, actuarial and madruwb.
(WebCore::MathMLMencloseElement::isPresentationAttribute): Deleted. No need to define
specific style for some notation.
(WebCore::MathMLMencloseElement::finishParsingChildren): Deleted. No need to add an
anonymous square root.
(WebCore::MathMLMencloseElement::collectStyleForPresentationAttribute): Deleted. No need to
define specific style for some notation.
(WebCore::MathMLMencloseElement::longDivLeftPadding): Deleted. RenderMathMLMenclose uses an
arbitrary size instead of measure a glyph.

  • mathml/MathMLMencloseElement.h: Define simple bit mask for each notation, add a short

integer to store the list of notations together with helper functions. Remove old code.

  • rendering/mathml/RenderMathMLMenclose.cpp: Rewrite RenderMathMLMenclose so that layout

functions correctly override the behavior of RenderMathMLRow.
(WebCore::RenderMathMLMenclose::RenderMathMLMenclose): Init m_ascent to 0.
(WebCore::RenderMathMLMenclose::ruleThickness): For now, we use the fallback value used by
for other bars. We may refine that in the future.
(WebCore::RenderMathMLMenclose::getSpaceAroundContent): Helper function to retrieve the
space to add around the content, depending on the notations specified. Note that for
notation circle, this spacing depends on the content size.
(WebCore::RenderMathMLMenclose::computePreferredLogicalWidths): Reimplement this function.
This is just adding left/right spacing around the content.
(WebCore::RenderMathMLMenclose::layoutBlock): Reimplement this function. We do the normal
RenderMathMLRow layout, adjust spacing and child position and
calculate m_ascent and m_contentRect.
(WebCore::RenderMathMLMenclose::firstLineBaseline): Implement this function.
We just return m_ascent.
(WebCore::drawLine): Helper function to draw a line using strokePath.
(WebCore::RenderMathMLMenclose::paint): We reimplement this function to draw
all notations using GraphicContext.
(WebCore::RenderMathMLMenclose::addChild): Deleted. No need to manage anonymous renderers.
(WebCore::RenderMathMLMenclose::updateLogicalHeight): Deleted. Height is now calculated
in layoutBlock.
(WebCore::RenderMathMLMenclose::checkNotationalValuesValidity): Deleted.

  • rendering/mathml/RenderMathMLMenclose.h: Update member definitions.
  • rendering/mathml/RenderMathMLRoot.cpp: We no longer need anonymous roots.

(WebCore::RenderMathMLRoot::RenderMathMLRoot): Deleted.

  • rendering/mathml/RenderMathMLRoot.h: We no longer need anonymous roots.
  • rendering/mathml/RenderMathMLRow.cpp: Allow to get the exact metrics of the chid row,

for use in RenderMathMLRoot.
(WebCore::RenderMathMLRow::computeLineVerticalStretch): rename parameters.
(WebCore::RenderMathMLRow::layoutRowItems): Set parameters to the final ascent, descent and
logical width of the chid row. Set the temporary logical width for RenderMathMenclose before
laying the children out.
(WebCore::RenderMathMLRow::layoutBlock): Rename parameters ; add a dummy logicalWidth
parameter.

  • rendering/mathml/RenderMathMLRow.h: Make some functions accessible or overridable by

RenderMathMLRoot. Make layoutRowItems return the final ascent, descent and logical width
after the chid row is laid out.

  • rendering/mathml/RenderMathMLSquareRoot.cpp: We no longer need anonymous roots.

(WebCore::RenderMathMLSquareRoot::RenderMathMLSquareRoot): Deleted.
(WebCore::RenderMathMLSquareRoot::createAnonymousWithParentRenderer): Deleted.

  • rendering/mathml/RenderMathMLSquareRoot.h: We no longer need anonymous roots.

LayoutTests:

  • mathml/presentation/menclose-notation-attribute-set1.html: Removed.

This is replaced with menclose-notation-values.

  • mathml/presentation/menclose-notation-attribute-set1-expected.txt: Removed.

This is replaced with menclose-notation-values.

  • mathml/presentation/menclose-notation-attribute-set2-expected-mismatch.html: Removed.

This is replaced with menclose-notation-values.

  • mathml/presentation/menclose-notation-attribute-set2.html: Removed.

This is replaced with menclose-notation-values.

  • mathml/presentation/menclose-notation-values.html: Added.

This test verifies the rendering of various menclose notations.

  • mathml/presentation/menclose-notation-equivalence.html: Added.

This test verifies some equivalence for the notation attribute value.

  • mathml/presentation/menclose-notation-equivalence-expected.html: Added.
  • mathml/presentation/menclose-notation-radical.html: Update the test now that support for

the radical notation is removed.

  • mathml/presentation/menclose-notation-radical-expected.html: ditto.
  • platform/gtk/mathml/presentation/menclose-notation-default-longdiv-expected.png: Update

reference due to small changes in longdiv implementation.

  • platform/gtk/mathml/presentation/menclose-notation-default-longdiv-expected.txt: ditto.
  • platform/mac/mathml/presentation/menclose-notation-default-longdiv-expected.png: ditto.
  • platform/mac/mathml/presentation/menclose-notation-default-longdiv-expected.txt: ditto.
  • platform/ios-simulator/mathml/presentation/menclose-notation-default-longdiv-expected.txt: ditto
  • platform/gtk/mathml/presentation/menclose-notation-values-expected.png: Added.
  • platform/gtk/mathml/presentation/menclose-notation-values-expected.txt: Added.
  • platform/mac/mathml/presentation/menclose-notation-values-expected.png: Added.
  • platform/mac/mathml/presentation/menclose-notation-values-expected.txt: Added.
  • platform/ios-simulator/mathml/presentation/menclose-notation-values-expected.txt: Added.
Location:
trunk
Files:
8 added
4 deleted
19 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r199975 r199980  
     12016-04-25  Frederic Wang  <fwang@igalia.com>
     2
     3        Refactor RenderMathMLMenclose.
     4        https://bugs.webkit.org/show_bug.cgi?id=155019
     5
     6        Reviewed by Sergio Villar Senin.
     7
     8        * mathml/presentation/menclose-notation-attribute-set1.html: Removed.
     9        This is replaced with menclose-notation-values.
     10        * mathml/presentation/menclose-notation-attribute-set1-expected.txt: Removed.
     11        This is replaced with menclose-notation-values.
     12        * mathml/presentation/menclose-notation-attribute-set2-expected-mismatch.html: Removed.
     13        This is replaced with menclose-notation-values.
     14        * mathml/presentation/menclose-notation-attribute-set2.html: Removed.
     15        This is replaced with menclose-notation-values.
     16        * mathml/presentation/menclose-notation-values.html: Added.
     17        This test verifies the rendering of various menclose notations.
     18        * mathml/presentation/menclose-notation-equivalence.html: Added.
     19        This test verifies some equivalence for the notation attribute value.
     20        * mathml/presentation/menclose-notation-equivalence-expected.html: Added.
     21        * mathml/presentation/menclose-notation-radical.html: Update the test now that support for
     22        the radical notation is removed.
     23        * mathml/presentation/menclose-notation-radical-expected.html: ditto.
     24        * platform/gtk/mathml/presentation/menclose-notation-default-longdiv-expected.png: Update
     25        reference due to small changes in longdiv implementation.
     26        * platform/gtk/mathml/presentation/menclose-notation-default-longdiv-expected.txt: ditto.
     27        * platform/mac/mathml/presentation/menclose-notation-default-longdiv-expected.png: ditto.
     28        * platform/mac/mathml/presentation/menclose-notation-default-longdiv-expected.txt: ditto.
     29        * platform/ios-simulator/mathml/presentation/menclose-notation-default-longdiv-expected.txt: ditto
     30        * platform/gtk/mathml/presentation/menclose-notation-values-expected.png: Added.
     31        * platform/gtk/mathml/presentation/menclose-notation-values-expected.txt: Added.
     32        * platform/mac/mathml/presentation/menclose-notation-values-expected.png: Added.
     33        * platform/mac/mathml/presentation/menclose-notation-values-expected.txt: Added.
     34        * platform/ios-simulator/mathml/presentation/menclose-notation-values-expected.txt: Added.
     35
    1362016-04-24  Gyuyoung Kim  <gyuyoung.kim@webkit.org>
    237
  • trunk/LayoutTests/mathml/presentation/menclose-notation-radical-expected.html

    r167539 r199980  
    66    <body>
    77        <p>
    8             <math><mrow><msqrt><mspace width="100px" height="50px" mathbackground="red"/></msqrt></mrow></math>
     8            <math><mrow><mrow><mspace width="100px" height="50px" mathbackground="red"/></mrow></mrow></math>
    99        </p>
    1010    </body>
  • trunk/LayoutTests/mathml/presentation/menclose-notation-radical.html

    r167539 r199980  
    55    </head>
    66    <body>
     7        <!-- We removed support for the radical notation, so this menclose element should render the same as an mrow element. -->
    78        <p>
    89            <math><mrow><menclose notation="radical"><mspace width="100px" height="50px" mathbackground="red"/></menclose></mrow></math>
  • trunk/LayoutTests/platform/gtk/mathml/presentation/menclose-notation-default-longdiv-expected.txt

    r170418 r199980  
    11layer at (0,0) size 800x600
    22  RenderView at (0,0) size 800x600
    3 layer at (0,0) size 800x91
    4   RenderBlock {HTML} at (0,0) size 800x91
    5     RenderBody {BODY} at (8,16) size 784x59
    6       RenderBlock {P} at (0,0) size 784x59
    7         RenderMathMLMath {math} at (0,0) size 102x56 [padding: 0 1 0 1]
    8           RenderMathMLRow {mrow} at (1,0) size 100x56
    9             RenderMathMLMenclose {menclose} at (0,0) size 100x56 [padding: 6 0 0 6]
    10               RenderMathMLSpace {mspace} at (6,6) size 100x50 [bgcolor=#FF0000]
     3layer at (0,0) size 800x89
     4  RenderBlock {HTML} at (0,0) size 800x89
     5    RenderBody {BODY} at (8,16) size 784x57
     6      RenderBlock {P} at (0,0) size 784x57
     7        RenderMathMLMath {math} at (0,0) size 114x58 [padding: 0 1 0 1]
     8          RenderMathMLRow {mrow} at (1,0) size 112x58
     9            RenderMathMLMenclose {menclose} at (0,0) size 112x58
     10              RenderMathMLSpace {mspace} at (7,3) size 101x51 [bgcolor=#FF0000]
    1111        RenderText {#text} at (0,0) size 0x0
  • trunk/LayoutTests/platform/ios-simulator/mathml/presentation/menclose-notation-default-longdiv-expected.txt

    r174527 r199980  
    11layer at (0,0) size 800x600
    22  RenderView at (0,0) size 800x600
    3 layer at (0,0) size 800x93
    4   RenderBlock {HTML} at (0,0) size 800x93
    5     RenderBody {BODY} at (8,16) size 784x61
    6       RenderBlock {P} at (0,0) size 784x61
    7         RenderMathMLMath {math} at (0,0) size 102x56 [padding: 0 1 0 1]
    8           RenderMathMLRow {mrow} at (1,0) size 100x56
    9             RenderMathMLMenclose {menclose} at (0,0) size 100x56 [padding: 6 0 0 5]
    10               RenderMathMLSpace {mspace} at (5,6) size 100x50 [bgcolor=#FF0000]
     3layer at (0,0) size 800x91
     4  RenderBlock {HTML} at (0,0) size 800x91
     5    RenderBody {BODY} at (8,16) size 784x59
     6      RenderBlock {P} at (0,0) size 784x59
     7        RenderMathMLMath {math} at (0,0) size 114x58 [padding: 0 1 0 1]
     8          RenderMathMLRow {mrow} at (1,0) size 112x58
     9            RenderMathMLMenclose {menclose} at (0,0) size 112x58
     10              RenderMathMLSpace {mspace} at (7,3) size 101x51 [bgcolor=#FF0000]
    1111        RenderText {#text} at (0,0) size 0x0
  • trunk/LayoutTests/platform/mac/mathml/presentation/menclose-notation-default-longdiv-expected.txt

    r167539 r199980  
    11layer at (0,0) size 800x600
    22  RenderView at (0,0) size 800x600
    3 layer at (0,0) size 800x92
    4   RenderBlock {HTML} at (0,0) size 800x92
    5     RenderBody {BODY} at (8,16) size 784x60
    6       RenderBlock {P} at (0,0) size 784x60
    7         RenderMathMLMath {math} at (0,0) size 102x56 [padding: 0 1 0 1]
    8           RenderMathMLRow {mrow} at (1,0) size 100x56
    9             RenderMathMLMenclose {menclose} at (0,0) size 100x56 [padding: 6 0 0 5]
    10               RenderMathMLSpace {mspace} at (5,6) size 100x50 [bgcolor=#FF0000]
     3layer at (0,0) size 800x90
     4  RenderBlock {HTML} at (0,0) size 800x90
     5    RenderBody {BODY} at (8,16) size 784x58
     6      RenderBlock {P} at (0,0) size 784x58
     7        RenderMathMLMath {math} at (0,0) size 114x58 [padding: 0 1 0 1]
     8          RenderMathMLRow {mrow} at (1,0) size 112x58
     9            RenderMathMLMenclose {menclose} at (0,0) size 112x58
     10              RenderMathMLSpace {mspace} at (7,3) size 101x51 [bgcolor=#FF0000]
    1111        RenderText {#text} at (0,0) size 0x0
  • trunk/Source/WebCore/ChangeLog

    r199978 r199980  
     12016-04-25  Frederic Wang  <fwang@igalia.com>
     2
     3        Refactor RenderMathMLMenclose.
     4        https://bugs.webkit.org/show_bug.cgi?id=155019
     5
     6        Reviewed by Sergio Villar Senin.
     7
     8        Tests: mathml/presentation/menclose-notation-equivalence.html
     9               mathml/presentation/menclose-notation-values.html
     10
     11        We rewrite RenderMathMLMenclose so that layout functions correctly override the
     12        behavior of RenderMathMLRow. We try and rely on the draft  of the MathML in HTML5
     13        implementation note, to make easier to get consistency with other rendering engines
     14        in the future. All notations are now drawn with GraphicContext functions instead of
     15        mixing them with CSS style. To save memory space, the list of known notations are
     16        now saved on a short integer using bit masks instead of a vector of string names.
     17        Finally, we remove support for the radical notation so that we no longer need to
     18        create an anonymous RenderMathMLRoot.
     19
     20        * mathml/MathMLMencloseElement.cpp: Remove code for some special notations and just
     21        reimplement parsing of the notation attribute.
     22        (WebCore::MathMLMencloseElement::MathMLMencloseElement): By default, the notation is longdiv.
     23        (WebCore::MathMLMencloseElement::parseAttribute): By default, the list of notation is empty.
     24        If there is no notation attribute, the default value longdiv is used.
     25        Otherwise, we parse the notation attribute and add each notation, using some equivalences
     26        for box, actuarial and madruwb.
     27        (WebCore::MathMLMencloseElement::isPresentationAttribute): Deleted. No need to define
     28        specific style for some notation.
     29        (WebCore::MathMLMencloseElement::finishParsingChildren): Deleted. No need to add an
     30        anonymous square root.
     31        (WebCore::MathMLMencloseElement::collectStyleForPresentationAttribute): Deleted. No need to
     32        define specific style for some notation.
     33        (WebCore::MathMLMencloseElement::longDivLeftPadding): Deleted. RenderMathMLMenclose uses an
     34        arbitrary size instead of measure a glyph.
     35        * mathml/MathMLMencloseElement.h: Define simple bit mask for each notation, add a short
     36        integer to store the list of notations together with helper functions. Remove old code.
     37        * rendering/mathml/RenderMathMLMenclose.cpp: Rewrite RenderMathMLMenclose so that layout
     38        functions correctly override the behavior of RenderMathMLRow.
     39        (WebCore::RenderMathMLMenclose::RenderMathMLMenclose): Init m_ascent to 0.
     40        (WebCore::RenderMathMLMenclose::ruleThickness): For now, we use the fallback value used by
     41        for other bars. We may refine that in the future.
     42        (WebCore::RenderMathMLMenclose::getSpaceAroundContent): Helper function to retrieve the
     43        space to add around the content, depending on the notations specified. Note that for
     44        notation circle, this spacing depends on the content size.
     45        (WebCore::RenderMathMLMenclose::computePreferredLogicalWidths): Reimplement this function.
     46        This is just adding left/right spacing around the content.
     47        (WebCore::RenderMathMLMenclose::layoutBlock): Reimplement this function. We do the normal
     48        RenderMathMLRow layout, adjust spacing and child position and
     49        calculate m_ascent and m_contentRect.
     50        (WebCore::RenderMathMLMenclose::firstLineBaseline): Implement this function.
     51        We just return m_ascent.
     52        (WebCore::drawLine): Helper function to draw a line using strokePath.
     53        (WebCore::RenderMathMLMenclose::paint): We reimplement this function to draw
     54        all notations using GraphicContext.
     55        (WebCore::RenderMathMLMenclose::addChild): Deleted. No need to manage anonymous renderers.
     56        (WebCore::RenderMathMLMenclose::updateLogicalHeight): Deleted. Height is now calculated
     57        in layoutBlock.
     58        (WebCore::RenderMathMLMenclose::checkNotationalValuesValidity): Deleted.
     59        * rendering/mathml/RenderMathMLMenclose.h: Update member definitions.
     60        * rendering/mathml/RenderMathMLRoot.cpp: We no longer need anonymous roots.
     61        (WebCore::RenderMathMLRoot::RenderMathMLRoot): Deleted.
     62        * rendering/mathml/RenderMathMLRoot.h: We no longer need anonymous roots.
     63        * rendering/mathml/RenderMathMLRow.cpp: Allow to get the exact metrics of the chid row,
     64        for use in RenderMathMLRoot.
     65        (WebCore::RenderMathMLRow::computeLineVerticalStretch): rename parameters.
     66        (WebCore::RenderMathMLRow::layoutRowItems): Set parameters to the final ascent, descent and
     67        logical width of the chid row. Set the temporary logical width for RenderMathMenclose before
     68        laying the children out.
     69        (WebCore::RenderMathMLRow::layoutBlock): Rename parameters ; add a dummy logicalWidth
     70        parameter.
     71        * rendering/mathml/RenderMathMLRow.h: Make some functions accessible or overridable by
     72        RenderMathMLRoot. Make layoutRowItems return the final ascent, descent and logical width
     73        after the chid row is laid out.
     74        * rendering/mathml/RenderMathMLSquareRoot.cpp: We no longer need anonymous roots.
     75        (WebCore::RenderMathMLSquareRoot::RenderMathMLSquareRoot): Deleted.
     76        (WebCore::RenderMathMLSquareRoot::createAnonymousWithParentRenderer): Deleted.
     77        * rendering/mathml/RenderMathMLSquareRoot.h: We no longer need anonymous roots.
     78
    1792016-04-25  Frederic Wang  <fwang@igalia.com>
    280
  • trunk/Source/WebCore/mathml/MathMLMencloseElement.cpp

    r199964 r199980  
    11/*
    22 * Copyright (C) 2014 Gurpreet Kaur (k.gurpreet@samsung.com). All rights reserved.
     3 * Copyright (C) 2016 Igalia S.L.
    34 *
    45 * Redistribution and use in source and binary forms, with or without
     
    3031
    3132#include "MathMLNames.h"
    32 #include "RenderElement.h"
    3333#include "RenderMathMLMenclose.h"
    34 #include "RenderObject.h"
    35 #include "TextRun.h"
    36 #include <wtf/Ref.h>
    37 #include <wtf/text/StringBuilder.h>
    38 
    3934
    4035namespace WebCore {
     
    4237MathMLMencloseElement::MathMLMencloseElement(const QualifiedName& tagName, Document& document)
    4338    : MathMLInlineContainerElement(tagName, document)
    44     , m_isRadicalValue(false)
    4539{
     40    // By default we draw a longdiv.
     41    clearNotations();
     42    addNotation(LongDiv);
    4643}
    4744
     
    5653}
    5754
    58 bool MathMLMencloseElement::isPresentationAttribute(const QualifiedName& name) const
     55void MathMLMencloseElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
    5956{
    60     if (name == MathMLNames::notationAttr)
    61         return true;
    62     return MathMLElement::isPresentationAttribute(name);
    63 }
     57    if (name == MathMLNames::notationAttr) {
     58        clearNotations();
     59        if (!hasAttribute(name)) {
     60            addNotation(LongDiv); // default value is longdiv
     61            return;
     62        }
     63        Vector<String> notationsList;
     64        String(value).split(' ', notationsList);
     65        for (auto& notation : notationsList) {
     66            if (notation == "longdiv") {
     67                addNotation(LongDiv);
     68            } else if (notation == "roundedbox") {
     69                addNotation(RoundedBox);
     70            } else if (notation == "circle") {
     71                addNotation(Circle);
     72            } else if (notation == "left") {
     73                addNotation(Left);
     74            } else if (notation == "right") {
     75                addNotation(Right);
     76            } else if (notation == "top") {
     77                addNotation(Top);
     78            } else if (notation == "bottom") {
     79                addNotation(Bottom);
     80            } else if (notation == "updiagonalstrike") {
     81                addNotation(UpDiagonalStrike);
     82            } else if (notation == "downdiagonalstrike") {
     83                addNotation(DownDiagonalStrike);
     84            } else if (notation == "verticalstrike") {
     85                addNotation(VerticalStrike);
     86            } else if (notation == "horizontalstrike") {
     87                addNotation(HorizontalStrike);
     88            } else if (notation == "updiagonalarrow") {
     89                addNotation(UpDiagonalArrow);
     90            } else if (notation == "phasorangle") {
     91                addNotation(PhasorAngle);
     92            } else if (notation == "box") {
     93                addNotation(Left);
     94                addNotation(Right);
     95                addNotation(Top);
     96                addNotation(Bottom);
     97            } else if (notation == "actuarial") {
     98                addNotation(Right);
     99                addNotation(Top);
     100            } else if (notation == "madruwb") {
     101                addNotation(Right);
     102                addNotation(Bottom);
     103            }
     104        }
     105        return;
     106    }
    64107
    65 void MathMLMencloseElement::finishParsingChildren()
    66 {
    67     MathMLInlineContainerElement::finishParsingChildren();
    68     // When notation value is a radical and menclose does not have any child
    69     // then we add anonymous squareroot child to menclose so that square root
    70     // symbol can be rendered.
    71     if (m_isRadicalValue && !firstElementChild())
    72         renderer()->addChild(nullptr, nullptr);
    73 }
    74 
    75 void MathMLMencloseElement::collectStyleForPresentationAttribute(const QualifiedName& name, const AtomicString& value, MutableStyleProperties& style)
    76 {
    77     String val = value;
    78     if (val.isEmpty())
    79         return;
    80     if (name == MathMLNames::notationAttr) {
    81         val.split(' ', m_notationValues);
    82         size_t notationValueSize = m_notationValues.size();
    83         for (size_t i = 0; i < notationValueSize; i++) {
    84             if (m_notationValues[i] == "top" || m_notationValues[i] == "longdiv") {
    85                 if (m_notationValues[i] == "longdiv")
    86                     addPropertyToPresentationAttributeStyle(style, CSSPropertyPaddingLeft, longDivLeftPadding());
    87                 addPropertyToPresentationAttributeStyle(style, CSSPropertyBorderTopStyle, "solid");
    88                 addPropertyToPresentationAttributeStyle(style, CSSPropertyBorderTopWidth, "thin");
    89                 addPropertyToPresentationAttributeStyle(style, CSSPropertyPaddingTop, ".3ex");
    90             } else if (m_notationValues[i] == "bottom") {
    91                 addPropertyToPresentationAttributeStyle(style, CSSPropertyBorderBottomStyle, "solid");
    92                 addPropertyToPresentationAttributeStyle(style, CSSPropertyBorderBottomWidth, "thin");
    93                 addPropertyToPresentationAttributeStyle(style, CSSPropertyPaddingBottom, ".3ex");
    94             } else if (m_notationValues[i] == "left") {
    95                 addPropertyToPresentationAttributeStyle(style, CSSPropertyBorderLeftStyle, "solid");
    96                 addPropertyToPresentationAttributeStyle(style, CSSPropertyBorderLeftWidth, "thin");
    97                 addPropertyToPresentationAttributeStyle(style, CSSPropertyPaddingLeft, ".3ex");
    98             } else if (m_notationValues[i] == "right") {
    99                 addPropertyToPresentationAttributeStyle(style, CSSPropertyBorderRightStyle, "solid");
    100                 addPropertyToPresentationAttributeStyle(style, CSSPropertyBorderRightWidth, "thin");
    101                 addPropertyToPresentationAttributeStyle(style, CSSPropertyPaddingRight, ".3ex");
    102             } else if (m_notationValues[i] == "box" || m_notationValues[i] == "roundedbox") {
    103                 addPropertyToPresentationAttributeStyle(style, CSSPropertyBorderStyle, "solid");
    104                 addPropertyToPresentationAttributeStyle(style, CSSPropertyBorderWidth, "thin");
    105                 addPropertyToPresentationAttributeStyle(style, CSSPropertyPadding, ".3ex");
    106                 if (m_notationValues[i] == "roundedbox")
    107                     addPropertyToPresentationAttributeStyle(style, CSSPropertyBorderRadius, ASCIILiteral("5px"));
    108             } else if (m_notationValues[i] == "actuarial" || m_notationValues[i] == "madruwb") {
    109                 addPropertyToPresentationAttributeStyle(style, CSSPropertyBorderRightStyle, "solid");
    110                 addPropertyToPresentationAttributeStyle(style, CSSPropertyBorderRightWidth, "thin");
    111                 addPropertyToPresentationAttributeStyle(style, CSSPropertyPaddingRight, ".3ex");
    112                 if (m_notationValues[i] == "actuarial") {
    113                     addPropertyToPresentationAttributeStyle(style, CSSPropertyBorderTopStyle, "solid");
    114                     addPropertyToPresentationAttributeStyle(style, CSSPropertyBorderTopWidth, "thin");
    115                     addPropertyToPresentationAttributeStyle(style, CSSPropertyPaddingTop, ".3ex");
    116                 } else if (m_notationValues[i] == "madruwb") {
    117                     addPropertyToPresentationAttributeStyle(style, CSSPropertyBorderBottomStyle, "solid");
    118                     addPropertyToPresentationAttributeStyle(style, CSSPropertyBorderBottomWidth, "thin");
    119                     addPropertyToPresentationAttributeStyle(style, CSSPropertyPaddingBottom, ".3ex");
    120                 }
    121             } else if (m_notationValues[i] == "radical")
    122                 m_isRadicalValue = true;
    123         }
    124     } else
    125         MathMLInlineContainerElement::collectStyleForPresentationAttribute(name, value, style);
    126 }
    127 
    128 
    129 String MathMLMencloseElement::longDivLeftPadding() const
    130 {
    131     StringBuilder padding;
    132     String closingBrace(")", String::ConstructFromLiteral);
    133     TextRun run(closingBrace);
    134     Node* node = parentNode();
    135     if (node && node->renderer()) {
    136         const FontCascade& font = node->renderer()->style().fontCascade();
    137         padding.appendNumber(font.width(run));
    138         padding.appendLiteral("px");
    139     }
    140     return padding.toString();
     108    MathMLInlineContainerElement::parseAttribute(name, value);
    141109}
    142110
  • trunk/Source/WebCore/mathml/MathMLMencloseElement.h

    r199964 r199980  
    11/*
    22 * Copyright (C) 2014 Gurpreet Kaur (k.gurpreet@samsung.com). All rights reserved.
     3 * Copyright (C) 2016 Igalia S.L.
    34 *
    45 * Redistribution and use in source and binary forms, with or without
     
    2829
    2930#if ENABLE(MATHML)
     31#include "Element.h"
    3032#include "MathMLInlineContainerElement.h"
    3133
     
    3537public:
    3638    static Ref<MathMLMencloseElement> create(const QualifiedName& tagName, Document&);
    37     const Vector<String>& notationValues() const { return m_notationValues; }
    38     bool isRadical() const { return m_isRadicalValue; }
    39     String longDivLeftPadding() const;
    40     bool isDefaultLongDiv() const { return !hasAttribute(MathMLNames::notationAttr); }
     39    void parseAttribute(const QualifiedName&, const AtomicString&) final;
     40
     41    enum MencloseNotationFlag {
     42        LongDiv = 1 << 1,
     43        RoundedBox = 1 << 2,
     44        Circle = 1 << 3,
     45        Left = 1 << 4,
     46        Right = 1 << 5,
     47        Top = 1 << 6,
     48        Bottom = 1 << 7,
     49        UpDiagonalStrike = 1 << 8,
     50        DownDiagonalStrike = 1 << 9,
     51        VerticalStrike = 1 << 10,
     52        HorizontalStrike = 1 << 11,
     53        UpDiagonalArrow = 1 << 12, // FIXME: updiagonalarrow is not implemented. See http://wkb.ug/127466
     54        PhasorAngle = 1 << 13 // FIXME: phasorangle is not implemented. See http://wkb.ug/127466
     55        // We do not implement the Radical notation. Authors should instead use the <msqrt> element.
     56    };
     57    bool hasNotation(MencloseNotationFlag notationFlag) const { return m_notationFlags & notationFlag; }
    4158
    4259private:
    4360    MathMLMencloseElement(const QualifiedName&, Document&);
    44     RenderPtr<RenderElement> createElementRenderer(std::unique_ptr<RenderStyle>, const RenderTreePosition&) override;
    45     bool isPresentationAttribute(const QualifiedName&) const override;
    46     void collectStyleForPresentationAttribute(const QualifiedName&, const AtomicString&, MutableStyleProperties&) override;
    47     void finishParsingChildren() override;
    48 
    49     Vector<String> m_notationValues;
    50     bool m_isRadicalValue;
     61    RenderPtr<RenderElement> createElementRenderer(std::unique_ptr<RenderStyle>, const RenderTreePosition&) final;
     62    void clearNotations() { m_notationFlags = 0; }
     63    void addNotation(MencloseNotationFlag notationFlag) { m_notationFlags |= notationFlag; }
     64    unsigned short m_notationFlags;
    5165};
    5266
  • trunk/Source/WebCore/rendering/mathml/RenderMathMLMenclose.cpp

    r199964 r199980  
    11/*
    22 * Copyright (C) 2014 Gurpreet Kaur (k.gurpreet@samsung.com). All rights reserved.
     3 * Copyright (C) 2016 Igalia S.L.
    34 *
    45 * Redistribution and use in source and binary forms, with or without
     
    3031
    3132#include "GraphicsContext.h"
    32 #include "MathMLMencloseElement.h"
     33#include "MathMLNames.h"
    3334#include "PaintInfo.h"
    34 #include "RenderMathMLSquareRoot.h"
    3535#include <wtf/MathExtras.h>
    3636
     
    3838
    3939using namespace MathMLNames;
     40
     41// The MathML in HTML5 implementation note suggests drawing the left part of longdiv with a parenthesis.
     42// For now, we use a Bezier curve and this somewhat arbitrary value.
     43const unsigned short longDivLeftSpace = 10;
    4044
    4145RenderMathMLMenclose::RenderMathMLMenclose(Element& element, std::unique_ptr<RenderStyle> style)
    4246    : RenderMathMLRow(element, WTFMove(style))
    43 {
    44 }
    45 
    46 void RenderMathMLMenclose::addChild(RenderObject* newChild, RenderObject* beforeChild)
    47 {
    48     MathMLMencloseElement* menclose = downcast<MathMLMencloseElement>(element());
    49     // Allow an anonymous RenderMathMLSquareRoot to handle drawing the radical
    50     // notation, rather than duplicating the code needed to paint a root.
    51     if (!firstChild() && menclose->isRadical())       
    52         RenderMathMLBlock::addChild(RenderMathMLSquareRoot::createAnonymousWithParentRenderer(*this).leakPtr());
    53    
    54     if (newChild) {
    55         if (firstChild() && menclose->isRadical())
    56             downcast<RenderElement>(*firstChild()).addChild(newChild, beforeChild && beforeChild->parent() == firstChild() ? beforeChild : nullptr);
    57         else
    58             RenderMathMLBlock::addChild(newChild, beforeChild);
    59     }
     47    , m_ascent(0)
     48{
     49}
     50
     51// This arbitrary thickness value is used for the parameter \xi_8 from the MathML in HTML5 implementation note.
     52// For now, we take:
     53// - OverbarVerticalGap = UnderbarVerticalGap = 3\xi_8
     54// - OverbarRuleThickness = UnderbarRuleThickness = \xi_8
     55// - OverbarExtraAscender = UnderbarExtraAscender = \xi_8
     56// FIXME: OverBar and UnderBar parameters should be read from the MATH tables.
     57// See https://bugs.webkit.org/show_bug.cgi?id=122297
     58LayoutUnit RenderMathMLMenclose::ruleThickness() const
     59{
     60    return 0.05f * style().fontCascade().size();
     61}
     62
     63void RenderMathMLMenclose::getSpaceAroundContent(LayoutUnit contentWidth, LayoutUnit contentHeight, LayoutUnit& leftSpace, LayoutUnit& rightSpace, LayoutUnit& topSpace, LayoutUnit& bottomSpace) const
     64{
     65    leftSpace = rightSpace = topSpace = bottomSpace = 0;
     66
     67    LayoutUnit thickness = ruleThickness();
     68
     69    // In the MathML in HTML5 implementation note, the "left" notation is described as follows:
     70    // - left side is 3\xi_8 padding + \xi_8 border + \xi_8 margin = 5\xi_8
     71    // - top space is Overbar Vertical Gap + Overbar Rule Thickness = 3\xi_8 + \xi_8 = 4\xi_8
     72    // - bottom space is Underbar Vertical Gap + Underbar Rule Thickness = 3\xi_8 + \xi_8 = 4\xi_8
     73    // The "right" notation is symmetric.
     74    if (hasNotation(MathMLMencloseElement::Left))
     75        leftSpace = std::max(leftSpace, 5 * thickness);
     76    if (hasNotation(MathMLMencloseElement::Right))
     77        rightSpace = std::max(rightSpace, 5 * thickness);
     78    if (hasNotation(MathMLMencloseElement::Left) || hasNotation(MathMLMencloseElement::Right)) {
     79        LayoutUnit extraSpace = 4 * thickness;
     80        topSpace = std::max(topSpace, extraSpace);
     81        bottomSpace = std::max(bottomSpace, extraSpace);
     82    }
     83
     84    // In the MathML in HTML5 implementation note, the "top" notation is described as follows:
     85    // - left and right space are 4\xi_8
     86    // - top side is Vertical Gap + Rule Thickness + Extra Ascender = 3\xi_8 + \xi_8 + \xi_8 = 5\xi_8
     87    // The "bottom" notation is symmetric.
     88    if (hasNotation(MathMLMencloseElement::Top))
     89        topSpace = std::max(topSpace, 5 * thickness);
     90    if (hasNotation(MathMLMencloseElement::Bottom))
     91        bottomSpace = std::max(bottomSpace, 5 * thickness);
     92    if (hasNotation(MathMLMencloseElement::Top) || hasNotation(MathMLMencloseElement::Bottom)) {
     93        LayoutUnit extraSpace = 4 * thickness;
     94        leftSpace = std::max(leftSpace, extraSpace);
     95        rightSpace = std::max(rightSpace, extraSpace);
     96    }
     97
     98    // For longdiv, we use our own rules for now:
     99    // - top space is like "top" notation
     100    // - bottom space is like "bottom" notation
     101    // - right space is like "right" notation
     102    // - left space is longDivLeftSpace * \xi_8
     103    if (hasNotation(MathMLMencloseElement::LongDiv)) {
     104        topSpace = std::max(topSpace, 5 * thickness);
     105        bottomSpace = std::max(bottomSpace, 5 * thickness);
     106        leftSpace = std::max(leftSpace, longDivLeftSpace * thickness);
     107        rightSpace = std::max(rightSpace, 4 * thickness);
     108    }
     109
     110    // In the MathML in HTML5 implementation note, the "rounded" notation is described as follows:
     111    // - top/bottom/left/right side have 3\xi_8 padding + \xi_8 border + \xi_8 margin = 5\xi_8
     112    if (hasNotation(MathMLMencloseElement::RoundedBox)) {
     113        LayoutUnit extraSpace = 5 * thickness;
     114        leftSpace = std::max(leftSpace, extraSpace);
     115        rightSpace = std::max(rightSpace, extraSpace);
     116        topSpace = std::max(topSpace, extraSpace);
     117        bottomSpace = std::max(bottomSpace, extraSpace);
     118    }
     119
     120    // In the MathML in HTML5 implementation note, the "rounded" notation is described as follows:
     121    // - top/bottom/left/right spaces are \xi_8/2
     122    if (hasNotation(MathMLMencloseElement::UpDiagonalStrike) || hasNotation(MathMLMencloseElement::DownDiagonalStrike)) {
     123        LayoutUnit extraSpace = thickness / 2;
     124        leftSpace = std::max(leftSpace, extraSpace);
     125        rightSpace = std::max(rightSpace, extraSpace);
     126        topSpace = std::max(topSpace, extraSpace);
     127        bottomSpace = std::max(bottomSpace, extraSpace);
     128    }
     129
     130    // In the MathML in HTML5 implementation note, the "circle" notation is described as follows:
     131    // - We draw the ellipse of axes the axes of symmetry of this ink box
     132    // - The radii of the ellipse are \sqrt{2}contentWidth/2 and \sqrt{2}contentHeight/2
     133    // - The thickness of the ellipse is \xi_8
     134    // - We add extra margin of \xi_8
     135    // Then for example the top space is \sqrt{2}contentHeight/2 - contentHeight/2 + \xi_8/2 + \xi_8.
     136    if (hasNotation(MathMLMencloseElement::Circle)) {
     137        LayoutUnit extraSpace = (contentWidth * (sqrtOfTwoFloat - 1) + 3 * thickness) / 2;
     138        leftSpace = std::max(leftSpace, extraSpace);
     139        rightSpace = std::max(rightSpace, extraSpace);
     140        extraSpace = (contentHeight * (sqrtOfTwoFloat - 1) + 3 * thickness) / 2;
     141        topSpace = std::max(topSpace, extraSpace);
     142        bottomSpace = std::max(bottomSpace, extraSpace);
     143    }
     144
     145    // In the MathML in HTML5 implementation note, the "vertical" and "horizontal" notations do not add space around the content.
    60146}
    61147
     
    64150    ASSERT(preferredLogicalWidthsDirty());
    65151
    66     RenderMathMLBlock::computePreferredLogicalWidths();
    67     const int paddingTop = 6;
    68 
    69     MathMLMencloseElement* menclose = downcast<MathMLMencloseElement>(element());
    70     const Vector<String>& notationValues = menclose->notationValues();
    71     size_t notationalValueSize = notationValues.size();
    72     for (size_t i = 0; i < notationalValueSize; i++) {
    73         if (notationValues[i] == "circle") {
    74             m_minPreferredLogicalWidth = minPreferredLogicalWidth() * sqrtOfTwoFloat;
    75             m_maxPreferredLogicalWidth = maxPreferredLogicalWidth() * sqrtOfTwoFloat;
    76         }
    77     }
    78 
    79     if (menclose->isDefaultLongDiv()) {
    80         style().setPaddingTop(Length(paddingTop, Fixed));
    81         style().setPaddingLeft(Length(menclose->longDivLeftPadding().toInt(), Fixed));
    82     }
     152    RenderMathMLRow::computePreferredLogicalWidths();
     153
     154    LayoutUnit preferredWidth = m_maxPreferredLogicalWidth;
     155    LayoutUnit leftSpace, rightSpace, dummy;
     156    getSpaceAroundContent(preferredWidth, 0, leftSpace, rightSpace, dummy, dummy);
     157    m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = leftSpace + preferredWidth + rightSpace;
     158
    83159    setPreferredLogicalWidthsDirty(false);
    84160}
    85161
    86 void RenderMathMLMenclose::updateLogicalHeight()
    87 {
    88     MathMLMencloseElement* menclose = downcast<MathMLMencloseElement>(element());
    89     const Vector<String>& notationValues = menclose->notationValues();
    90     size_t notationalValueSize = notationValues.size();
    91     for (size_t i = 0; i < notationalValueSize; i++)
    92         if (notationValues[i] == "circle")
    93             setLogicalHeight(logicalHeight() * sqrtOfTwoFloat);
     162void RenderMathMLMenclose::layoutBlock(bool relayoutChildren, LayoutUnit)
     163{
     164    ASSERT(needsLayout());
     165
     166    if (!relayoutChildren && simplifiedLayout())
     167        return;
     168
     169    LayoutUnit contentAscent = 0;
     170    LayoutUnit contentDescent = 0;
     171    RenderMathMLRow::computeLineVerticalStretch(contentAscent, contentDescent);
     172    RenderMathMLRow::layoutRowItems(contentAscent, contentDescent);
     173    LayoutUnit contentWidth = logicalWidth();
     174
     175    LayoutUnit leftSpace, rightSpace, topSpace, bottomSpace;
     176    getSpaceAroundContent(contentWidth, contentAscent + contentDescent, leftSpace, rightSpace, topSpace, bottomSpace);
     177    setLogicalWidth(leftSpace + contentWidth + rightSpace);
     178    m_ascent = topSpace + contentAscent;
     179    LayoutUnit descent = contentDescent + bottomSpace;
     180    LayoutPoint contentLocation(leftSpace, m_ascent - contentAscent);
     181    for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox())
     182        child->setLocation(child->location() + contentLocation);
     183
     184    setLogicalHeight(m_ascent + descent);
     185
     186    m_contentRect = LayoutRect(leftSpace, topSpace, contentWidth, contentAscent + contentDescent);
     187
     188    clearNeedsLayout();
     189}
     190
     191Optional<int> RenderMathMLMenclose::firstLineBaseline() const
     192{
     193    return Optional<int>(static_cast<int>(lroundf(m_ascent)));
     194}
     195
     196// GraphicsContext::drawLine does not seem appropriate to draw menclose lines.
     197// To avoid unexpected behaviors and inconsistency with other notations, we just use strokePath.
     198static void drawLine(PaintInfo& info, const LayoutUnit& xStart, const LayoutUnit& yStart, const LayoutUnit& xEnd, const LayoutUnit& yEnd)
     199{
     200    Path line;
     201    line.moveTo(LayoutPoint(xStart, yStart));
     202    line.addLineTo(LayoutPoint(xEnd, yEnd));
     203    info.context().strokePath(line);
    94204}
    95205
    96206void RenderMathMLMenclose::paint(PaintInfo& info, const LayoutPoint& paintOffset)
    97207{
    98     RenderMathMLBlock::paint(info, paintOffset);
     208    RenderMathMLRow::paint(info, paintOffset);
    99209
    100210    if (info.context().paintingDisabled() || info.phase != PaintPhaseForeground || style().visibility() != VISIBLE)
    101211        return;
    102    
    103     MathMLMencloseElement* menclose = downcast<MathMLMencloseElement>(element());
    104     const Vector<String>& notationValues = menclose->notationValues();
    105     size_t notationalValueSize = notationValues.size();
    106     bool isDefaultLongDiv = menclose->isDefaultLongDiv();
    107     if ((notationalValueSize && checkNotationalValuesValidity(notationValues)) || isDefaultLongDiv) {
    108         IntRect rect = absoluteBoundingBoxRect();
    109         int left = rect.x();
    110         int top = rect.y();
    111         int boxWidth = rect.width();
    112         int boxHeight = rect.height();
    113         int halfboxWidth = rect.width() / 2;
    114         int halfboxHeight = rect.height() / 2;
    115 
    116         GraphicsContextStateSaver stateSaver(info.context());
    117         info.context().setStrokeThickness(1);
    118         info.context().setStrokeStyle(SolidStroke);
    119         info.context().setStrokeColor(style().visitedDependentColor(CSSPropertyColor));
    120         // TODO add support for notation value updiagonalarrow https://bugs.webkit.org/show_bug.cgi?id=127466
    121         for (size_t i = 0; i < notationalValueSize; i++) {
    122             if (notationValues[i] == "updiagonalstrike")
    123                 info.context().drawLine(IntPoint(left, top + boxHeight), IntPoint(left + boxWidth, top));
    124             else if (notationValues[i] == "downdiagonalstrike")
    125                 info.context().drawLine(IntPoint(left, top), IntPoint(left + boxWidth, top + boxHeight));
    126             else if (notationValues[i] == "verticalstrike")
    127                 info.context().drawLine(IntPoint(left + halfboxWidth, top), IntPoint(left + halfboxWidth, top + boxHeight));
    128             else if (notationValues[i] == "horizontalstrike")
    129                 info.context().drawLine(IntPoint(left, top + halfboxHeight), IntPoint(left + boxWidth, top + halfboxHeight));
    130             else if (notationValues[i] == "circle") {
    131                 info.context().setFillColor(Color::transparent);
    132                 info.context().drawEllipse(rect);
    133             } else if (notationValues[i] == "longdiv")
    134                 isDefaultLongDiv = true;
    135         }
    136         if (isDefaultLongDiv) {
    137             Path root;
    138             int midxPoint = 0;
    139             root.moveTo(FloatPoint(left, top));
    140             int childLeft = firstChild() ? firstChild()->absoluteBoundingBoxRect().x() : 0;
    141             if (childLeft)
    142                 midxPoint= childLeft - left;
    143             else
    144                 midxPoint = style().paddingLeft().value();
    145             root.addBezierCurveTo(FloatPoint(left, top), FloatPoint(left + midxPoint, top + halfboxHeight), FloatPoint(left, top + boxHeight));
    146             info.context().strokePath(root);
    147             if (isDefaultLongDiv)
    148                 info.context().drawLine(IntPoint(left, top), IntPoint(left + boxWidth + midxPoint, top));
    149         }
    150     }
    151 }
    152 
    153 bool RenderMathMLMenclose::checkNotationalValuesValidity(const Vector<String>& attr) const
    154 {
    155     size_t attrSize = attr.size();
    156     for (size_t i = 0; i < attrSize; i++) {
    157         if (attr[i] == "updiagonalstrike" || attr[i] == "downdiagonalstrike" || attr[i] == "horizontalstrike" || attr[i] == "verticalstrike"
    158             || attr[i] == "circle" || attr[i] == "longdiv")
    159             return true;
    160     }
    161     return false;
     212
     213    LayoutUnit thickness = ruleThickness();
     214    GraphicsContextStateSaver stateSaver(info.context());
     215
     216    info.context().setStrokeThickness(thickness);
     217    info.context().setStrokeStyle(SolidStroke);
     218    info.context().setStrokeColor(style().visitedDependentColor(CSSPropertyColor));
     219    info.context().setFillColor(Color::transparent);
     220    info.applyTransform(AffineTransform().translate(paintOffset + location()));
     221
     222    // In the MathML in HTML5 implementation note, the "left" notation is described as follows:
     223    // - center of the left vertical bar is at 3\xi_8 padding + \xi_8 border/2 = 7\xi_8/2
     224    // - top space is Overbar Vertical Gap + Overbar Rule Thickness = 3\xi_8 + \xi_8 = 4\xi_8
     225    // - bottom space is Underbar Vertical Gap + Underbar Rule Thickness = 3\xi_8 + \xi_8 = 4\xi_8
     226    if (hasNotation(MathMLMencloseElement::Left)) {
     227        LayoutUnit x = m_contentRect.x() - 7 * thickness / 2;
     228        LayoutUnit yStart = m_contentRect.y() - 4 * thickness;
     229        LayoutUnit yEnd = m_contentRect.maxY() + 4 * thickness;
     230        drawLine(info, x, yStart, x, yEnd);
     231    }
     232
     233    // In the MathML in HTML5 implementation note, the "right" notation is described as follows:
     234    // - center of the right vertical bar is at 3\xi_8 padding + \xi_8 border/2 = 7\xi_8/2
     235    // - top space is Overbar Vertical Gap + Overbar Rule Thickness = 3\xi_8 + \xi_8 = 4\xi_8
     236    // - bottom space is Underbar Vertical Gap + Underbar Rule Thickness = 3\xi_8 + \xi_8 = 4\xi_8
     237    if (hasNotation(MathMLMencloseElement::Right)) {
     238        LayoutUnit x = m_contentRect.maxX() + 7 * thickness / 2;
     239        LayoutUnit yStart = m_contentRect.y() - 4 * thickness;
     240        LayoutUnit yEnd = m_contentRect.maxY() + 4 * thickness;
     241        drawLine(info, x, yStart, x, yEnd);
     242    }
     243
     244    // In the MathML in HTML5 implementation note, the "vertical" notation is horizontally centered.
     245    if (hasNotation(MathMLMencloseElement::VerticalStrike)) {
     246        LayoutUnit x = m_contentRect.x() + (m_contentRect.width() - thickness) / 2;
     247        LayoutUnit yStart = m_contentRect.y();
     248        LayoutUnit yEnd = m_contentRect.maxY();
     249        drawLine(info, x, yStart, x, yEnd);
     250    }
     251
     252    // In the MathML in HTML5 implementation note, the "top" notation is described as follows:
     253    // - middle of the top horizontal bar is at Vertical Gap + Rule Thickness / 2 = 7\xi_8/2
     254    // - left and right spaces have size 4\xi_8
     255    if (hasNotation(MathMLMencloseElement::Top)) {
     256        LayoutUnit y = m_contentRect.y() - 7 * thickness / 2;
     257        LayoutUnit xStart = m_contentRect.x() - 4 * thickness;
     258        LayoutUnit xEnd = m_contentRect.maxX() + 4 * thickness;
     259        drawLine(info, xStart, y, xEnd, y);
     260    }
     261
     262    // In the MathML in HTML5 implementation note, the "bottom" notation is described as follows:
     263    // - middle of the bottom horizontal bar is at Vertical Gap + Rule Thickness / 2 = 7\xi_8/2
     264    // - left and right spaces have size 4\xi_8
     265    if (hasNotation(MathMLMencloseElement::Bottom)) {
     266        LayoutUnit y = m_contentRect.maxY() + 7 * thickness / 2;
     267        LayoutUnit xStart = m_contentRect.x() - 4 * thickness;
     268        LayoutUnit xEnd = m_contentRect.maxX() + 4 * thickness;
     269        drawLine(info, xStart, y, xEnd, y);
     270    }
     271
     272    // In the MathML in HTML5 implementation note, the "vertical" notation is vertically centered.
     273    if (hasNotation(MathMLMencloseElement::HorizontalStrike)) {
     274        LayoutUnit y = m_contentRect.y() + (m_contentRect.height() - thickness) / 2;
     275        LayoutUnit xStart = m_contentRect.x();
     276        LayoutUnit xEnd = m_contentRect.maxX();
     277        drawLine(info, xStart, y, xEnd, y);
     278    }
     279
     280    // In the MathML in HTML5 implementation note, the "updiagonalstrike" goes from the bottom left corner
     281    // to the top right corner.
     282    if (hasNotation(MathMLMencloseElement::UpDiagonalStrike))
     283        drawLine(info, m_contentRect.x(), m_contentRect.maxY(), m_contentRect.maxX(), m_contentRect.y());
     284
     285    // In the MathML in HTML5 implementation note, the "downdiagonalstrike" goes from the top left corner
     286    // to the bottom right corner.
     287    if (hasNotation(MathMLMencloseElement::DownDiagonalStrike))
     288        drawLine(info, m_contentRect.x(), m_contentRect.y(), m_contentRect.maxX(), m_contentRect.maxY());
     289
     290    // In the MathML in HTML5 implementation note, the "roundedbox" has radii size 3\xi_8 and is obtained
     291    // by inflating the content box by 3\xi_8 + \xi_8/2 = 7\xi_8/2
     292    if (hasNotation(MathMLMencloseElement::RoundedBox)) {
     293        LayoutSize radiiSize(3 * thickness, 3 * thickness);
     294        RoundedRect::Radii radii(radiiSize, radiiSize, radiiSize, radiiSize);
     295        RoundedRect roundedRect(m_contentRect, radii);
     296        roundedRect.inflate(7 * thickness / 2);
     297        Path path;
     298        path.addRoundedRect(roundedRect);
     299        info.context().strokePath(path);
     300    }
     301
     302    // For longdiv, we use our own rules for now:
     303    // - top space is like "top" notation
     304    // - bottom space is like "bottom" notation
     305    // - right space is like "right" notation
     306    // - left space is longDivLeftSpace * \xi_8
     307    // - We subtract half of the thickness from these spaces to obtain "top", "bottom", "left"
     308    //   and "right" coordinates.
     309    // - The top bar is drawn from "right" to "left" and positioned at vertical offset "top".
     310    // - The left part is draw as a quadratic Bezier curve with end points going from "top" to
     311    //   "bottom" and positioned at horizontal offset "left".
     312    // - In order to force the curvature of the left part, we use a middle point that is vertically
     313    //   centered and shifted towards the right by longDivLeftSpace * \xi_8
     314    if (hasNotation(MathMLMencloseElement::LongDiv)) {
     315        LayoutUnit top = m_contentRect.y() - 7 * thickness / 2;
     316        LayoutUnit bottom = m_contentRect.maxY() + 7 * thickness / 2;
     317        LayoutUnit left = m_contentRect.x() - longDivLeftSpace * thickness + thickness / 2;
     318        LayoutUnit right = m_contentRect.maxX() + 4 * thickness;
     319        LayoutUnit midX = left + longDivLeftSpace * thickness;
     320        LayoutUnit midY = (top + bottom) / 2;
     321        Path path;
     322        path.moveTo(LayoutPoint(right, top));
     323        path.addLineTo(LayoutPoint(left, top));
     324        path.addQuadCurveTo(LayoutPoint(midX, midY), FloatPoint(left, bottom));
     325        info.context().strokePath(path);
     326    }
     327
     328    // In the MathML in HTML5 implementation note, the "circle" notation is described as follows:
     329    // - The center and axes are the same as the content bounding box.
     330    // - The width of the bounding box is \xi_8/2 + contentWidth * \sqrt{2} + \xi_8/2
     331    // - The height is \xi_8/2 + contentHeight * \sqrt{2} + \xi_8/2
     332    if (hasNotation(MathMLMencloseElement::Circle)) {
     333        LayoutRect ellipseRect;
     334        ellipseRect.setWidth(m_contentRect.width() * sqrtOfTwoFloat + thickness);
     335        ellipseRect.setHeight(m_contentRect.height() * sqrtOfTwoFloat + thickness);
     336        ellipseRect.setX(m_contentRect.x() - (ellipseRect.width() - m_contentRect.width()) / 2);
     337        ellipseRect.setY(m_contentRect.y() - (ellipseRect.height() - m_contentRect.height()) / 2);
     338        Path path;
     339        path.addEllipse(ellipseRect);
     340        info.context().strokePath(path);
     341    }
    162342}
    163343
  • trunk/Source/WebCore/rendering/mathml/RenderMathMLMenclose.h

    r199964 r199980  
    11/*
    22 * Copyright (C) 2014 Gurpreet Kaur (k.gurpreet@samsung.com). All rights reserved.
     3 * Copyright (C) 2016 Igalia S.L.
    34 *
    45 * Redistribution and use in source and binary forms, with or without
     
    2829
    2930#if ENABLE(MATHML)
     31#include "MathMLMencloseElement.h"
    3032#include "RenderMathMLRow.h"
    3133
     
    3739
    3840private:
    39     bool isRenderMathMLMenclose() const final { return true; }
    4041    const char* renderName() const final { return "RenderMathMLMenclose"; }
     42    void computePreferredLogicalWidths() final;
     43    void layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeight = 0) final;
     44    Optional<int> firstLineBaseline() const final;
    4145    void paint(PaintInfo&, const LayoutPoint&) final;
    42     void updateLogicalHeight() override;
    43     void addChild(RenderObject* newChild, RenderObject* beforeChild = nullptr) override;
    44     void computePreferredLogicalWidths() final;
    45     bool checkNotationalValuesValidity(const Vector<String>&) const;
     46
     47    LayoutUnit ruleThickness() const;
     48    bool hasNotation(MathMLMencloseElement::MencloseNotationFlag notationFlag) const { return downcast<MathMLMencloseElement>(element())->hasNotation(notationFlag); }
     49
     50    void getSpaceAroundContent(LayoutUnit contentWidth, LayoutUnit contentHeight, LayoutUnit& leftSpace, LayoutUnit& rightSpace, LayoutUnit& topSpace, LayoutUnit& bottomSpace) const;
     51
     52    LayoutUnit m_ascent;
     53    LayoutRect m_contentRect;
    4654};
    4755   
  • trunk/Source/WebCore/rendering/mathml/RenderMathMLRoot.cpp

    r199964 r199980  
    6161}
    6262
    63 RenderMathMLRoot::RenderMathMLRoot(Document& document, std::unique_ptr<RenderStyle> style)
    64     : RenderMathMLBlock(document, WTFMove(style))
    65 {
    66 }
    67 
    6863RenderMathMLRootWrapper* RenderMathMLRoot::baseWrapper() const
    6964{
  • trunk/Source/WebCore/rendering/mathml/RenderMathMLRoot.h

    r199964 r199980  
    4444public:
    4545    RenderMathMLRoot(Element&, std::unique_ptr<RenderStyle>);
    46     RenderMathMLRoot(Document&, std::unique_ptr<RenderStyle>);
    4746
    4847    void addChild(RenderObject* newChild, RenderObject* beforeChild = 0) override;
  • trunk/Source/WebCore/rendering/mathml/RenderMathMLRow.cpp

    r199964 r199980  
    7171}
    7272
    73 void RenderMathMLRow::computeLineVerticalStretch(int& stretchHeightAboveBaseline, int& stretchDepthBelowBaseline)
     73void RenderMathMLRow::computeLineVerticalStretch(LayoutUnit& ascent, LayoutUnit& descent)
    7474{
    7575    for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
     
    8585        LayoutUnit childDepthBelowBaseline = child->logicalHeight() - childHeightAboveBaseline;
    8686
    87         stretchHeightAboveBaseline = std::max<LayoutUnit>(stretchHeightAboveBaseline, childHeightAboveBaseline);
    88         stretchDepthBelowBaseline = std::max<LayoutUnit>(stretchDepthBelowBaseline, childDepthBelowBaseline);
     87        ascent = std::max<LayoutUnit>(ascent, childHeightAboveBaseline);
     88        descent = std::max<LayoutUnit>(descent, childDepthBelowBaseline);
    8989    }
    9090
    9191    // We ensure a minimal stretch size.
    92     if (stretchHeightAboveBaseline + stretchDepthBelowBaseline <= 0) {
    93         stretchHeightAboveBaseline = style().fontSize();
    94         stretchDepthBelowBaseline = 0;
     92    if (ascent + descent <= 0) {
     93        ascent = style().fontSize();
     94        descent = 0;
    9595    }
    9696}
     
    111111}
    112112
    113 void RenderMathMLRow::layoutRowItems(int stretchHeightAboveBaseline, int stretchDepthBelowBaseline)
     113void RenderMathMLRow::layoutRowItems(LayoutUnit& ascent, LayoutUnit& descent)
    114114{
    115115    // We first stretch the vertical operators.
     
    123123            auto renderOperator = downcast<RenderMathMLBlock>(child)->unembellishedOperator();
    124124            if (renderOperator && renderOperator->hasOperatorFlag(MathMLOperatorDictionary::Stretchy) && renderOperator->isVertical())
    125                 renderOperator->stretchTo(stretchHeightAboveBaseline, stretchDepthBelowBaseline);
     125                renderOperator->stretchTo(ascent, descent);
    126126        }
    127127
     
    132132
    133133    width += borderEnd() + paddingEnd();
    134     // FIXME: RenderMathMLRoot and RenderMathMLEnclose classes should also recalculate the exact logical width instead of using the preferred width.
    135     // See https://bugs.webkit.org/show_bug.cgi?id=130326
    136     if ((!isRenderMathMLMath() || style().display() == INLINE) && !isRenderMathMLRoot() && !isRenderMathMLMenclose())
     134    // FIXME: RenderMathMLRoot classes should also recalculate the exact logical width instead of using the preferred width.
     135    // See http://webkit.org/b/153987
     136    if ((!isRenderMathMLMath() || style().display() == INLINE) && !isRenderMathMLRoot())
    137137        setLogicalWidth(width);
    138138
     
    176176        child->setLocation(child->location() + LayoutPoint(centerBlockOffset, startOffset));
    177177    }
     178
     179    ascent = maxAscent;
     180    descent = maxDescent;
    178181}
    179182
     
    185188        return;
    186189
    187     int stretchHeightAboveBaseline = 0;
    188     int stretchDepthBelowBaseline = 0;
    189     computeLineVerticalStretch(stretchHeightAboveBaseline, stretchDepthBelowBaseline);
     190    LayoutUnit ascent = 0;
     191    LayoutUnit descent = 0;
     192    computeLineVerticalStretch(ascent, descent);
    190193
    191194    recomputeLogicalWidth();
     
    193196    setLogicalHeight(borderAndPaddingLogicalHeight() + scrollbarLogicalHeight());
    194197
    195     layoutRowItems(stretchHeightAboveBaseline, stretchDepthBelowBaseline);
     198    layoutRowItems(ascent, descent);
    196199
    197200    updateLogicalHeight();
  • trunk/Source/WebCore/rendering/mathml/RenderMathMLRow.h

    r199964 r199980  
    4343    void updateOperatorProperties();
    4444
    45     void layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeight = 0) final;
    46     void paintChildren(PaintInfo& forSelf, const LayoutPoint&, PaintInfo& forChild, bool usePrintRect) final;
    47     Optional<int> firstLineBaseline() const final;
     45    void layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeight = 0) override;
     46    void paintChildren(PaintInfo& forSelf, const LayoutPoint&, PaintInfo& forChild, bool usePrintRect) override;
     47    Optional<int> firstLineBaseline() const override;
     48
     49protected:
     50    void layoutRowItems(LayoutUnit& ascent, LayoutUnit& descent);
     51    void computeLineVerticalStretch(LayoutUnit& ascent, LayoutUnit& descent);
     52    void computePreferredLogicalWidths() override;
    4853
    4954private:
    5055    bool isRenderMathMLRow() const final { return true; }
    5156    const char* renderName() const override { return isAnonymous() ? "RenderMathMLRow (anonymous)" : "RenderMathMLRow"; }
    52 
    53     void layoutRowItems(int stretchHeightAboveBaseline, int stretchDepthBelowBaseline);
    54     void computeLineVerticalStretch(int& stretchHeightAboveBaseline, int& stretchDepthBelowBaseline);
    55     void computePreferredLogicalWidths() override;
    5657};
    5758
  • trunk/Source/WebCore/rendering/mathml/RenderMathMLSquareRoot.cpp

    r199964 r199980  
    4040}
    4141
    42 RenderMathMLSquareRoot::RenderMathMLSquareRoot(Document& document, std::unique_ptr<RenderStyle> style)
    43     : RenderMathMLRoot(document, WTFMove(style))
    44 {
    45 }
    46 
    47 RenderPtr<RenderMathMLSquareRoot> RenderMathMLSquareRoot::createAnonymousWithParentRenderer(RenderMathMLMenclose& parent)
    48 {
    49     RenderPtr<RenderMathMLSquareRoot> squareRoot = createRenderer<RenderMathMLSquareRoot>(parent.document(), RenderStyle::createAnonymousStyleWithDisplay(&parent.style(), FLEX));
    50     squareRoot->initializeStyle();
    51     return squareRoot;
    52 }
    53 
    5442}
    5543#endif // ENABLE(MATHML)
  • trunk/Source/WebCore/rendering/mathml/RenderMathMLSquareRoot.h

    r199964 r199980  
    4040public:
    4141    RenderMathMLSquareRoot(Element&, std::unique_ptr<RenderStyle>);
    42     RenderMathMLSquareRoot(Document&, std::unique_ptr<RenderStyle>);
    4342    static RenderPtr<RenderMathMLSquareRoot> createAnonymousWithParentRenderer(RenderMathMLMenclose&);
    4443   
Note: See TracChangeset for help on using the changeset viewer.