Changeset 204022 in webkit
- Timestamp:
- Aug 2, 2016 4:27:19 AM (8 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r204021 r204022 1 2016-07-28 Frederic Wang <fwang@igalia.com> 2 3 Move parsing of the form attribute to MathMLOperatorElement 4 https://bugs.webkit.org/show_bug.cgi?id=160239 5 6 Reviewed by Darin Adler. 7 8 We move the parsing of the mo@form attribute to the MathMLOperatorElement class. Note that 9 when the attribute is not explicit, the form may also be guessed by searching into the 10 operator dictionary. Hence we also start moving the determination of the default dictionary 11 properties. Moving the actual parsing of the corresponding attributes will be done in 12 follow-up commits. 13 14 No new tests, already covered by existing tests. 15 16 * mathml/MathMLInlineContainerElement.cpp: 17 (WebCore::MathMLInlineContainerElement::childrenChanged): Make the form of operators dirty 18 if its siblings have changed. 19 * mathml/MathMLOperatorDictionary.cpp: 20 (WebCore::MathMLOperatorDictionary::search): Merge old getEntry functions into one helper 21 function that returns an Optional<Entry>. 22 (WebCore::MathMLOperatorDictionary::getEntry): Deleted 23 * mathml/MathMLOperatorDictionary.h: Declare MathMLOperatorDictionary::find. 24 * mathml/MathMLOperatorElement.cpp: 25 (WebCore::MathMLOperatorElement::dictionaryProperty): We determine the operator form by 26 parsing the corresponding attribute or by using heuristics if that attribute is not 27 specified. We also read dictionary the corresponding dictionary properties. 28 (WebCore::MathMLOperatorElement::flags): Return the flags read from the dictionary. 29 (WebCore::MathMLOperatorElement::defaultLeadingSpace): Return the space read from the dictionary. 30 (WebCore::MathMLOperatorElement::defaultTrailingSpace): Return the space read from the dictionary. 31 (WebCore::MathMLOperatorElement::childrenChanged): Make the dictionary properties dirty. 32 (WebCore::MathMLOperatorElement::parseAttribute): Make the dictionary properties dirty when 33 the form changes. 34 * mathml/MathMLOperatorElement.h: New member to store dictionary properties and expose them. 35 * rendering/mathml/RenderMathMLFencedOperator.cpp: 36 (WebCore::RenderMathMLFencedOperator::setOperatorProperties): We implement the case specific 37 to anonymous mfenced operators here. 38 * rendering/mathml/RenderMathMLFencedOperator.h: Move the m_operatorForm member here and 39 declare the overriden function setOperatorProperties. 40 * rendering/mathml/RenderMathMLOperator.cpp: 41 (WebCore::RenderMathMLOperator::setOperatorProperties): Simplify this code since the logic 42 has been moved to the element classes. 43 (WebCore::RenderMathMLOperator::setOperatorPropertiesFromOpDictEntry): Deleted. 44 * rendering/mathml/RenderMathMLOperator.h: Remove setOperatorPropertiesFromOpDictEntry, make 45 members accessible to RenderMathMLFencedOperator and remove m_operatorForm. 46 1 47 2016-08-02 Frederic Wang <fwang.igalia.com> 2 48 -
trunk/Source/WebCore/mathml/MathMLInlineContainerElement.cpp
r204021 r204022 33 33 34 34 #include "MathMLNames.h" 35 #include "MathMLOperatorElement.h" 35 36 #include "RenderMathMLBlock.h" 36 37 #include "RenderMathMLFenced.h" … … 55 56 void MathMLInlineContainerElement::childrenChanged(const ChildChange& change) 56 57 { 58 for (auto child = firstChild(); child; child = child->nextSibling()) { 59 if (child->hasTagName(MathMLNames::moTag)) 60 static_cast<MathMLOperatorElement*>(child)->setOperatorFormDirty(); 61 } 62 57 63 // FIXME: Parsing of operator properties should be done in the element classes rather than in the renderer classes. 58 64 // See https://webkit.org/b/156537 -
trunk/Source/WebCore/mathml/MathMLOperatorDictionary.cpp
r203116 r204022 1090 1090 }; 1091 1091 1092 const Entry* MathMLOperatorDictionary::getEntry(UChar textContent, Form form)1092 Optional<Entry> MathMLOperatorDictionary::search(UChar character, Form form, bool explicitForm) 1093 1093 { 1094 return tryBinarySearch<const Entry, Key>(dictionary, dictionarySize, Key(textContent, form), ExtractKey); 1095 } 1096 1097 const Entry* MathMLOperatorDictionary::getEntry(UChar textContent) 1098 { 1099 // For each operator, the dictionary has at most three form in the following order: Infix, Prefix, Postfix. 1100 if (const Entry* entry = tryBinarySearch<const Entry, UChar>(dictionary, dictionarySize, textContent, ExtractChar)) { 1094 if (!character) 1095 return Nullopt; 1096 1097 // We try and find the default values from the operator dictionary. 1098 if (auto* entry = tryBinarySearch<const Entry, Key>(dictionary, dictionarySize, Key(character, form), ExtractKey)) 1099 return *entry; 1100 1101 if (explicitForm) 1102 return Nullopt; 1103 1104 // 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. 1105 // 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 innerfences should not be considered infix. 1106 if (auto* entry = tryBinarySearch<const Entry, UChar>(dictionary, dictionarySize, character, ExtractChar)) { 1101 1107 // There are at most two other entries before the one found. 1102 if (entry != dictionary && (entry - 1)->character == textContent)1108 if (entry != dictionary && (entry - 1)->character == character) 1103 1109 entry--; 1104 if (entry != dictionary && (entry - 1)->character == textContent)1110 if (entry != dictionary && (entry - 1)->character == character) 1105 1111 entry--; 1106 return entry;1112 return *entry; 1107 1113 } 1108 return nullptr; 1114 1115 return Nullopt; 1109 1116 } 1110 1117 -
trunk/Source/WebCore/mathml/MathMLOperatorDictionary.h
r203228 r204022 29 29 30 30 #include <unicode/utypes.h> 31 #include <wtf/Optional.h> 31 32 32 33 namespace WebCore { … … 50 51 unsigned flags : 8; 51 52 }; 52 const Entry* getEntry(UChar, Form); 53 const Entry* getEntry(UChar); 53 Optional<Entry> search(UChar, Form, bool explicitForm); 54 54 bool isVertical(UChar); 55 55 } -
trunk/Source/WebCore/mathml/MathMLOperatorElement.cpp
r204021 r204022 36 36 37 37 using namespace MathMLNames; 38 using namespace MathMLOperatorDictionary; 38 39 39 40 MathMLOperatorElement::MathMLOperatorElement(const QualifiedName& tagName, Document& document) … … 61 62 UChar MathMLOperatorElement::operatorText() 62 63 { 63 if (m_operatorText) 64 return m_operatorText.value(); 64 if (!m_operatorText) 65 m_operatorText = parseOperatorText(textContent()); 66 return m_operatorText.value(); 67 } 65 68 66 m_operatorText = parseOperatorText(textContent()); 67 return m_operatorText.value(); 69 MathMLOperatorElement::DictionaryProperty MathMLOperatorElement::computeDictionaryProperty() 70 { 71 DictionaryProperty dictionaryProperty; 72 73 // We first determine the form attribute and use the default spacing and properties. 74 const auto& value = attributeWithoutSynchronization(formAttr); 75 bool explicitForm = true; 76 if (value == "prefix") 77 dictionaryProperty.form = Prefix; 78 else if (value == "infix") 79 dictionaryProperty.form = Infix; 80 else if (value == "postfix") 81 dictionaryProperty.form = Postfix; 82 else { 83 // FIXME: We should use more advanced heuristics indicated in the specification to determine the operator form (https://bugs.webkit.org/show_bug.cgi?id=124829). 84 explicitForm = false; 85 if (!previousSibling() && nextSibling()) 86 dictionaryProperty.form = Prefix; 87 else if (previousSibling() && !nextSibling()) 88 dictionaryProperty.form = Postfix; 89 else 90 dictionaryProperty.form = Infix; 91 } 92 93 // We then try and find an entry in the operator dictionary to override the default values. 94 if (auto entry = search(operatorText(), dictionaryProperty.form, explicitForm)) { 95 dictionaryProperty.form = static_cast<MathMLOperatorDictionary::Form>(entry.value().form); 96 dictionaryProperty.leadingSpaceInMathUnit = entry.value().lspace; 97 dictionaryProperty.trailingSpaceInMathUnit = entry.value().rspace; 98 dictionaryProperty.flags = entry.value().flags; 99 } 100 101 return dictionaryProperty; 102 } 103 104 const MathMLOperatorElement::DictionaryProperty& MathMLOperatorElement::dictionaryProperty() 105 { 106 if (!m_dictionaryProperty) 107 m_dictionaryProperty = computeDictionaryProperty(); 108 return m_dictionaryProperty.value(); 109 } 110 111 unsigned short MathMLOperatorElement::flags() 112 { 113 // FIXME: We should also handle boolean attributes here (https://webkit.org/b/160190). 114 return dictionaryProperty().flags; 115 } 116 117 MathMLElement::Length MathMLOperatorElement::defaultLeadingSpace() 118 { 119 Length space; 120 space.type = LengthType::MathUnit; 121 space.value = static_cast<float>(dictionaryProperty().leadingSpaceInMathUnit); 122 return space; 123 } 124 125 MathMLElement::Length MathMLOperatorElement::defaultTrailingSpace() 126 { 127 Length space; 128 space.type = LengthType::MathUnit; 129 space.value = static_cast<float>(dictionaryProperty().trailingSpaceInMathUnit); 130 return space; 68 131 } 69 132 … … 71 134 { 72 135 m_operatorText = Nullopt; 136 m_dictionaryProperty = Nullopt; 73 137 MathMLTextElement::childrenChanged(change); 74 138 } … … 76 140 void MathMLOperatorElement::parseAttribute(const QualifiedName& name, const AtomicString& value) 77 141 { 142 if (name == formAttr) 143 m_dictionaryProperty = Nullopt; 144 78 145 if ((name == stretchyAttr || name == lspaceAttr || name == rspaceAttr || name == movablelimitsAttr) && renderer()) { 79 146 downcast<RenderMathMLOperator>(*renderer()).updateFromElement(); -
trunk/Source/WebCore/mathml/MathMLOperatorElement.h
r203896 r204022 27 27 28 28 #if ENABLE(MATHML) 29 #include "MathMLOperatorDictionary.h" 29 30 #include "MathMLTextElement.h" 30 31 … … 36 37 static UChar parseOperatorText(const String&); 37 38 UChar operatorText(); 39 void setOperatorFormDirty() { m_dictionaryProperty = Nullopt; } 40 MathMLOperatorDictionary::Form form() { return dictionaryProperty().form; } 41 unsigned short flags(); 42 Length defaultLeadingSpace(); 43 Length defaultTrailingSpace(); 38 44 39 45 private: … … 44 50 45 51 Optional<UChar> m_operatorText; 52 53 struct DictionaryProperty { 54 MathMLOperatorDictionary::Form form; 55 // Default leading and trailing spaces are "thickmathspace". 56 unsigned short leadingSpaceInMathUnit { 5 }; 57 unsigned short trailingSpaceInMathUnit { 5 }; 58 // Default operator properties are all set to "false". 59 unsigned short flags { 0 }; 60 }; 61 Optional<DictionaryProperty> m_dictionaryProperty; 62 DictionaryProperty computeDictionaryProperty(); 63 const DictionaryProperty& dictionaryProperty(); 46 64 }; 47 65 -
trunk/Source/WebCore/rendering/mathml/RenderMathMLFencedOperator.cpp
r203973 r204022 27 27 28 28 #if ENABLE(MATHML) 29 29 30 #include "RenderMathMLFencedOperator.h" 30 31 32 #include "MathMLOperatorDictionary.h" 31 33 #include "MathMLOperatorElement.h" 32 34 33 35 namespace WebCore { 34 36 37 using namespace MathMLOperatorDictionary; 38 35 39 RenderMathMLFencedOperator::RenderMathMLFencedOperator(Document& document, RenderStyle&& style, const String& operatorString, MathMLOperatorDictionary::Form form, unsigned short flags) 36 : RenderMathMLOperator(document, WTFMove(style), form, flags) 40 : RenderMathMLOperator(document, WTFMove(style), flags) 41 , m_operatorForm(form) 37 42 { 38 43 updateOperatorContent(operatorString); 44 45 // maxsize always has the default value "infinity" value for mfenced operators. 46 m_maxSize = intMaxForLayoutUnit; 39 47 } 40 48 … … 45 53 } 46 54 55 void RenderMathMLFencedOperator::setOperatorProperties() 56 { 57 // We determine the stretch direction (default is vertical). 58 m_isVertical = MathMLOperatorDictionary::isVertical(m_textContent); 59 60 // Resets all but the Fence and Separator properties. 61 m_operatorFlags &= MathMLOperatorDictionary::Fence | MathMLOperatorDictionary::Separator; 62 63 // minsize always has the default value "1em" value for mfenced operators. 64 m_minSize = style().fontCascade().size(); 65 66 // Default spacing is thickmathspace. 67 MathMLElement::Length leadingSpace; 68 leadingSpace.type = MathMLElement::LengthType::MathUnit; 69 leadingSpace.value = 5; 70 MathMLElement::Length trailingSpace = leadingSpace; 71 72 if (auto entry = search(m_textContent, m_operatorForm, true)) { 73 // We use the space specified in the operator dictionary. 74 leadingSpace.value = static_cast<float>(entry.value().lspace); 75 trailingSpace.value = static_cast<float>(entry.value().rspace); 76 77 // We use the dictionary but preserve the Fence and Separator properties. 78 m_operatorFlags = (m_operatorFlags & (MathMLOperatorDictionary::Fence | MathMLOperatorDictionary::Separator)) | entry.value().flags; 79 } 80 81 // Resolve the leading and trailing spaces. 82 m_leadingSpace = toUserUnits(leadingSpace, style(), 0); 83 m_trailingSpace = toUserUnits(trailingSpace, style(), 0); 84 } 85 47 86 } 48 87 -
trunk/Source/WebCore/rendering/mathml/RenderMathMLFencedOperator.h
r203973 r204022 40 40 private: 41 41 bool isRenderMathMLFencedOperator() const final { return true; } 42 void setOperatorProperties() final; 42 43 UChar textContent() const final { return m_textContent; } 43 44 44 45 UChar m_textContent { 0 }; 46 MathMLOperatorDictionary::Form m_operatorForm; 45 47 }; 46 48 -
trunk/Source/WebCore/rendering/mathml/RenderMathMLOperator.cpp
r203973 r204022 54 54 } 55 55 56 RenderMathMLOperator::RenderMathMLOperator(Document& document, RenderStyle&& style, MathMLOperatorDictionary::Form form,unsigned short flags)56 RenderMathMLOperator::RenderMathMLOperator(Document& document, RenderStyle&& style, unsigned short flags) 57 57 : RenderMathMLToken(document, WTFMove(style)) 58 , m_operatorForm(form)59 58 , m_operatorFlags(flags) 60 59 { … … 88 87 } 89 88 90 void RenderMathMLOperator::setOperatorPropertiesFromOpDictEntry(const MathMLOperatorDictionary::Entry* entry)91 {92 // If this operator is anonymous, we preserve the Fence and Separator properties. This is to handle the case of RenderMathMLFenced.93 if (isAnonymous())94 m_operatorFlags = (m_operatorFlags & (MathMLOperatorDictionary::Fence | MathMLOperatorDictionary::Separator)) | entry->flags;95 else96 m_operatorFlags = entry->flags;97 98 // Leading and trailing space is specified as multiple of 1/18em.99 m_leadingSpace = entry->lspace * style().fontCascade().size() / 18;100 m_trailingSpace = entry->rspace * style().fontCascade().size() / 18;101 }102 103 89 void RenderMathMLOperator::setOperatorProperties() 104 90 { … … 106 92 m_isVertical = MathMLOperatorDictionary::isVertical(textContent()); 107 93 108 // We determine the form of the operator. 109 bool explicitForm = true; 110 if (!isAnonymous()) { 111 const AtomicString& form = element().attributeWithoutSynchronization(MathMLNames::formAttr); 112 if (form == "prefix") 113 m_operatorForm = MathMLOperatorDictionary::Prefix; 114 else if (form == "infix") 115 m_operatorForm = MathMLOperatorDictionary::Infix; 116 else if (form == "postfix") 117 m_operatorForm = MathMLOperatorDictionary::Postfix; 118 else { 119 // FIXME: We should use more advanced heuristics indicated in the specification to determine the operator form (https://bugs.webkit.org/show_bug.cgi?id=124829). 120 explicitForm = false; 121 if (!element().previousSibling() && element().nextSibling()) 122 m_operatorForm = MathMLOperatorDictionary::Prefix; 123 else if (element().previousSibling() && !element().nextSibling()) 124 m_operatorForm = MathMLOperatorDictionary::Postfix; 125 else 126 m_operatorForm = MathMLOperatorDictionary::Infix; 127 } 128 } 129 130 // We determine the default values of the operator properties. 131 132 // First we initialize with the default values for unknown operators. 133 if (isAnonymous()) 134 m_operatorFlags &= MathMLOperatorDictionary::Fence | MathMLOperatorDictionary::Separator; // This resets all but the Fence and Separator properties. 135 else 136 m_operatorFlags = 0; // This resets all the operator properties. 137 m_leadingSpace = 5 * style().fontCascade().size() / 18; // This sets leading space to "thickmathspace". 138 m_trailingSpace = 5 * style().fontCascade().size() / 18; // This sets trailing space to "thickmathspace". 94 // Initialize with the default values. 95 m_operatorFlags = element().flags(); 96 m_leadingSpace = toUserUnits(element().defaultLeadingSpace(), style(), 0); 97 m_trailingSpace = toUserUnits(element().defaultTrailingSpace(), style(), 0); 139 98 m_minSize = style().fontCascade().size(); // This sets minsize to "1em". 140 99 m_maxSize = intMaxForLayoutUnit; // This sets maxsize to "infinity". 141 142 if (textContent()) {143 // Then we try to find the default values from the operator dictionary.144 if (const MathMLOperatorDictionary::Entry* entry = MathMLOperatorDictionary::getEntry(textContent(), m_operatorForm))145 setOperatorPropertiesFromOpDictEntry(entry);146 else if (!explicitForm) {147 // 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.148 // 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.149 if (const MathMLOperatorDictionary::Entry* entry = MathMLOperatorDictionary::getEntry(textContent())) {150 m_operatorForm = static_cast<MathMLOperatorDictionary::Form>(entry->form); // We override the form previously determined.151 setOperatorPropertiesFromOpDictEntry(entry);152 }153 }154 }155 100 156 101 if (!isAnonymous()) { -
trunk/Source/WebCore/rendering/mathml/RenderMathMLOperator.h
r203973 r204022 40 40 public: 41 41 RenderMathMLOperator(MathMLOperatorElement&, RenderStyle&&); 42 RenderMathMLOperator(Document&, RenderStyle&&, MathMLOperatorDictionary::Form,unsigned short flags = 0);42 RenderMathMLOperator(Document&, RenderStyle&&, unsigned short flags = 0); 43 43 MathMLOperatorElement& element() const; 44 44 … … 61 61 protected: 62 62 void rebuildTokenContent(); 63 virtual void setOperatorProperties(); 63 64 64 MathMLOperatorDictionary::Form m_operatorForm; 65 bool m_isVertical { true }; 66 LayoutUnit m_leadingSpace; 67 LayoutUnit m_trailingSpace; 68 LayoutUnit m_minSize; 69 LayoutUnit m_maxSize; 65 70 unsigned short m_operatorFlags; 66 71 67 72 private: 68 virtual void setOperatorProperties();69 73 void styleDidChange(StyleDifference, const RenderStyle* oldStyle) final; 70 74 void computePreferredLogicalWidths() final; … … 89 93 void setOperatorFlagFromAttribute(MathMLOperatorDictionary::Flag, const QualifiedName&); 90 94 void setOperatorFlagFromAttributeValue(MathMLOperatorDictionary::Flag, const AtomicString& attributeValue); 91 void setOperatorPropertiesFromOpDictEntry(const MathMLOperatorDictionary::Entry*);92 95 93 96 LayoutUnit verticalStretchedOperatorShift() const; … … 97 100 LayoutUnit m_stretchWidth; 98 101 99 bool m_isVertical { true };100 LayoutUnit m_leadingSpace;101 LayoutUnit m_trailingSpace;102 LayoutUnit m_minSize;103 LayoutUnit m_maxSize;104 102 MathOperator m_mathOperator; 105 103 };
Note: See TracChangeset
for help on using the changeset viewer.