Bad position of large operators inside an munderover element
[WebKit-https.git] / Source / WebCore / rendering / mathml / RenderMathMLOperator.h
1 /*
2  * Copyright (C) 2010 Alex Milowski (alex@milowski.com). All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
14  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
15  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
16  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
17  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
18  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
19  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #ifndef RenderMathMLOperator_h
27 #define RenderMathMLOperator_h
28
29 #if ENABLE(MATHML)
30
31 #include "Font.h"
32 #include "GlyphPage.h"
33 #include "MathMLElement.h"
34 #include "OpenTypeMathData.h"
35 #include "RenderMathMLToken.h"
36
37 namespace WebCore {
38
39 namespace MathMLOperatorDictionary {
40
41 enum Form { Infix, Prefix, Postfix };
42 enum Flag {
43     Accent = 0x1, // FIXME: This must be used to implement accentunder/accent on munderover (https://bugs.webkit.org/show_bug.cgi?id=124826).
44     Fence = 0x2, // This has no visual effect but allows to expose semantic information via the accessibility tree.
45     LargeOp = 0x4,
46     MovableLimits = 0x8, // FIXME: This must be used to implement displaystyle  (https://bugs.webkit.org/show_bug.cgi?id=118737).
47     Separator = 0x10, // This has no visual effect but allows to expose semantic information via the accessibility tree.
48     Stretchy = 0x20,
49     Symmetric = 0x40
50 };
51 struct Entry {
52     UChar character;
53     unsigned form : 2;
54     unsigned lspace : 3;
55     unsigned rspace : 3;
56     unsigned flags : 8;
57 };
58
59 }
60
61 class RenderMathMLOperator : public RenderMathMLToken {
62 public:
63     RenderMathMLOperator(MathMLElement&, Ref<RenderStyle>&&);
64     RenderMathMLOperator(Document&, Ref<RenderStyle>&&, const String& operatorString, MathMLOperatorDictionary::Form, unsigned short flags = 0);
65
66     virtual void stretchTo(LayoutUnit heightAboveBaseline, LayoutUnit depthBelowBaseline);
67     void stretchTo(LayoutUnit width);
68     LayoutUnit stretchSize() const { return m_isVertical ? m_stretchHeightAboveBaseline + m_stretchDepthBelowBaseline : m_stretchWidth; }
69     void resetStretchSize();
70     
71     bool hasOperatorFlag(MathMLOperatorDictionary::Flag flag) const { return m_operatorFlags & flag; }
72     // FIXME: The displaystyle property is not implemented (https://bugs.webkit.org/show_bug.cgi?id=118737).
73     bool isLargeOperatorInDisplayStyle() const { return !hasOperatorFlag(MathMLOperatorDictionary::Stretchy) && hasOperatorFlag(MathMLOperatorDictionary::LargeOp); }
74     bool isVertical() const { return m_isVertical; }
75
76     virtual void updateStyle() override final;
77
78     virtual void paint(PaintInfo&, const LayoutPoint&) override;
79
80     void updateTokenContent(const String& operatorString);
81     virtual void updateTokenContent() override final;
82     void updateOperatorProperties();
83     void setOperatorFlagAndScheduleLayoutIfNeeded(MathMLOperatorDictionary::Flag, const AtomicString& attributeValue);
84     LayoutUnit trailingSpaceError();
85
86 protected:
87     virtual void setOperatorProperties();
88     virtual void computePreferredLogicalWidths() override;
89     virtual void computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues&) const override;
90     float advanceForGlyph(const GlyphData&) const;
91     void setLeadingSpace(LayoutUnit leadingSpace) { m_leadingSpace = leadingSpace; }
92     void setTrailingSpace(LayoutUnit trailingSpace) { m_trailingSpace = trailingSpace; }
93     UChar textContent() const { return m_textContent; }
94
95 private:
96     enum DrawMode {
97         DrawNormal, DrawSizeVariant, DrawGlyphAssembly
98     };
99
100     class StretchyData {
101     public:
102         DrawMode mode() const { return m_mode; }
103         GlyphData variant() const { return m_data[0]; }
104         GlyphData top() const { return m_data[0]; }
105         GlyphData extension() const { return m_data[1]; }
106         GlyphData bottom() const { return m_data[2]; }
107         GlyphData middle() const { return m_data[3]; }
108         GlyphData left() const { return m_data[2]; }
109         GlyphData right() const { return m_data[0]; }
110
111         void setNormalMode()
112         {
113             m_mode = DrawNormal;
114         }
115         void setSizeVariantMode(const GlyphData& variant)
116         {
117             m_mode = DrawSizeVariant;
118             m_data[0] = variant;
119         }
120         void setGlyphAssemblyMode(const GlyphData& top, const GlyphData& extension, const GlyphData& bottom, const GlyphData& middle)
121         {
122             m_mode = DrawGlyphAssembly;
123             m_data[0] = top;
124             m_data[1] = extension;
125             m_data[2] = bottom;
126             m_data[3] = middle;
127         }
128         StretchyData()
129             : m_mode(DrawNormal) { }
130         StretchyData(const StretchyData& data)
131         {
132             switch (data.m_mode) {
133             case DrawNormal:
134                 setNormalMode();
135                 break;
136             case DrawSizeVariant:
137                 setSizeVariantMode(data.variant());
138                 break;
139             case DrawGlyphAssembly:
140                 setGlyphAssemblyMode(data.top(), data.extension(), data.bottom(), data.middle());
141                 break;
142             }
143         }
144
145     private:
146         DrawMode m_mode;
147         // FIXME: For OpenType fonts with a MATH table all the glyphs are from the same font, so we would only need to store the glyph indices here.
148         GlyphData m_data[4];
149     };
150
151     virtual const char* renderName() const override { return isAnonymous() ? "RenderMathMLOperator (anonymous)" : "RenderMathMLOperator"; }
152     virtual void paintChildren(PaintInfo& forSelf, const LayoutPoint&, PaintInfo& forChild, bool usePrintRect) override;
153     virtual bool isRenderMathMLOperator() const override { return true; }
154     // The following operators are invisible: U+2061 FUNCTION APPLICATION, U+2062 INVISIBLE TIMES, U+2063 INVISIBLE SEPARATOR, U+2064 INVISIBLE PLUS.
155     bool isInvisibleOperator() const { return 0x2061 <= m_textContent && m_textContent <= 0x2064; }
156     virtual bool isChildAllowed(const RenderObject&, const RenderStyle&) const override;
157
158     virtual Optional<int> firstLineBaseline() const override;
159     virtual RenderMathMLOperator* unembellishedOperator() override { return this; }
160     void rebuildTokenContent(const String& operatorString);
161     virtual void updateFromElement() override;
162
163     bool shouldAllowStretching() const;
164
165     FloatRect boundsForGlyph(const GlyphData&) const;
166     float heightForGlyph(const GlyphData&) const;
167
168     bool getGlyphAssemblyFallBack(Vector<OpenTypeMathData::AssemblyPart>, StretchyData&) const;
169     StretchyData getDisplayStyleLargeOperator(UChar) const;
170     StretchyData findStretchyData(UChar, float* maximumGlyphWidth);
171
172     enum GlyphPaintTrimming {
173         TrimTop,
174         TrimBottom,
175         TrimTopAndBottom,
176         TrimLeft,
177         TrimRight,
178         TrimLeftAndRight
179     };
180
181     LayoutRect paintGlyph(PaintInfo&, const GlyphData&, const LayoutPoint& origin, GlyphPaintTrimming);
182     void fillWithVerticalExtensionGlyph(PaintInfo&, const LayoutPoint& from, const LayoutPoint& to);
183     void fillWithHorizontalExtensionGlyph(PaintInfo&, const LayoutPoint& from, const LayoutPoint& to);
184     void paintVerticalGlyphAssembly(PaintInfo&, const LayoutPoint&);
185     void paintHorizontalGlyphAssembly(PaintInfo&, const LayoutPoint&);
186     void setOperatorFlagFromAttribute(MathMLOperatorDictionary::Flag, const QualifiedName&);
187     void setOperatorFlagFromAttributeValue(MathMLOperatorDictionary::Flag, const AtomicString& attributeValue);
188     void setOperatorPropertiesFromOpDictEntry(const MathMLOperatorDictionary::Entry*);
189
190     LayoutUnit m_stretchHeightAboveBaseline;
191     LayoutUnit m_stretchDepthBelowBaseline;
192     LayoutUnit m_stretchWidth;
193
194     UChar m_textContent;
195     bool m_isVertical;
196     MathMLOperatorDictionary::Form m_operatorForm;
197     unsigned short m_operatorFlags;
198     LayoutUnit m_leadingSpace;
199     LayoutUnit m_trailingSpace;
200     LayoutUnit m_minSize;
201     LayoutUnit m_maxSize;
202     StretchyData m_stretchyData;
203 };
204
205 } // namespace WebCore
206
207 SPECIALIZE_TYPE_TRAITS_RENDER_OBJECT(RenderMathMLOperator, isRenderMathMLOperator())
208
209 #endif // ENABLE(MATHML)
210 #endif // RenderMathMLOperator_h