Changeset 205111 in webkit
- Timestamp:
- Aug 28, 2016 11:55:59 PM (8 years ago)
- Location:
- trunk
- Files:
-
- 5 added
- 12 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r205110 r205111 1 2016-08-25 Frederic Wang <fwang@igalia.com> 2 3 Add support for non-BMP operators U+1EEF0 and U+1EEF1 4 https://bugs.webkit.org/show_bug.cgi?id=153984 5 6 We add two reftests to check that the non-BMP operators are properly 7 handled by the MathML dictionary (form, properties, direction) as well 8 as the rendering code (spacing, stretching). We test the new horizontal 9 strechy operators U+1EEF0 and U+1EEF1 as well as the letter U+1D400 10 which is not a real mathematical operator. We add a minimal test 11 font which contains a black square for U+005F, U+1EEF0, U+1EEF1, U+1D400 12 and the data that can be used to stretch them horizontally. 13 14 Reviewed by Darin Adler. 15 16 * mathml/presentation/non-bmp-operators-spacing-expected.html: Added. 17 * mathml/presentation/non-bmp-operators-spacing.html: Added. 18 * mathml/presentation/non-bmp-operators-stretching-expected.html: Added. 19 * mathml/presentation/non-bmp-operators-stretching.html: Added. 20 * mathml/presentation/non-bmp-operators.woff: Added. 21 1 22 2016-08-28 Youenn Fablet <youenn@apple.com> 2 23 -
trunk/Source/WebCore/ChangeLog
r205110 r205111 1 2016-08-25 Frederic Wang <fwang@igalia.com> 2 3 Add support for non-BMP operators U+1EEF0 and U+1EEF1 4 https://bugs.webkit.org/show_bug.cgi?id=153984 5 6 Reviewed by Darin Adler. 7 8 Tests: mathml/presentation/non-bmp-operators-spacing.html 9 mathml/presentation/non-bmp-operators-stretching.html 10 11 * mathml/MathMLOperatorDictionary.cpp: We move the definition of operator dictionary Entry 12 here as it is not used by external code. 13 We now also accept non-BMP operators and add entries for U+1EEF0 and U+1EEF1. 14 (WebCore::extractProperty): Helper function to convert from Entry structure to a Property 15 structure. 16 (WebCore::MathMLOperatorDictionary::search): This function now accepts a non-BMP parameter 17 and returns a Property structure. 18 (WebCore::MathMLOperatorDictionary::isVertical): This function now accepts a non-BMP parameter. 19 * mathml/MathMLOperatorDictionary.h: Replace the Entry structure with a Property structure 20 which was used by MathMLOperatorElement. Update the signatures of search and isVertical. 21 * mathml/MathMLOperatorElement.cpp: 22 (WebCore::MathMLOperatorElement::parseOperatorChar): Remove the special case that excludes 23 non-BMP operators. 24 (WebCore::MathMLOperatorElement::computeDictionaryProperty): Rename the property structure 25 to use the one moved into MathMLOperatorDictionary.h. We no longer need to convert the result 26 of the search call. 27 (WebCore::MathMLOperatorElement::dictionaryProperty): Rename the property structure. 28 * mathml/MathMLOperatorElement.h: Make OperatorChar accept non-BMP operators. 29 MathMLOperatorElement::DictionaryProperty is now moved into MathMLOperatorDictionary 30 and renamed Property. 31 * rendering/mathml/MathOperator.cpp: Accept non-BMP operators. 32 * rendering/mathml/MathOperator.h: Ditto. 33 * rendering/mathml/RenderMathMLFencedOperator.cpp: 34 (WebCore::RenderMathMLFencedOperator::updateOperatorContent): Adjust code to use the new 35 return type of MathMLOperatorDictionary::search. 36 * rendering/mathml/RenderMathMLFencedOperator.h: Accept non-BMP operators. 37 * rendering/mathml/RenderMathMLOperator.cpp: Ditto. 38 * rendering/mathml/RenderMathMLOperator.h: Ditto. 39 1 40 2016-08-28 Youenn Fablet <youenn@apple.com> 2 41 -
trunk/Source/WebCore/mathml/MathMLOperatorDictionary.cpp
r204885 r205111 33 33 using namespace MathMLOperatorDictionary; 34 34 35 typedef std::pair<UChar, Form> Key; 35 typedef std::pair<UChar32, Form> Key; 36 struct Entry { 37 UChar32 character; 38 unsigned form : 2; 39 unsigned lspace : 3; 40 unsigned rspace : 3; 41 unsigned flags : 8; 42 }; 36 43 static inline Key ExtractKey(const Entry* entry) { return Key(entry->character, static_cast<Form>(entry->form)); } 37 static inline UChar ExtractChar(const Entry* entry) { return entry->character; } 44 static inline UChar32 ExtractChar(const Entry* entry) { return entry->character; } 45 static inline Property ExtractProperty(const Entry& entry) 46 { 47 Property property; 48 property.form = static_cast<Form>(entry.form); 49 property.leadingSpaceInMathUnit = entry.lspace; 50 property.trailingSpaceInMathUnit = entry.rspace; 51 property.flags = entry.flags; 52 return property; 53 } 38 54 39 55 // This table has been automatically generated from the Operator Dictionary of the MathML3 specification (appendix C). 40 56 // Some people use the binary operator "U+2225 PARALLEL TO" as an opening and closing delimiter, so we add the corresponding stretchy prefix and postfix forms. 41 static const unsigned dictionarySize = 104 1;57 static const unsigned dictionarySize = 1043; 42 58 static const Entry dictionary[dictionarySize] = { 43 59 { 0x21, Postfix, 1, 0, 0}, // EXCLAMATION MARK … … 1081 1097 { 0x2AFF, Prefix, 1, 2, Symmetric | LargeOp | MovableLimits}, // N-ARY WHITE VERTICAL BAR 1082 1098 { 0x2B45, Infix, 5, 5, Stretchy}, // LEFTWARDS QUADRUPLE ARROW 1083 { 0x2B46, Infix, 5, 5, Stretchy} // RIGHTWARDS QUADRUPLE ARROW 1099 { 0x2B46, Infix, 5, 5, Stretchy}, // RIGHTWARDS QUADRUPLE ARROW 1100 { 0x1EEF0, Prefix, 0, 0, Stretchy }, // ARABIC MATHEMATICAL OPERATOR MEEM WITH HAH WITH TATWEEL 1101 { 0x1EEF1, Prefix, 0, 0, Stretchy } // ARABIC MATHEMATICAL OPERATOR HAH WITH DAL 1084 1102 }; 1085 1103 1086 1104 // A list of operators that stretch in the horizontal direction. This has been generated from Mozilla's MathML operator dictionary. 1087 static inline UChar ExtractKeyHorizontal(const UChar* entry) { return *entry; }1088 static const UChar horizontalOperators[] = {1089 0x003D, 0x005E, 0x005F, 0x007E, 0x00AF, 0x02C6, 0x02C7, 0x02C9, 0x02CD, 0x02DC, 0x02F7, 0x0302, 0x0332, 0x203E, 0x20D0, 0x20D1, 0x20D6, 0x20D7, 0x20E1, 0x2190, 0x2192, 0x2194, 0x2198, 0x2199, 0x219C, 0x219D, 0x219E, 0x21A0, 0x21A2, 0x21A3, 0x21A4, 0x21A6, 0x21A9, 0x21AA, 0x21AB, 0x21AC, 0x21AD, 0x21B4, 0x21B9, 0x21BC, 0x21BD, 0x21C0, 0x21C1, 0x21C4, 0x21C6, 0x21C7, 0x21C9, 0x21CB, 0x21CC, 0x21D0, 0x21D2, 0x21D4, 0x21DA, 0x21DB, 0x21DC, 0x21DD, 0x21E0, 0x21E2, 0x21E4, 0x21E5, 0x21E6, 0x21E8, 0x21F0, 0x21F6, 0x21FD, 0x21FE, 0x21FF, 0x23B4, 0x23B5, 0x23DC, 0x23DD, 0x23DE, 0x23DF, 0x23E0, 0x23E1, 0x2500, 0x27F5, 0x27F6, 0x27F7, 0x27F8, 0x27F9, 0x27FA, 0x27FB, 0x27FC, 0x27FD, 0x27FE, 0x27FF, 0x290C, 0x290D, 0x290E, 0x290F, 0x2910, 0x294E, 0x2950, 0x2952, 0x2953, 0x2956, 0x2957, 0x295A, 0x295B, 0x295E, 0x295F, 0x2B45, 0x2B46, 0xFE35, 0xFE36, 0xFE37, 0xFE38 1105 static inline UChar32 ExtractKeyHorizontal(const UChar32* entry) { return *entry; } 1106 static const UChar32 horizontalOperators[] = { 1107 0x003D, 0x005E, 0x005F, 0x007E, 0x00AF, 0x02C6, 0x02C7, 0x02C9, 0x02CD, 0x02DC, 0x02F7, 0x0302, 0x0332, 0x203E, 0x20D0, 0x20D1, 0x20D6, 0x20D7, 0x20E1, 0x2190, 0x2192, 0x2194, 0x2198, 0x2199, 0x219C, 0x219D, 0x219E, 0x21A0, 0x21A2, 0x21A3, 0x21A4, 0x21A6, 0x21A9, 0x21AA, 0x21AB, 0x21AC, 0x21AD, 0x21B4, 0x21B9, 0x21BC, 0x21BD, 0x21C0, 0x21C1, 0x21C4, 0x21C6, 0x21C7, 0x21C9, 0x21CB, 0x21CC, 0x21D0, 0x21D2, 0x21D4, 0x21DA, 0x21DB, 0x21DC, 0x21DD, 0x21E0, 0x21E2, 0x21E4, 0x21E5, 0x21E6, 0x21E8, 0x21F0, 0x21F6, 0x21FD, 0x21FE, 0x21FF, 0x23B4, 0x23B5, 0x23DC, 0x23DD, 0x23DE, 0x23DF, 0x23E0, 0x23E1, 0x2500, 0x27F5, 0x27F6, 0x27F7, 0x27F8, 0x27F9, 0x27FA, 0x27FB, 0x27FC, 0x27FD, 0x27FE, 0x27FF, 0x290C, 0x290D, 0x290E, 0x290F, 0x2910, 0x294E, 0x2950, 0x2952, 0x2953, 0x2956, 0x2957, 0x295A, 0x295B, 0x295E, 0x295F, 0x2B45, 0x2B46, 0xFE35, 0xFE36, 0xFE37, 0xFE38, 0x1EEF0, 0x1EEF1 1090 1108 }; 1091 1109 1092 Optional< Entry> MathMLOperatorDictionary::search(UCharcharacter, Form form, bool explicitForm)1110 Optional<Property> MathMLOperatorDictionary::search(UChar32 character, Form form, bool explicitForm) 1093 1111 { 1094 1112 if (!character) … … 1097 1115 // We try and find the default values from the operator dictionary. 1098 1116 if (auto* entry = tryBinarySearch<const Entry, Key>(dictionary, dictionarySize, Key(character, form), ExtractKey)) 1099 return *entry;1117 return ExtractProperty(*entry); 1100 1118 1101 1119 if (explicitForm) … … 1104 1122 // 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 1123 // 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)) {1124 if (auto* entry = tryBinarySearch<const Entry, UChar32>(dictionary, dictionarySize, character, ExtractChar)) { 1107 1125 // There are at most two other entries before the one found. 1108 1126 if (entry != dictionary && (entry - 1)->character == character) … … 1110 1128 if (entry != dictionary && (entry - 1)->character == character) 1111 1129 entry--; 1112 return *entry;1130 return ExtractProperty(*entry); 1113 1131 } 1114 1132 … … 1116 1134 } 1117 1135 1118 bool MathMLOperatorDictionary::isVertical(UChar textContent)1136 bool MathMLOperatorDictionary::isVertical(UChar32 textContent) 1119 1137 { 1120 return !tryBinarySearch<const UChar , UChar>(horizontalOperators, WTF_ARRAY_LENGTH(horizontalOperators), textContent, ExtractKeyHorizontal);1138 return !tryBinarySearch<const UChar32, UChar32>(horizontalOperators, WTF_ARRAY_LENGTH(horizontalOperators), textContent, ExtractKeyHorizontal); 1121 1139 } 1122 1140 -
trunk/Source/WebCore/mathml/MathMLOperatorDictionary.h
r204032 r205111 45 45 }; 46 46 const unsigned allFlags = Accent | Fence | LargeOp | MovableLimits | Separator | Stretchy | Symmetric; 47 struct Entry { 48 UChar character; 49 unsigned form : 2; 50 unsigned lspace : 3; 51 unsigned rspace : 3; 52 unsigned flags : 8; 47 struct Property { 48 MathMLOperatorDictionary::Form form; 49 // Default leading and trailing spaces are "thickmathspace". 50 unsigned short leadingSpaceInMathUnit { 5 }; 51 unsigned short trailingSpaceInMathUnit { 5 }; 52 // Default operator properties are all set to "false". 53 unsigned short flags { 0 }; 53 54 }; 54 Optional< Entry> search(UChar, Form, bool explicitForm);55 bool isVertical(UChar );55 Optional<Property> search(UChar32, Form, bool explicitForm); 56 bool isVertical(UChar32); 56 57 } 57 58 -
trunk/Source/WebCore/mathml/MathMLOperatorElement.cpp
r204885 r205111 53 53 // FIXME: This operator dictionary does not accept multiple characters (https://webkit.org/b/124828). 54 54 if (auto codePoint = convertToSingleCodePoint(string)) { 55 // FIXME: MathMLOperatorDictionary/RenderMathMLOperator/MathOperator do not support non-BMP characters (https://webkit.org/b/122296). 56 if (U_IS_BMP(codePoint.value())) { 57 UChar character = codePoint.value(); 58 // The minus sign renders better than the hyphen sign used in some MathML formulas. 59 if (character == hyphenMinus) 60 character = minusSign; 61 operatorChar.character = character; 62 operatorChar.isVertical = MathMLOperatorDictionary::isVertical(operatorChar.character); 63 } 55 auto character = codePoint.value(); 56 // The minus sign renders better than the hyphen sign used in some MathML formulas. 57 if (character == hyphenMinus) 58 character = minusSign; 59 operatorChar.character = character; 60 operatorChar.isVertical = isVertical(operatorChar.character); 64 61 } 65 62 return operatorChar; … … 73 70 } 74 71 75 MathMLOperatorElement::DictionaryProperty MathMLOperatorElement::computeDictionaryProperty()76 { 77 DictionaryProperty dictionaryProperty;72 Property MathMLOperatorElement::computeDictionaryProperty() 73 { 74 Property dictionaryProperty; 78 75 79 76 // We first determine the form attribute and use the default spacing and properties. … … 98 95 99 96 // We then try and find an entry in the operator dictionary to override the default values. 100 if (auto entry = search(operatorChar().character, dictionaryProperty.form, explicitForm)) { 101 dictionaryProperty.form = static_cast<MathMLOperatorDictionary::Form>(entry.value().form); 102 dictionaryProperty.leadingSpaceInMathUnit = entry.value().lspace; 103 dictionaryProperty.trailingSpaceInMathUnit = entry.value().rspace; 104 dictionaryProperty.flags = entry.value().flags; 105 } 97 if (auto entry = search(operatorChar().character, dictionaryProperty.form, explicitForm)) 98 dictionaryProperty = entry.value(); 106 99 107 100 return dictionaryProperty; 108 101 } 109 102 110 const MathMLOperatorElement::DictionaryProperty& MathMLOperatorElement::dictionaryProperty()103 const Property& MathMLOperatorElement::dictionaryProperty() 111 104 { 112 105 if (!m_dictionaryProperty) -
trunk/Source/WebCore/mathml/MathMLOperatorElement.h
r204885 r205111 37 37 static Ref<MathMLOperatorElement> create(const QualifiedName& tagName, Document&); 38 38 struct OperatorChar { 39 UChar character { 0 };39 UChar32 character { 0 }; 40 40 bool isVertical { true }; 41 41 }; … … 60 60 Optional<OperatorChar> m_operatorChar; 61 61 62 struct DictionaryProperty { 63 MathMLOperatorDictionary::Form form; 64 // Default leading and trailing spaces are "thickmathspace". 65 unsigned short leadingSpaceInMathUnit { 5 }; 66 unsigned short trailingSpaceInMathUnit { 5 }; 67 // Default operator properties are all set to "false". 68 unsigned short flags { 0 }; 69 }; 70 Optional<DictionaryProperty> m_dictionaryProperty; 71 DictionaryProperty computeDictionaryProperty(); 72 const DictionaryProperty& dictionaryProperty(); 62 Optional<MathMLOperatorDictionary::Property> m_dictionaryProperty; 63 MathMLOperatorDictionary::Property computeDictionaryProperty(); 64 const MathMLOperatorDictionary::Property& dictionaryProperty(); 73 65 74 66 struct OperatorProperties { -
trunk/Source/WebCore/rendering/mathml/MathOperator.cpp
r204885 r205111 61 61 // FIXME: This hardcoded data can be removed when OpenType MATH font are widely available (http://wkbug/156837). 62 62 struct StretchyCharacter { 63 UChar character;63 UChar32 character; 64 64 UChar topChar; 65 65 UChar extensionChar; … … 86 86 }; 87 87 88 void MathOperator::setOperator(const RenderStyle& style, UChar baseCharacter, Type operatorType)88 void MathOperator::setOperator(const RenderStyle& style, UChar32 baseCharacter, Type operatorType) 89 89 { 90 90 m_baseCharacter = baseCharacter; … … 122 122 } 123 123 124 bool MathOperator::getGlyph(const RenderStyle& style, UChar character, GlyphData& glyph) const124 bool MathOperator::getGlyph(const RenderStyle& style, UChar32 character, GlyphData& glyph) const 125 125 { 126 126 glyph = style.fontCascade().glyphDataForCharacter(character, !style.isLeftToRightDirection()); … … 172 172 // However, many math fonts do not provide constructions for the non-combining equivalent. 173 173 const unsigned maxFallbackPerCharacter = 3; 174 static const UChar characterFallback[][maxFallbackPerCharacter] = {174 static const UChar32 characterFallback[][maxFallbackPerCharacter] = { 175 175 { 0x005E, 0x0302, 0 }, // CIRCUMFLEX ACCENT 176 176 { 0x005F, 0x0332, 0 }, // LOW LINE -
trunk/Source/WebCore/rendering/mathml/MathOperator.h
r204885 r205111 42 42 MathOperator() { } 43 43 enum class Type { NormalOperator, DisplayOperator, VerticalOperator, HorizontalOperator }; 44 void setOperator(const RenderStyle&, UChar baseCharacter, Type);44 void setOperator(const RenderStyle&, UChar32 baseCharacter, Type); 45 45 void reset(const RenderStyle&); 46 46 … … 74 74 75 75 LayoutUnit stretchSize() const; 76 bool getGlyph(const RenderStyle&, UChar character, GlyphData&) const;76 bool getGlyph(const RenderStyle&, UChar32 character, GlyphData&) const; 77 77 bool getBaseGlyph(const RenderStyle& style, GlyphData& baseGlyph) const { return getGlyph(style, m_baseCharacter, baseGlyph); } 78 78 void setSizeVariant(const GlyphData&); … … 89 89 void paintHorizontalGlyphAssembly(const RenderStyle&, PaintInfo&, const LayoutPoint&); 90 90 91 UChar m_baseCharacter { 0 };91 UChar32 m_baseCharacter { 0 }; 92 92 Type m_operatorType { Type::NormalOperator }; 93 93 StretchType m_stretchType { StretchType::Unstretched }; -
trunk/Source/WebCore/rendering/mathml/RenderMathMLFencedOperator.cpp
r204885 r205111 51 51 // However we preserve the Fence and Separator properties specified in the constructor. 52 52 if (auto entry = search(m_operatorChar.character, m_operatorForm, true)) { 53 m_leadingSpaceInMathUnit = entry.value().l space;54 m_trailingSpaceInMathUnit = entry.value(). rspace;53 m_leadingSpaceInMathUnit = entry.value().leadingSpaceInMathUnit; 54 m_trailingSpaceInMathUnit = entry.value().trailingSpaceInMathUnit; 55 55 m_operatorFlags = (m_operatorFlags & (MathMLOperatorDictionary::Fence | MathMLOperatorDictionary::Separator)) | entry.value().flags; 56 56 } else { -
trunk/Source/WebCore/rendering/mathml/RenderMathMLFencedOperator.h
r204075 r205111 42 42 bool isRenderMathMLFencedOperator() const final { return true; } 43 43 bool isVertical() const final { return m_operatorChar.isVertical; } 44 UChar textContent() const final { return m_operatorChar.character; }44 UChar32 textContent() const final { return m_operatorChar.character; } 45 45 LayoutUnit leadingSpace() const final; 46 46 LayoutUnit trailingSpace() const final; -
trunk/Source/WebCore/rendering/mathml/RenderMathMLOperator.cpp
r204885 r205111 63 63 } 64 64 65 UChar RenderMathMLOperator::textContent() const65 UChar32 RenderMathMLOperator::textContent() const 66 66 { 67 67 return element().operatorChar().character; … … 71 71 { 72 72 // The following operators are invisible: U+2061 FUNCTION APPLICATION, U+2062 INVISIBLE TIMES, U+2063 INVISIBLE SEPARATOR, U+2064 INVISIBLE PLUS. 73 UChar character = textContent();73 UChar32 character = textContent(); 74 74 return 0x2061 <= character && character <= 0x2064; 75 75 } -
trunk/Source/WebCore/rendering/mathml/RenderMathMLOperator.h
r204075 r205111 56 56 void updateTokenContent() final; 57 57 void updateFromElement() final; 58 virtual UChar textContent() const;58 virtual UChar32 textContent() const; 59 59 60 60 protected:
Note: See TracChangeset
for help on using the changeset viewer.