Changeset 164418 in webkit


Ignore:
Timestamp:
Feb 20, 2014 12:28:42 AM (10 years ago)
Author:
fred.wang@free.fr
Message:

Implement the MathML Operator Dictionary.
https://bugs.webkit.org/show_bug.cgi?id=99620

Reviewed by Chris Fleizach.

Source/WebCore:

The MathML Operator Dictionary is implemented and the corresponding mo
attributes are parsed. Currently, only the stretchy property is used for
the visual rendering and the fence/separators properties are used by the
accessibility code. Very basic heuristics to determine the form are also
added.

Tests: mathml/presentation/mo-form-fallback.html

mathml/presentation/mo-form-stretchy.html
mathml/presentation/mo-invalid-attributes.html

  • accessibility/AccessibilityRenderObject.cpp:

(WebCore::AccessibilityRenderObject::isMathFenceOperator):
(WebCore::AccessibilityRenderObject::isMathSeparatorOperator):

  • mathml/mathattrs.in:
  • rendering/mathml/RenderMathMLFenced.cpp:

(WebCore::RenderMathMLFenced::createMathMLOperator):
(WebCore::RenderMathMLFenced::makeFences):
(WebCore::RenderMathMLFenced::addChild):

  • rendering/mathml/RenderMathMLFenced.h:
  • rendering/mathml/RenderMathMLOperator.cpp:

(WebCore::MathMLOperatorDictionary::ExtractKey):
(WebCore::MathMLOperatorDictionary::ExtractChar):
(WebCore::RenderMathMLOperator::RenderMathMLOperator):
(WebCore::RenderMathMLOperator::setOperatorFlagFromAttribute):
(WebCore::RenderMathMLOperator::setOperatorPropertiesFromOpDictEntry):
(WebCore::RenderMathMLOperator::SetOperatorProperties):
(WebCore::RenderMathMLOperator::advanceForCharacter):
(WebCore::RenderMathMLOperator::computePreferredLogicalWidths):
(WebCore::RenderMathMLOperator::updateFromElement):
(WebCore::RenderMathMLOperator::shouldAllowStretching):
(WebCore::RenderMathMLOperator::updateStyle):

  • rendering/mathml/RenderMathMLOperator.h:

LayoutTests:

  • mathml/presentation/mo-form-fallback-expected.html: Added.
  • mathml/presentation/mo-form-fallback.html: Added.
  • mathml/presentation/mo-form-stretchy-expected.html: Added.
  • mathml/presentation/mo-form-stretchy.html: Added.
  • mathml/presentation/mo-invalid-attributes-expected.html: Added.
  • mathml/presentation/mo-invalid-attributes.html: Added.
  • mathml/presentation/mo-stretch.html: add an explicit stretchy attribute on the ∥ which is actually not a delimiter.
Location:
trunk
Files:
6 added
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r164407 r164418  
     12014-02-20  Frédéric Wang  <fred.wang@free.fr>
     2
     3        Implement the MathML Operator Dictionary.
     4        https://bugs.webkit.org/show_bug.cgi?id=99620
     5
     6        Reviewed by Chris Fleizach.
     7
     8        * mathml/presentation/mo-form-fallback-expected.html: Added.
     9        * mathml/presentation/mo-form-fallback.html: Added.
     10        * mathml/presentation/mo-form-stretchy-expected.html: Added.
     11        * mathml/presentation/mo-form-stretchy.html: Added.
     12        * mathml/presentation/mo-invalid-attributes-expected.html: Added.
     13        * mathml/presentation/mo-invalid-attributes.html: Added.
     14        * mathml/presentation/mo-stretch.html: add an explicit stretchy attribute on the &DoubleVerticalBar; which is actually not a delimiter.
     15
    1162014-02-19  Ryosuke Niwa  <rniwa@webkit.org>
    217
  • trunk/LayoutTests/mathml/presentation/mo-stretch.html

    r159219 r164418  
    1111            <mo>&LeftFloor;</mo> <mo>&RightFloor;</mo>
    1212            <mo stretchy="true">&Integral;</mo> <mo>|</mo>
    13             <mo>&Verbar;</mo> <mo>&DoubleVerticalBar;</mo>
     13            <mo>&Verbar;</mo> <mo stretchy="true">&DoubleVerticalBar;</mo>
    1414        </mrow>
    1515    </math>
     
    2626            <mo>&LeftFloor;</mo> <mo>&RightFloor;</mo>
    2727            <mo stretchy="true">&Integral;</mo> <mo>|</mo>
    28             <mo>&Verbar;</mo> <mo>&DoubleVerticalBar;</mo>
     28            <mo>&Verbar;</mo> <mo stretchy="true">&DoubleVerticalBar;</mo>
    2929            <mspace height="75px" depth="1px"/>
    3030        </mrow>
     
    3939            <mo>&LeftFloor;</mo> <mo>&RightFloor;</mo>
    4040            <mo stretchy="true">&Integral;</mo> <mo>|</mo>
    41             <mo>&Verbar;</mo> <mo>&DoubleVerticalBar;</mo>
     41            <mo>&Verbar;</mo> <mo stretchy="true">&DoubleVerticalBar;</mo>
    4242            <mspace height="50px" depth="1px"/>
    4343        </mrow>
     
    5252            <mo>&LeftFloor;</mo> <mo>&RightFloor;</mo>
    5353            <mo stretchy="true">&Integral;</mo> <mo>|</mo>
    54             <mo>&Verbar;</mo> <mo>&DoubleVerticalBar;</mo>
     54            <mo>&Verbar;</mo> <mo stretchy="true">&DoubleVerticalBar;</mo>
    5555            <mspace height="20px" depth="1px"/>
    5656        </mrow>
     
    6868            <mo>&LeftFloor;</mo> <mo>&RightFloor;</mo>
    6969            <mo stretchy="true">&Integral;</mo> <mo>|</mo>
    70             <mo>&Verbar;</mo> <mo>&DoubleVerticalBar;</mo>
     70            <mo>&Verbar;</mo> <mo stretchy="true">&DoubleVerticalBar;</mo>
    7171            <mspace height="40px" depth="1px"/>
    7272      </msqrt>
  • trunk/Source/WebCore/ChangeLog

    r164415 r164418  
     12014-02-20  Frédéric Wang  <fred.wang@free.fr>
     2
     3        Implement the MathML Operator Dictionary.
     4        https://bugs.webkit.org/show_bug.cgi?id=99620
     5
     6        Reviewed by Chris Fleizach.
     7
     8        The MathML Operator Dictionary is implemented and the corresponding mo
     9        attributes are parsed. Currently, only the stretchy property is used for
     10        the visual rendering and the fence/separators properties are used by the
     11        accessibility code. Very basic heuristics to determine the form are also
     12        added.
     13
     14        Tests: mathml/presentation/mo-form-fallback.html
     15               mathml/presentation/mo-form-stretchy.html
     16               mathml/presentation/mo-invalid-attributes.html
     17
     18        * accessibility/AccessibilityRenderObject.cpp:
     19        (WebCore::AccessibilityRenderObject::isMathFenceOperator):
     20        (WebCore::AccessibilityRenderObject::isMathSeparatorOperator):
     21        * mathml/mathattrs.in:
     22        * rendering/mathml/RenderMathMLFenced.cpp:
     23        (WebCore::RenderMathMLFenced::createMathMLOperator):
     24        (WebCore::RenderMathMLFenced::makeFences):
     25        (WebCore::RenderMathMLFenced::addChild):
     26        * rendering/mathml/RenderMathMLFenced.h:
     27        * rendering/mathml/RenderMathMLOperator.cpp:
     28        (WebCore::MathMLOperatorDictionary::ExtractKey):
     29        (WebCore::MathMLOperatorDictionary::ExtractChar):
     30        (WebCore::RenderMathMLOperator::RenderMathMLOperator):
     31        (WebCore::RenderMathMLOperator::setOperatorFlagFromAttribute):
     32        (WebCore::RenderMathMLOperator::setOperatorPropertiesFromOpDictEntry):
     33        (WebCore::RenderMathMLOperator::SetOperatorProperties):
     34        (WebCore::RenderMathMLOperator::advanceForCharacter):
     35        (WebCore::RenderMathMLOperator::computePreferredLogicalWidths):
     36        (WebCore::RenderMathMLOperator::updateFromElement):
     37        (WebCore::RenderMathMLOperator::shouldAllowStretching):
     38        (WebCore::RenderMathMLOperator::updateStyle):
     39        * rendering/mathml/RenderMathMLOperator.h:
     40
    1412014-02-19  Zalan Bujtas  <zalan@apple.com>
    242
  • trunk/Source/WebCore/accessibility/AccessibilityRenderObject.cpp

    r164358 r164418  
    34933493        return false;
    34943494
    3495     return toRenderMathMLOperator(*m_renderer).operatorType() == RenderMathMLOperator::Fence;
     3495    return toRenderMathMLOperator(*m_renderer).hasOperatorFlag(MathMLOperatorDictionary::Fence);
    34963496}
    34973497
     
    35013501        return false;
    35023502
    3503     return toRenderMathMLOperator(*m_renderer).operatorType() == RenderMathMLOperator::Separator;
     3503    return toRenderMathMLOperator(*m_renderer).hasOperatorFlag(MathMLOperatorDictionary::Separator);
    35043504}
    35053505   
  • trunk/Source/WebCore/mathml/mathattrs.in

    r162933 r164418  
    44attrsNullNamespace
    55
     6accent
    67actiontype
    78alttext
     
    1516dir
    1617encoding
     18fence
    1719fontfamily
    1820fontsize
    1921fontstyle
    2022fontweight
     23form
    2124height
     25largeop
    2226linethickness
     27lspace
    2328mathbackground
    2429mathcolor
    2530mathsize
    2631mathvariant
     32maxsize
     33minsize
     34movablelimits
    2735notation
    2836numalign
    2937open
    3038rowspan
     39rspace
     40separator
    3141selection
    3242separators
    3343src
    3444stretchy
     45symmetric
    3546subscriptshift
    3647superscriptshift
  • trunk/Source/WebCore/rendering/mathml/RenderMathMLFenced.cpp

    r161491 r164418  
    8383}
    8484
    85 RenderPtr<RenderMathMLOperator> RenderMathMLFenced::createMathMLOperator(UChar uChar, RenderMathMLOperator::OperatorType operatorType)
     85RenderPtr<RenderMathMLOperator> RenderMathMLFenced::createMathMLOperator(UChar uChar, MathMLOperatorDictionary::Form form, MathMLOperatorDictionary::Flag flag)
    8686{
    8787    auto newStyle = RenderStyle::createAnonymousStyleWithDisplay(&style(), FLEX);
    8888    newStyle.get().setFlexDirection(FlowColumn);
    89     newStyle.get().setMarginEnd(Length((operatorType == RenderMathMLOperator::Fence ? gFenceMarginEms : gSeparatorMarginEndEms) * style().fontSize(), Fixed));
    90     if (operatorType == RenderMathMLOperator::Fence)
     89    newStyle.get().setMarginEnd(Length((flag == MathMLOperatorDictionary::Fence ? gFenceMarginEms : gSeparatorMarginEndEms) * style().fontSize(), Fixed));
     90    if (flag == MathMLOperatorDictionary::Fence)
    9191        newStyle.get().setMarginStart(Length(gFenceMarginEms * style().fontSize(), Fixed));
    92     RenderPtr<RenderMathMLOperator> newOperator = createRenderer<RenderMathMLOperator>(element(), std::move(newStyle), uChar);
    93     newOperator->setOperatorType(operatorType);
     92    RenderPtr<RenderMathMLOperator> newOperator = createRenderer<RenderMathMLOperator>(element(), std::move(newStyle), uChar, form, flag);
    9493    newOperator->initializeStyle();
    9594    return newOperator;
     
    9897void RenderMathMLFenced::makeFences()
    9998{
    100     RenderPtr<RenderMathMLOperator> openFence = createMathMLOperator(m_open, RenderMathMLOperator::Fence);
     99    RenderPtr<RenderMathMLOperator> openFence = createMathMLOperator(m_open, MathMLOperatorDictionary::Prefix, MathMLOperatorDictionary::Fence);
    101100    RenderMathMLOperator* openFencePtr = openFence.get();
    102101    RenderMathMLRow::addChild(openFence.leakPtr(), firstChild());
    103102
    104     RenderPtr<RenderMathMLOperator> closeFence = createMathMLOperator(m_close, RenderMathMLOperator::Fence);
     103    RenderPtr<RenderMathMLOperator> closeFence = createMathMLOperator(m_close, MathMLOperatorDictionary::Postfix, MathMLOperatorDictionary::Fence);
    105104    m_closeFenceRenderer = closeFence.get();
    106105    RenderMathMLRow::addChild(closeFence.leakPtr());
     
    141140                separator = (*m_separators.get())[count - 1];
    142141               
    143             separatorRenderer = createMathMLOperator(separator, RenderMathMLOperator::Separator);
     142            separatorRenderer = createMathMLOperator(separator, MathMLOperatorDictionary::Infix, MathMLOperatorDictionary::Separator);
    144143        }
    145144    }
  • trunk/Source/WebCore/rendering/mathml/RenderMathMLFenced.h

    r162158 r164418  
    4848    virtual void updateFromElement() override;
    4949
    50     RenderPtr<RenderMathMLOperator> createMathMLOperator(UChar, RenderMathMLOperator::OperatorType);
     50    RenderPtr<RenderMathMLOperator> createMathMLOperator(UChar, MathMLOperatorDictionary::Form, MathMLOperatorDictionary::Flag);
    5151    void makeFences();
    5252
  • trunk/Source/WebCore/rendering/mathml/RenderMathMLOperator.cpp

    r162732 r164418  
    6464};
    6565
     66namespace MathMLOperatorDictionary {
     67
     68typedef std::pair<UChar, Form> Key;
     69inline Key ExtractKey(const Entry* entry) { return Key(entry->character, entry->form); }
     70inline UChar ExtractChar(const Entry* entry) { return entry->character; }
     71
     72// This table has been automatically generated from the Operator Dictionary of the MathML3 specification (appendix C).
     73// 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.
     74#define MATHML_OPDICT_SIZE 1041
     75static const Entry dictionary[MATHML_OPDICT_SIZE] = {
     76    { 0x21, Postfix, 1, 0, 0}, // EXCLAMATION MARK
     77    { 0x25, Infix, 3, 3, 0}, // PERCENT SIGN
     78    { 0x26, Postfix, 0, 0, 0}, // AMPERSAND
     79    { 0x27, Postfix, 0, 0, Accent}, // APOSTROPHE
     80    { 0x28, Prefix, 0, 0, Symmetric | Fence | Stretchy}, // LEFT PARENTHESIS
     81    { 0x29, Postfix, 0, 0, Symmetric | Fence | Stretchy}, // RIGHT PARENTHESIS
     82    { 0x2A, Infix, 3, 3, 0}, // ASTERISK
     83    { 0x2B, Infix, 4, 4, 0}, // PLUS SIGN
     84    { 0x2B, Prefix, 0, 1, 0}, // PLUS SIGN
     85    { 0x2C, Infix, 0, 3, Separator}, // COMMA
     86    { 0x2D, Infix, 4, 4, 0}, // HYPHEN-MINUS
     87    { 0x2D, Prefix, 0, 1, 0}, // HYPHEN-MINUS
     88    { 0x2E, Infix, 3, 3, 0}, // FULL STOP
     89    { 0x2F, Infix, 1, 1, 0}, // SOLIDUS
     90    { 0x3A, Infix, 1, 2, 0}, // COLON
     91    { 0x3B, Infix, 0, 3, Separator}, // SEMICOLON
     92    { 0x3C, Infix, 5, 5, 0}, // LESS-THAN SIGN
     93    { 0x3D, Infix, 5, 5, 0}, // EQUALS SIGN
     94    { 0x3E, Infix, 5, 5, 0}, // GREATER-THAN SIGN
     95    { 0x3F, Infix, 1, 1, 0}, // QUESTION MARK
     96    { 0x40, Infix, 1, 1, 0}, // COMMERCIAL AT
     97    { 0x5B, Prefix, 0, 0, Symmetric | Fence | Stretchy}, // LEFT SQUARE BRACKET
     98    { 0x5C, Infix, 0, 0, 0}, // REVERSE SOLIDUS
     99    { 0x5D, Postfix, 0, 0, Symmetric | Fence | Stretchy}, // RIGHT SQUARE BRACKET
     100    { 0x5E, Postfix, 0, 0, Accent | Stretchy}, // CIRCUMFLEX ACCENT
     101    { 0x5E, Infix, 1, 1, 0}, // CIRCUMFLEX ACCENT
     102    { 0x5F, Postfix, 0, 0, Accent | Stretchy}, // LOW LINE
     103    { 0x5F, Infix, 1, 1, 0}, // LOW LINE
     104    { 0x60, Postfix, 0, 0, Accent}, // GRAVE ACCENT
     105    { 0x7B, Prefix, 0, 0, Symmetric | Fence | Stretchy}, // LEFT CURLY BRACKET
     106    { 0x7C, Infix, 2, 2, Stretchy | Symmetric | Fence}, // VERTICAL LINE
     107    { 0x7C, Prefix, 0, 0, Symmetric | Fence | Stretchy}, // VERTICAL LINE
     108    { 0x7C, Postfix, 0, 0, Symmetric | Fence | Stretchy}, // VERTICAL LINE
     109    { 0x7D, Postfix, 0, 0, Symmetric | Fence | Stretchy}, // RIGHT CURLY BRACKET
     110    { 0x7E, Postfix, 0, 0, Accent | Stretchy}, // TILDE
     111    { 0xA8, Postfix, 0, 0, Accent}, // DIAERESIS
     112    { 0xAC, Prefix, 2, 1, 0}, // NOT SIGN
     113    { 0xAF, Postfix, 0, 0, Accent | Stretchy}, // MACRON
     114    { 0xB0, Postfix, 0, 0, 0}, // DEGREE SIGN
     115    { 0xB1, Infix, 4, 4, 0}, // PLUS-MINUS SIGN
     116    { 0xB1, Prefix, 0, 1, 0}, // PLUS-MINUS SIGN
     117    { 0xB4, Postfix, 0, 0, Accent}, // ACUTE ACCENT
     118    { 0xB7, Infix, 4, 4, 0}, // MIDDLE DOT
     119    { 0xB8, Postfix, 0, 0, Accent}, // CEDILLA
     120    { 0xD7, Infix, 4, 4, 0}, // MULTIPLICATION SIGN
     121    { 0xF7, Infix, 4, 4, 0}, // DIVISION SIGN
     122    { 0x2C6, Postfix, 0, 0, Accent | Stretchy}, // MODIFIER LETTER CIRCUMFLEX ACCENT
     123    { 0x2C7, Postfix, 0, 0, Accent | Stretchy}, // CARON
     124    { 0x2C9, Postfix, 0, 0, Accent | Stretchy}, // MODIFIER LETTER MACRON
     125    { 0x2CA, Postfix, 0, 0, Accent}, // MODIFIER LETTER ACUTE ACCENT
     126    { 0x2CB, Postfix, 0, 0, Accent}, // MODIFIER LETTER GRAVE ACCENT
     127    { 0x2CD, Postfix, 0, 0, Accent | Stretchy}, // MODIFIER LETTER LOW MACRON
     128    { 0x2D8, Postfix, 0, 0, Accent}, // BREVE
     129    { 0x2D9, Postfix, 0, 0, Accent}, // DOT ABOVE
     130    { 0x2DA, Postfix, 0, 0, Accent}, // RING ABOVE
     131    { 0x2DC, Postfix, 0, 0, Accent | Stretchy}, // SMALL TILDE
     132    { 0x2DD, Postfix, 0, 0, Accent}, // DOUBLE ACUTE ACCENT
     133    { 0x2F7, Postfix, 0, 0, Accent | Stretchy}, // MODIFIER LETTER LOW TILDE
     134    { 0x302, Postfix, 0, 0, Accent | Stretchy}, // COMBINING CIRCUMFLEX ACCENT
     135    { 0x311, Postfix, 0, 0, Accent}, // COMBINING INVERTED BREVE
     136    { 0x3F6, Infix, 5, 5, 0}, // GREEK REVERSED LUNATE EPSILON SYMBOL
     137    { 0x2016, Prefix, 0, 0, Fence | Stretchy}, // DOUBLE VERTICAL LINE
     138    { 0x2016, Postfix, 0, 0, Fence | Stretchy}, // DOUBLE VERTICAL LINE
     139    { 0x2018, Prefix, 0, 0, Fence}, // LEFT SINGLE QUOTATION MARK
     140    { 0x2019, Postfix, 0, 0, Fence}, // RIGHT SINGLE QUOTATION MARK
     141    { 0x201C, Prefix, 0, 0, Fence}, // LEFT DOUBLE QUOTATION MARK
     142    { 0x201D, Postfix, 0, 0, Fence}, // RIGHT DOUBLE QUOTATION MARK
     143    { 0x2022, Infix, 4, 4, 0}, // BULLET
     144    { 0x2026, Infix, 0, 0, 0}, // HORIZONTAL ELLIPSIS
     145    { 0x2032, Postfix, 0, 2, 0}, // PRIME
     146    { 0x203E, Postfix, 0, 0, Accent | Stretchy}, // OVERLINE
     147    { 0x2044, Infix, 4, 4, Stretchy}, // FRACTION SLASH
     148    { 0x2061, Infix, 0, 0, 0}, // FUNCTION APPLICATION
     149    { 0x2062, Infix, 0, 0, 0}, // INVISIBLE TIMES
     150    { 0x2063, Infix, 0, 0, Separator}, // INVISIBLE SEPARATOR
     151    { 0x2064, Infix, 0, 0, 0}, // INVISIBLE PLUS
     152    { 0x20DB, Postfix, 0, 0, Accent}, // COMBINING THREE DOTS ABOVE
     153    { 0x20DC, Postfix, 0, 0, Accent}, // COMBINING FOUR DOTS ABOVE
     154    { 0x2145, Prefix, 2, 1, 0}, // DOUBLE-STRUCK ITALIC CAPITAL D
     155    { 0x2146, Prefix, 2, 0, 0}, // DOUBLE-STRUCK ITALIC SMALL D
     156    { 0x2190, Infix, 5, 5, Accent | Stretchy}, // LEFTWARDS ARROW
     157    { 0x2191, Infix, 5, 5, Stretchy}, // UPWARDS ARROW
     158    { 0x2192, Infix, 5, 5, Stretchy | Accent}, // RIGHTWARDS ARROW
     159    { 0x2193, Infix, 5, 5, Stretchy}, // DOWNWARDS ARROW
     160    { 0x2194, Infix, 5, 5, Stretchy | Accent}, // LEFT RIGHT ARROW
     161    { 0x2195, Infix, 5, 5, Stretchy}, // UP DOWN ARROW
     162    { 0x2196, Infix, 5, 5, Stretchy}, // NORTH WEST ARROW
     163    { 0x2197, Infix, 5, 5, Stretchy}, // NORTH EAST ARROW
     164    { 0x2198, Infix, 5, 5, Stretchy}, // SOUTH EAST ARROW
     165    { 0x2199, Infix, 5, 5, Stretchy}, // SOUTH WEST ARROW
     166    { 0x219A, Infix, 5, 5, Accent}, // LEFTWARDS ARROW WITH STROKE
     167    { 0x219B, Infix, 5, 5, Accent}, // RIGHTWARDS ARROW WITH STROKE
     168    { 0x219C, Infix, 5, 5, Stretchy | Accent}, // LEFTWARDS WAVE ARROW
     169    { 0x219D, Infix, 5, 5, Stretchy | Accent}, // RIGHTWARDS WAVE ARROW
     170    { 0x219E, Infix, 5, 5, Stretchy | Accent}, // LEFTWARDS TWO HEADED ARROW
     171    { 0x219F, Infix, 5, 5, Stretchy | Accent}, // UPWARDS TWO HEADED ARROW
     172    { 0x21A0, Infix, 5, 5, Stretchy | Accent}, // RIGHTWARDS TWO HEADED ARROW
     173    { 0x21A1, Infix, 5, 5, Stretchy}, // DOWNWARDS TWO HEADED ARROW
     174    { 0x21A2, Infix, 5, 5, Stretchy | Accent}, // LEFTWARDS ARROW WITH TAIL
     175    { 0x21A3, Infix, 5, 5, Stretchy | Accent}, // RIGHTWARDS ARROW WITH TAIL
     176    { 0x21A4, Infix, 5, 5, Stretchy | Accent}, // LEFTWARDS ARROW FROM BAR
     177    { 0x21A5, Infix, 5, 5, Stretchy}, // UPWARDS ARROW FROM BAR
     178    { 0x21A6, Infix, 5, 5, Stretchy | Accent}, // RIGHTWARDS ARROW FROM BAR
     179    { 0x21A7, Infix, 5, 5, Stretchy}, // DOWNWARDS ARROW FROM BAR
     180    { 0x21A8, Infix, 5, 5, Stretchy}, // UP DOWN ARROW WITH BASE
     181    { 0x21A9, Infix, 5, 5, Stretchy | Accent}, // LEFTWARDS ARROW WITH HOOK
     182    { 0x21AA, Infix, 5, 5, Stretchy | Accent}, // RIGHTWARDS ARROW WITH HOOK
     183    { 0x21AB, Infix, 5, 5, Stretchy | Accent}, // LEFTWARDS ARROW WITH LOOP
     184    { 0x21AC, Infix, 5, 5, Stretchy | Accent}, // RIGHTWARDS ARROW WITH LOOP
     185    { 0x21AD, Infix, 5, 5, Stretchy | Accent}, // LEFT RIGHT WAVE ARROW
     186    { 0x21AE, Infix, 5, 5, Accent}, // LEFT RIGHT ARROW WITH STROKE
     187    { 0x21AF, Infix, 5, 5, Stretchy}, // DOWNWARDS ZIGZAG ARROW
     188    { 0x21B0, Infix, 5, 5, Stretchy}, // UPWARDS ARROW WITH TIP LEFTWARDS
     189    { 0x21B1, Infix, 5, 5, Stretchy}, // UPWARDS ARROW WITH TIP RIGHTWARDS
     190    { 0x21B2, Infix, 5, 5, Stretchy}, // DOWNWARDS ARROW WITH TIP LEFTWARDS
     191    { 0x21B3, Infix, 5, 5, Stretchy}, // DOWNWARDS ARROW WITH TIP RIGHTWARDS
     192    { 0x21B4, Infix, 5, 5, Stretchy}, // RIGHTWARDS ARROW WITH CORNER DOWNWARDS
     193    { 0x21B5, Infix, 5, 5, Stretchy}, // DOWNWARDS ARROW WITH CORNER LEFTWARDS
     194    { 0x21B6, Infix, 5, 5, Accent}, // ANTICLOCKWISE TOP SEMICIRCLE ARROW
     195    { 0x21B7, Infix, 5, 5, Accent}, // CLOCKWISE TOP SEMICIRCLE ARROW
     196    { 0x21B8, Infix, 5, 5, 0}, // NORTH WEST ARROW TO LONG BAR
     197    { 0x21B9, Infix, 5, 5, Stretchy | Accent}, // LEFTWARDS ARROW TO BAR OVER RIGHTWARDS ARROW TO BAR
     198    { 0x21BA, Infix, 5, 5, 0}, // ANTICLOCKWISE OPEN CIRCLE ARROW
     199    { 0x21BB, Infix, 5, 5, 0}, // CLOCKWISE OPEN CIRCLE ARROW
     200    { 0x21BC, Infix, 5, 5, Stretchy | Accent}, // LEFTWARDS HARPOON WITH BARB UPWARDS
     201    { 0x21BD, Infix, 5, 5, Stretchy | Accent}, // LEFTWARDS HARPOON WITH BARB DOWNWARDS
     202    { 0x21BE, Infix, 5, 5, Stretchy}, // UPWARDS HARPOON WITH BARB RIGHTWARDS
     203    { 0x21BF, Infix, 5, 5, Stretchy}, // UPWARDS HARPOON WITH BARB LEFTWARDS
     204    { 0x21C0, Infix, 5, 5, Stretchy | Accent}, // RIGHTWARDS HARPOON WITH BARB UPWARDS
     205    { 0x21C1, Infix, 5, 5, Stretchy | Accent}, // RIGHTWARDS HARPOON WITH BARB DOWNWARDS
     206    { 0x21C2, Infix, 5, 5, Stretchy}, // DOWNWARDS HARPOON WITH BARB RIGHTWARDS
     207    { 0x21C3, Infix, 5, 5, Stretchy}, // DOWNWARDS HARPOON WITH BARB LEFTWARDS
     208    { 0x21C4, Infix, 5, 5, Stretchy | Accent}, // RIGHTWARDS ARROW OVER LEFTWARDS ARROW
     209    { 0x21C5, Infix, 5, 5, Stretchy}, // UPWARDS ARROW LEFTWARDS OF DOWNWARDS ARROW
     210    { 0x21C6, Infix, 5, 5, Stretchy | Accent}, // LEFTWARDS ARROW OVER RIGHTWARDS ARROW
     211    { 0x21C7, Infix, 5, 5, Stretchy | Accent}, // LEFTWARDS PAIRED ARROWS
     212    { 0x21C8, Infix, 5, 5, Stretchy}, // UPWARDS PAIRED ARROWS
     213    { 0x21C9, Infix, 5, 5, Stretchy | Accent}, // RIGHTWARDS PAIRED ARROWS
     214    { 0x21CA, Infix, 5, 5, Stretchy}, // DOWNWARDS PAIRED ARROWS
     215    { 0x21CB, Infix, 5, 5, Stretchy | Accent}, // LEFTWARDS HARPOON OVER RIGHTWARDS HARPOON
     216    { 0x21CC, Infix, 5, 5, Stretchy | Accent}, // RIGHTWARDS HARPOON OVER LEFTWARDS HARPOON
     217    { 0x21CD, Infix, 5, 5, Accent}, // LEFTWARDS DOUBLE ARROW WITH STROKE
     218    { 0x21CE, Infix, 5, 5, Accent}, // LEFT RIGHT DOUBLE ARROW WITH STROKE
     219    { 0x21CF, Infix, 5, 5, Accent}, // RIGHTWARDS DOUBLE ARROW WITH STROKE
     220    { 0x21D0, Infix, 5, 5, Stretchy | Accent}, // LEFTWARDS DOUBLE ARROW
     221    { 0x21D1, Infix, 5, 5, Stretchy}, // UPWARDS DOUBLE ARROW
     222    { 0x21D2, Infix, 5, 5, Stretchy | Accent}, // RIGHTWARDS DOUBLE ARROW
     223    { 0x21D3, Infix, 5, 5, Stretchy}, // DOWNWARDS DOUBLE ARROW
     224    { 0x21D4, Infix, 5, 5, Stretchy | Accent}, // LEFT RIGHT DOUBLE ARROW
     225    { 0x21D5, Infix, 5, 5, Stretchy}, // UP DOWN DOUBLE ARROW
     226    { 0x21D6, Infix, 5, 5, Stretchy}, // NORTH WEST DOUBLE ARROW
     227    { 0x21D7, Infix, 5, 5, Stretchy}, // NORTH EAST DOUBLE ARROW
     228    { 0x21D8, Infix, 5, 5, Stretchy}, // SOUTH EAST DOUBLE ARROW
     229    { 0x21D9, Infix, 5, 5, Stretchy}, // SOUTH WEST DOUBLE ARROW
     230    { 0x21DA, Infix, 5, 5, Stretchy | Accent}, // LEFTWARDS TRIPLE ARROW
     231    { 0x21DB, Infix, 5, 5, Stretchy | Accent}, // RIGHTWARDS TRIPLE ARROW
     232    { 0x21DC, Infix, 5, 5, Stretchy | Accent}, // LEFTWARDS SQUIGGLE ARROW
     233    { 0x21DD, Infix, 5, 5, Stretchy | Accent}, // RIGHTWARDS SQUIGGLE ARROW
     234    { 0x21DE, Infix, 5, 5, 0}, // UPWARDS ARROW WITH DOUBLE STROKE
     235    { 0x21DF, Infix, 5, 5, 0}, // DOWNWARDS ARROW WITH DOUBLE STROKE
     236    { 0x21E0, Infix, 5, 5, Stretchy | Accent}, // LEFTWARDS DASHED ARROW
     237    { 0x21E1, Infix, 5, 5, Stretchy}, // UPWARDS DASHED ARROW
     238    { 0x21E2, Infix, 5, 5, Stretchy | Accent}, // RIGHTWARDS DASHED ARROW
     239    { 0x21E3, Infix, 5, 5, Stretchy}, // DOWNWARDS DASHED ARROW
     240    { 0x21E4, Infix, 5, 5, Stretchy | Accent}, // LEFTWARDS ARROW TO BAR
     241    { 0x21E5, Infix, 5, 5, Stretchy | Accent}, // RIGHTWARDS ARROW TO BAR
     242    { 0x21E6, Infix, 5, 5, Stretchy | Accent}, // LEFTWARDS WHITE ARROW
     243    { 0x21E7, Infix, 5, 5, Stretchy}, // UPWARDS WHITE ARROW
     244    { 0x21E8, Infix, 5, 5, Stretchy | Accent}, // RIGHTWARDS WHITE ARROW
     245    { 0x21E9, Infix, 5, 5, Stretchy}, // DOWNWARDS WHITE ARROW
     246    { 0x21EA, Infix, 5, 5, Stretchy}, // UPWARDS WHITE ARROW FROM BAR
     247    { 0x21EB, Infix, 5, 5, Stretchy}, // UPWARDS WHITE ARROW ON PEDESTAL
     248    { 0x21EC, Infix, 5, 5, Stretchy}, // UPWARDS WHITE ARROW ON PEDESTAL WITH HORIZONTAL BAR
     249    { 0x21ED, Infix, 5, 5, Stretchy}, // UPWARDS WHITE ARROW ON PEDESTAL WITH VERTICAL BAR
     250    { 0x21EE, Infix, 5, 5, Stretchy}, // UPWARDS WHITE DOUBLE ARROW
     251    { 0x21EF, Infix, 5, 5, Stretchy}, // UPWARDS WHITE DOUBLE ARROW ON PEDESTAL
     252    { 0x21F0, Infix, 5, 5, Stretchy | Accent}, // RIGHTWARDS WHITE ARROW FROM WALL
     253    { 0x21F1, Infix, 5, 5, 0}, // NORTH WEST ARROW TO CORNER
     254    { 0x21F2, Infix, 5, 5, 0}, // SOUTH EAST ARROW TO CORNER
     255    { 0x21F3, Infix, 5, 5, Stretchy}, // UP DOWN WHITE ARROW
     256    { 0x21F4, Infix, 5, 5, Accent}, // RIGHT ARROW WITH SMALL CIRCLE
     257    { 0x21F5, Infix, 5, 5, Stretchy}, // DOWNWARDS ARROW LEFTWARDS OF UPWARDS ARROW
     258    { 0x21F6, Infix, 5, 5, Stretchy | Accent}, // THREE RIGHTWARDS ARROWS
     259    { 0x21F7, Infix, 5, 5, Accent}, // LEFTWARDS ARROW WITH VERTICAL STROKE
     260    { 0x21F8, Infix, 5, 5, Accent}, // RIGHTWARDS ARROW WITH VERTICAL STROKE
     261    { 0x21F9, Infix, 5, 5, Accent}, // LEFT RIGHT ARROW WITH VERTICAL STROKE
     262    { 0x21FA, Infix, 5, 5, Accent}, // LEFTWARDS ARROW WITH DOUBLE VERTICAL STROKE
     263    { 0x21FB, Infix, 5, 5, Accent}, // RIGHTWARDS ARROW WITH DOUBLE VERTICAL STROKE
     264    { 0x21FC, Infix, 5, 5, Accent}, // LEFT RIGHT ARROW WITH DOUBLE VERTICAL STROKE
     265    { 0x21FD, Infix, 5, 5, Stretchy | Accent}, // LEFTWARDS OPEN-HEADED ARROW
     266    { 0x21FE, Infix, 5, 5, Stretchy | Accent}, // RIGHTWARDS OPEN-HEADED ARROW
     267    { 0x21FF, Infix, 5, 5, Stretchy | Accent}, // LEFT RIGHT OPEN-HEADED ARROW
     268    { 0x2200, Prefix, 2, 1, 0}, // FOR ALL
     269    { 0x2201, Infix, 1, 2, 0}, // COMPLEMENT
     270    { 0x2202, Prefix, 2, 1, 0}, // PARTIAL DIFFERENTIAL
     271    { 0x2203, Prefix, 2, 1, 0}, // THERE EXISTS
     272    { 0x2204, Prefix, 2, 1, 0}, // THERE DOES NOT EXIST
     273    { 0x2206, Infix, 3, 3, 0}, // INCREMENT
     274    { 0x2207, Prefix, 2, 1, 0}, // NABLA
     275    { 0x2208, Infix, 5, 5, 0}, // ELEMENT OF
     276    { 0x2209, Infix, 5, 5, 0}, // NOT AN ELEMENT OF
     277    { 0x220A, Infix, 5, 5, 0}, // SMALL ELEMENT OF
     278    { 0x220B, Infix, 5, 5, 0}, // CONTAINS AS MEMBER
     279    { 0x220C, Infix, 5, 5, 0}, // DOES NOT CONTAIN AS MEMBER
     280    { 0x220D, Infix, 5, 5, 0}, // SMALL CONTAINS AS MEMBER
     281    { 0x220E, Infix, 3, 3, 0}, // END OF PROOF
     282    { 0x220F, Prefix, 1, 2, Symmetric | LargeOp | MovableLimits}, // N-ARY PRODUCT
     283    { 0x2210, Prefix, 1, 2, Symmetric | LargeOp | MovableLimits}, // N-ARY COPRODUCT
     284    { 0x2211, Prefix, 1, 2, Symmetric | LargeOp | MovableLimits}, // N-ARY SUMMATION
     285    { 0x2212, Infix, 4, 4, 0}, // MINUS SIGN
     286    { 0x2212, Prefix, 0, 1, 0}, // MINUS SIGN
     287    { 0x2213, Infix, 4, 4, 0}, // MINUS-OR-PLUS SIGN
     288    { 0x2213, Prefix, 0, 1, 0}, // MINUS-OR-PLUS SIGN
     289    { 0x2214, Infix, 4, 4, 0}, // DOT PLUS
     290    { 0x2215, Infix, 4, 4, Stretchy}, // DIVISION SLASH
     291    { 0x2216, Infix, 4, 4, 0}, // SET MINUS
     292    { 0x2217, Infix, 4, 4, 0}, // ASTERISK OPERATOR
     293    { 0x2218, Infix, 4, 4, 0}, // RING OPERATOR
     294    { 0x2219, Infix, 4, 4, 0}, // BULLET OPERATOR
     295    { 0x221A, Prefix, 1, 1, Stretchy}, // SQUARE ROOT
     296    { 0x221B, Prefix, 1, 1, 0}, // CUBE ROOT
     297    { 0x221C, Prefix, 1, 1, 0}, // FOURTH ROOT
     298    { 0x221D, Infix, 5, 5, 0}, // PROPORTIONAL TO
     299    { 0x221F, Infix, 5, 5, 0}, // RIGHT ANGLE
     300    { 0x2220, Prefix, 0, 0, 0}, // ANGLE
     301    { 0x2221, Prefix, 0, 0, 0}, // MEASURED ANGLE
     302    { 0x2222, Prefix, 0, 0, 0}, // SPHERICAL ANGLE
     303    { 0x2223, Infix, 5, 5, 0}, // DIVIDES
     304    { 0x2224, Infix, 5, 5, 0}, // DOES NOT DIVIDE
     305    { 0x2225, Infix, 5, 5, 0}, // PARALLEL TO
     306    { 0x2225, Prefix, 0, 0, Symmetric | Fence | Stretchy}, // PARALLEL TO
     307    { 0x2225, Postfix, 0, 0, Symmetric | Fence | Stretchy}, // PARALLEL TO
     308    { 0x2226, Infix, 5, 5, 0}, // NOT PARALLEL TO
     309    { 0x2227, Infix, 4, 4, 0}, // LOGICAL AND
     310    { 0x2228, Infix, 4, 4, 0}, // LOGICAL OR
     311    { 0x2229, Infix, 4, 4, 0}, // INTERSECTION
     312    { 0x222A, Infix, 4, 4, 0}, // UNION
     313    { 0x222B, Prefix, 0, 1, Symmetric | LargeOp}, // INTEGRAL
     314    { 0x222C, Prefix, 0, 1, Symmetric | LargeOp}, // DOUBLE INTEGRAL
     315    { 0x222D, Prefix, 0, 1, Symmetric | LargeOp}, // TRIPLE INTEGRAL
     316    { 0x222E, Prefix, 0, 1, Symmetric | LargeOp}, // CONTOUR INTEGRAL
     317    { 0x222F, Prefix, 0, 1, Symmetric | LargeOp}, // SURFACE INTEGRAL
     318    { 0x2230, Prefix, 0, 1, Symmetric | LargeOp}, // VOLUME INTEGRAL
     319    { 0x2231, Prefix, 0, 1, Symmetric | LargeOp}, // CLOCKWISE INTEGRAL
     320    { 0x2232, Prefix, 0, 1, Symmetric | LargeOp}, // CLOCKWISE CONTOUR INTEGRAL
     321    { 0x2233, Prefix, 0, 1, Symmetric | LargeOp}, // ANTICLOCKWISE CONTOUR INTEGRAL
     322    { 0x2234, Infix, 5, 5, 0}, // THEREFORE
     323    { 0x2235, Infix, 5, 5, 0}, // BECAUSE
     324    { 0x2236, Infix, 5, 5, 0}, // RATIO
     325    { 0x2237, Infix, 5, 5, 0}, // PROPORTION
     326    { 0x2238, Infix, 4, 4, 0}, // DOT MINUS
     327    { 0x2239, Infix, 5, 5, 0}, // EXCESS
     328    { 0x223A, Infix, 4, 4, 0}, // GEOMETRIC PROPORTION
     329    { 0x223B, Infix, 5, 5, 0}, // HOMOTHETIC
     330    { 0x223C, Infix, 5, 5, 0}, // TILDE OPERATOR
     331    { 0x223D, Infix, 5, 5, 0}, // REVERSED TILDE
     332    { 0x223E, Infix, 5, 5, 0}, // INVERTED LAZY S
     333    { 0x223F, Infix, 3, 3, 0}, // SINE WAVE
     334    { 0x2240, Infix, 4, 4, 0}, // WREATH PRODUCT
     335    { 0x2241, Infix, 5, 5, 0}, // NOT TILDE
     336    { 0x2242, Infix, 5, 5, 0}, // MINUS TILDE
     337    { 0x2243, Infix, 5, 5, 0}, // ASYMPTOTICALLY EQUAL TO
     338    { 0x2244, Infix, 5, 5, 0}, // NOT ASYMPTOTICALLY EQUAL TO
     339    { 0x2245, Infix, 5, 5, 0}, // APPROXIMATELY EQUAL TO
     340    { 0x2246, Infix, 5, 5, 0}, // APPROXIMATELY BUT NOT ACTUALLY EQUAL TO
     341    { 0x2247, Infix, 5, 5, 0}, // NEITHER APPROXIMATELY NOR ACTUALLY EQUAL TO
     342    { 0x2248, Infix, 5, 5, 0}, // ALMOST EQUAL TO
     343    { 0x2249, Infix, 5, 5, 0}, // NOT ALMOST EQUAL TO
     344    { 0x224A, Infix, 5, 5, 0}, // ALMOST EQUAL OR EQUAL TO
     345    { 0x224B, Infix, 5, 5, 0}, // TRIPLE TILDE
     346    { 0x224C, Infix, 5, 5, 0}, // ALL EQUAL TO
     347    { 0x224D, Infix, 5, 5, 0}, // EQUIVALENT TO
     348    { 0x224E, Infix, 5, 5, 0}, // GEOMETRICALLY EQUIVALENT TO
     349    { 0x224F, Infix, 5, 5, 0}, // DIFFERENCE BETWEEN
     350    { 0x2250, Infix, 5, 5, 0}, // APPROACHES THE LIMIT
     351    { 0x2251, Infix, 5, 5, 0}, // GEOMETRICALLY EQUAL TO
     352    { 0x2252, Infix, 5, 5, 0}, // APPROXIMATELY EQUAL TO OR THE IMAGE OF
     353    { 0x2253, Infix, 5, 5, 0}, // IMAGE OF OR APPROXIMATELY EQUAL TO
     354    { 0x2254, Infix, 5, 5, 0}, // COLON EQUALS
     355    { 0x2255, Infix, 5, 5, 0}, // EQUALS COLON
     356    { 0x2256, Infix, 5, 5, 0}, // RING IN EQUAL TO
     357    { 0x2257, Infix, 5, 5, 0}, // RING EQUAL TO
     358    { 0x2258, Infix, 5, 5, 0}, // CORRESPONDS TO
     359    { 0x2259, Infix, 5, 5, 0}, // ESTIMATES
     360    { 0x225A, Infix, 5, 5, 0}, // EQUIANGULAR TO
     361    { 0x225C, Infix, 5, 5, 0}, // DELTA EQUAL TO
     362    { 0x225D, Infix, 5, 5, 0}, // EQUAL TO BY DEFINITION
     363    { 0x225E, Infix, 5, 5, 0}, // MEASURED BY
     364    { 0x225F, Infix, 5, 5, 0}, // QUESTIONED EQUAL TO
     365    { 0x2260, Infix, 5, 5, 0}, // NOT EQUAL TO
     366    { 0x2261, Infix, 5, 5, 0}, // IDENTICAL TO
     367    { 0x2262, Infix, 5, 5, 0}, // NOT IDENTICAL TO
     368    { 0x2263, Infix, 5, 5, 0}, // STRICTLY EQUIVALENT TO
     369    { 0x2264, Infix, 5, 5, 0}, // LESS-THAN OR EQUAL TO
     370    { 0x2265, Infix, 5, 5, 0}, // GREATER-THAN OR EQUAL TO
     371    { 0x2266, Infix, 5, 5, 0}, // LESS-THAN OVER EQUAL TO
     372    { 0x2267, Infix, 5, 5, 0}, // GREATER-THAN OVER EQUAL TO
     373    { 0x2268, Infix, 5, 5, 0}, // LESS-THAN BUT NOT EQUAL TO
     374    { 0x2269, Infix, 5, 5, 0}, // GREATER-THAN BUT NOT EQUAL TO
     375    { 0x226A, Infix, 5, 5, 0}, // MUCH LESS-THAN
     376    { 0x226B, Infix, 5, 5, 0}, // MUCH GREATER-THAN
     377    { 0x226C, Infix, 5, 5, 0}, // BETWEEN
     378    { 0x226D, Infix, 5, 5, 0}, // NOT EQUIVALENT TO
     379    { 0x226E, Infix, 5, 5, 0}, // NOT LESS-THAN
     380    { 0x226F, Infix, 5, 5, 0}, // NOT GREATER-THAN
     381    { 0x2270, Infix, 5, 5, 0}, // NEITHER LESS-THAN NOR EQUAL TO
     382    { 0x2271, Infix, 5, 5, 0}, // NEITHER GREATER-THAN NOR EQUAL TO
     383    { 0x2272, Infix, 5, 5, 0}, // LESS-THAN OR EQUIVALENT TO
     384    { 0x2273, Infix, 5, 5, 0}, // GREATER-THAN OR EQUIVALENT TO
     385    { 0x2274, Infix, 5, 5, 0}, // NEITHER LESS-THAN NOR EQUIVALENT TO
     386    { 0x2275, Infix, 5, 5, 0}, // NEITHER GREATER-THAN NOR EQUIVALENT TO
     387    { 0x2276, Infix, 5, 5, 0}, // LESS-THAN OR GREATER-THAN
     388    { 0x2277, Infix, 5, 5, 0}, // GREATER-THAN OR LESS-THAN
     389    { 0x2278, Infix, 5, 5, 0}, // NEITHER LESS-THAN NOR GREATER-THAN
     390    { 0x2279, Infix, 5, 5, 0}, // NEITHER GREATER-THAN NOR LESS-THAN
     391    { 0x227A, Infix, 5, 5, 0}, // PRECEDES
     392    { 0x227B, Infix, 5, 5, 0}, // SUCCEEDS
     393    { 0x227C, Infix, 5, 5, 0}, // PRECEDES OR EQUAL TO
     394    { 0x227D, Infix, 5, 5, 0}, // SUCCEEDS OR EQUAL TO
     395    { 0x227E, Infix, 5, 5, 0}, // PRECEDES OR EQUIVALENT TO
     396    { 0x227F, Infix, 5, 5, 0}, // SUCCEEDS OR EQUIVALENT TO
     397    { 0x2280, Infix, 5, 5, 0}, // DOES NOT PRECEDE
     398    { 0x2281, Infix, 5, 5, 0}, // DOES NOT SUCCEED
     399    { 0x2282, Infix, 5, 5, 0}, // SUBSET OF
     400    { 0x2283, Infix, 5, 5, 0}, // SUPERSET OF
     401    { 0x2284, Infix, 5, 5, 0}, // NOT A SUBSET OF
     402    { 0x2285, Infix, 5, 5, 0}, // NOT A SUPERSET OF
     403    { 0x2286, Infix, 5, 5, 0}, // SUBSET OF OR EQUAL TO
     404    { 0x2287, Infix, 5, 5, 0}, // SUPERSET OF OR EQUAL TO
     405    { 0x2288, Infix, 5, 5, 0}, // NEITHER A SUBSET OF NOR EQUAL TO
     406    { 0x2289, Infix, 5, 5, 0}, // NEITHER A SUPERSET OF NOR EQUAL TO
     407    { 0x228A, Infix, 5, 5, 0}, // SUBSET OF WITH NOT EQUAL TO
     408    { 0x228B, Infix, 5, 5, 0}, // SUPERSET OF WITH NOT EQUAL TO
     409    { 0x228C, Infix, 4, 4, 0}, // MULTISET
     410    { 0x228D, Infix, 4, 4, 0}, // MULTISET MULTIPLICATION
     411    { 0x228E, Infix, 4, 4, 0}, // MULTISET UNION
     412    { 0x228F, Infix, 5, 5, 0}, // SQUARE IMAGE OF
     413    { 0x2290, Infix, 5, 5, 0}, // SQUARE ORIGINAL OF
     414    { 0x2291, Infix, 5, 5, 0}, // SQUARE IMAGE OF OR EQUAL TO
     415    { 0x2292, Infix, 5, 5, 0}, // SQUARE ORIGINAL OF OR EQUAL TO
     416    { 0x2293, Infix, 4, 4, 0}, // SQUARE CAP
     417    { 0x2294, Infix, 4, 4, 0}, // SQUARE CUP
     418    { 0x2295, Infix, 4, 4, 0}, // CIRCLED PLUS
     419    { 0x2296, Infix, 4, 4, 0}, // CIRCLED MINUS
     420    { 0x2297, Infix, 4, 4, 0}, // CIRCLED TIMES
     421    { 0x2298, Infix, 4, 4, 0}, // CIRCLED DIVISION SLASH
     422    { 0x2299, Infix, 4, 4, 0}, // CIRCLED DOT OPERATOR
     423    { 0x229A, Infix, 4, 4, 0}, // CIRCLED RING OPERATOR
     424    { 0x229B, Infix, 4, 4, 0}, // CIRCLED ASTERISK OPERATOR
     425    { 0x229C, Infix, 4, 4, 0}, // CIRCLED EQUALS
     426    { 0x229D, Infix, 4, 4, 0}, // CIRCLED DASH
     427    { 0x229E, Infix, 4, 4, 0}, // SQUARED PLUS
     428    { 0x229F, Infix, 4, 4, 0}, // SQUARED MINUS
     429    { 0x22A0, Infix, 4, 4, 0}, // SQUARED TIMES
     430    { 0x22A1, Infix, 4, 4, 0}, // SQUARED DOT OPERATOR
     431    { 0x22A2, Infix, 5, 5, 0}, // RIGHT TACK
     432    { 0x22A3, Infix, 5, 5, 0}, // LEFT TACK
     433    { 0x22A4, Infix, 5, 5, 0}, // DOWN TACK
     434    { 0x22A5, Infix, 5, 5, 0}, // UP TACK
     435    { 0x22A6, Infix, 5, 5, 0}, // ASSERTION
     436    { 0x22A7, Infix, 5, 5, 0}, // MODELS
     437    { 0x22A8, Infix, 5, 5, 0}, // TRUE
     438    { 0x22A9, Infix, 5, 5, 0}, // FORCES
     439    { 0x22AA, Infix, 5, 5, 0}, // TRIPLE VERTICAL BAR RIGHT TURNSTILE
     440    { 0x22AB, Infix, 5, 5, 0}, // DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE
     441    { 0x22AC, Infix, 5, 5, 0}, // DOES NOT PROVE
     442    { 0x22AD, Infix, 5, 5, 0}, // NOT TRUE
     443    { 0x22AE, Infix, 5, 5, 0}, // DOES NOT FORCE
     444    { 0x22AF, Infix, 5, 5, 0}, // NEGATED DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE
     445    { 0x22B0, Infix, 5, 5, 0}, // PRECEDES UNDER RELATION
     446    { 0x22B1, Infix, 5, 5, 0}, // SUCCEEDS UNDER RELATION
     447    { 0x22B2, Infix, 5, 5, 0}, // NORMAL SUBGROUP OF
     448    { 0x22B3, Infix, 5, 5, 0}, // CONTAINS AS NORMAL SUBGROUP
     449    { 0x22B4, Infix, 5, 5, 0}, // NORMAL SUBGROUP OF OR EQUAL TO
     450    { 0x22B5, Infix, 5, 5, 0}, // CONTAINS AS NORMAL SUBGROUP OR EQUAL TO
     451    { 0x22B6, Infix, 5, 5, 0}, // ORIGINAL OF
     452    { 0x22B7, Infix, 5, 5, 0}, // IMAGE OF
     453    { 0x22B8, Infix, 5, 5, 0}, // MULTIMAP
     454    { 0x22B9, Infix, 5, 5, 0}, // HERMITIAN CONJUGATE MATRIX
     455    { 0x22BA, Infix, 4, 4, 0}, // INTERCALATE
     456    { 0x22BB, Infix, 4, 4, 0}, // XOR
     457    { 0x22BC, Infix, 4, 4, 0}, // NAND
     458    { 0x22BD, Infix, 4, 4, 0}, // NOR
     459    { 0x22BE, Infix, 3, 3, 0}, // RIGHT ANGLE WITH ARC
     460    { 0x22BF, Infix, 3, 3, 0}, // RIGHT TRIANGLE
     461    { 0x22C0, Prefix, 1, 2, Symmetric | LargeOp | MovableLimits}, // N-ARY LOGICAL AND
     462    { 0x22C1, Prefix, 1, 2, Symmetric | LargeOp | MovableLimits}, // N-ARY LOGICAL OR
     463    { 0x22C2, Prefix, 1, 2, Symmetric | LargeOp | MovableLimits}, // N-ARY INTERSECTION
     464    { 0x22C3, Prefix, 1, 2, Symmetric | LargeOp | MovableLimits}, // N-ARY UNION
     465    { 0x22C4, Infix, 4, 4, 0}, // DIAMOND OPERATOR
     466    { 0x22C5, Infix, 4, 4, 0}, // DOT OPERATOR
     467    { 0x22C6, Infix, 4, 4, 0}, // STAR OPERATOR
     468    { 0x22C7, Infix, 4, 4, 0}, // DIVISION TIMES
     469    { 0x22C8, Infix, 5, 5, 0}, // BOWTIE
     470    { 0x22C9, Infix, 4, 4, 0}, // LEFT NORMAL FACTOR SEMIDIRECT PRODUCT
     471    { 0x22CA, Infix, 4, 4, 0}, // RIGHT NORMAL FACTOR SEMIDIRECT PRODUCT
     472    { 0x22CB, Infix, 4, 4, 0}, // LEFT SEMIDIRECT PRODUCT
     473    { 0x22CC, Infix, 4, 4, 0}, // RIGHT SEMIDIRECT PRODUCT
     474    { 0x22CD, Infix, 5, 5, 0}, // REVERSED TILDE EQUALS
     475    { 0x22CE, Infix, 4, 4, 0}, // CURLY LOGICAL OR
     476    { 0x22CF, Infix, 4, 4, 0}, // CURLY LOGICAL AND
     477    { 0x22D0, Infix, 5, 5, 0}, // DOUBLE SUBSET
     478    { 0x22D1, Infix, 5, 5, 0}, // DOUBLE SUPERSET
     479    { 0x22D2, Infix, 4, 4, 0}, // DOUBLE INTERSECTION
     480    { 0x22D3, Infix, 4, 4, 0}, // DOUBLE UNION
     481    { 0x22D4, Infix, 5, 5, 0}, // PITCHFORK
     482    { 0x22D5, Infix, 5, 5, 0}, // EQUAL AND PARALLEL TO
     483    { 0x22D6, Infix, 5, 5, 0}, // LESS-THAN WITH DOT
     484    { 0x22D7, Infix, 5, 5, 0}, // GREATER-THAN WITH DOT
     485    { 0x22D8, Infix, 5, 5, 0}, // VERY MUCH LESS-THAN
     486    { 0x22D9, Infix, 5, 5, 0}, // VERY MUCH GREATER-THAN
     487    { 0x22DA, Infix, 5, 5, 0}, // LESS-THAN EQUAL TO OR GREATER-THAN
     488    { 0x22DB, Infix, 5, 5, 0}, // GREATER-THAN EQUAL TO OR LESS-THAN
     489    { 0x22DC, Infix, 5, 5, 0}, // EQUAL TO OR LESS-THAN
     490    { 0x22DD, Infix, 5, 5, 0}, // EQUAL TO OR GREATER-THAN
     491    { 0x22DE, Infix, 5, 5, 0}, // EQUAL TO OR PRECEDES
     492    { 0x22DF, Infix, 5, 5, 0}, // EQUAL TO OR SUCCEEDS
     493    { 0x22E0, Infix, 5, 5, 0}, // DOES NOT PRECEDE OR EQUAL
     494    { 0x22E1, Infix, 5, 5, 0}, // DOES NOT SUCCEED OR EQUAL
     495    { 0x22E2, Infix, 5, 5, 0}, // NOT SQUARE IMAGE OF OR EQUAL TO
     496    { 0x22E3, Infix, 5, 5, 0}, // NOT SQUARE ORIGINAL OF OR EQUAL TO
     497    { 0x22E4, Infix, 5, 5, 0}, // SQUARE IMAGE OF OR NOT EQUAL TO
     498    { 0x22E5, Infix, 5, 5, 0}, // SQUARE ORIGINAL OF OR NOT EQUAL TO
     499    { 0x22E6, Infix, 5, 5, 0}, // LESS-THAN BUT NOT EQUIVALENT TO
     500    { 0x22E7, Infix, 5, 5, 0}, // GREATER-THAN BUT NOT EQUIVALENT TO
     501    { 0x22E8, Infix, 5, 5, 0}, // PRECEDES BUT NOT EQUIVALENT TO
     502    { 0x22E9, Infix, 5, 5, 0}, // SUCCEEDS BUT NOT EQUIVALENT TO
     503    { 0x22EA, Infix, 5, 5, 0}, // NOT NORMAL SUBGROUP OF
     504    { 0x22EB, Infix, 5, 5, 0}, // DOES NOT CONTAIN AS NORMAL SUBGROUP
     505    { 0x22EC, Infix, 5, 5, 0}, // NOT NORMAL SUBGROUP OF OR EQUAL TO
     506    { 0x22ED, Infix, 5, 5, 0}, // DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL
     507    { 0x22EE, Infix, 5, 5, 0}, // VERTICAL ELLIPSIS
     508    { 0x22EF, Infix, 0, 0, 0}, // MIDLINE HORIZONTAL ELLIPSIS
     509    { 0x22F0, Infix, 5, 5, 0}, // UP RIGHT DIAGONAL ELLIPSIS
     510    { 0x22F1, Infix, 5, 5, 0}, // DOWN RIGHT DIAGONAL ELLIPSIS
     511    { 0x22F2, Infix, 5, 5, 0}, // ELEMENT OF WITH LONG HORIZONTAL STROKE
     512    { 0x22F3, Infix, 5, 5, 0}, // ELEMENT OF WITH VERTICAL BAR AT END OF HORIZONTAL STROKE
     513    { 0x22F4, Infix, 5, 5, 0}, // SMALL ELEMENT OF WITH VERTICAL BAR AT END OF HORIZONTAL STROKE
     514    { 0x22F5, Infix, 5, 5, 0}, // ELEMENT OF WITH DOT ABOVE
     515    { 0x22F6, Infix, 5, 5, 0}, // ELEMENT OF WITH OVERBAR
     516    { 0x22F7, Infix, 5, 5, 0}, // SMALL ELEMENT OF WITH OVERBAR
     517    { 0x22F8, Infix, 5, 5, 0}, // ELEMENT OF WITH UNDERBAR
     518    { 0x22F9, Infix, 5, 5, 0}, // ELEMENT OF WITH TWO HORIZONTAL STROKES
     519    { 0x22FA, Infix, 5, 5, 0}, // CONTAINS WITH LONG HORIZONTAL STROKE
     520    { 0x22FB, Infix, 5, 5, 0}, // CONTAINS WITH VERTICAL BAR AT END OF HORIZONTAL STROKE
     521    { 0x22FC, Infix, 5, 5, 0}, // SMALL CONTAINS WITH VERTICAL BAR AT END OF HORIZONTAL STROKE
     522    { 0x22FD, Infix, 5, 5, 0}, // CONTAINS WITH OVERBAR
     523    { 0x22FE, Infix, 5, 5, 0}, // SMALL CONTAINS WITH OVERBAR
     524    { 0x22FF, Infix, 5, 5, 0}, // Z NOTATION BAG MEMBERSHIP
     525    { 0x2308, Prefix, 0, 0, Symmetric | Fence | Stretchy}, // LEFT CEILING
     526    { 0x2309, Postfix, 0, 0, Symmetric | Fence | Stretchy}, // RIGHT CEILING
     527    { 0x230A, Prefix, 0, 0, Symmetric | Fence | Stretchy}, // LEFT FLOOR
     528    { 0x230B, Postfix, 0, 0, Symmetric | Fence | Stretchy}, // RIGHT FLOOR
     529    { 0x23B4, Postfix, 0, 0, Accent | Stretchy}, // TOP SQUARE BRACKET
     530    { 0x23B5, Postfix, 0, 0, Accent | Stretchy}, // BOTTOM SQUARE BRACKET
     531    { 0x23DC, Postfix, 0, 0, Accent | Stretchy}, // TOP PARENTHESIS
     532    { 0x23DD, Postfix, 0, 0, Accent | Stretchy}, // BOTTOM PARENTHESIS
     533    { 0x23DE, Postfix, 0, 0, Accent | Stretchy}, // TOP CURLY BRACKET
     534    { 0x23DF, Postfix, 0, 0, Accent | Stretchy}, // BOTTOM CURLY BRACKET
     535    { 0x23E0, Postfix, 0, 0, Accent | Stretchy}, // TOP TORTOISE SHELL BRACKET
     536    { 0x23E1, Postfix, 0, 0, Accent | Stretchy}, // BOTTOM TORTOISE SHELL BRACKET
     537    { 0x25A0, Infix, 3, 3, 0}, // BLACK SQUARE
     538    { 0x25A1, Infix, 3, 3, 0}, // WHITE SQUARE
     539    { 0x25AA, Infix, 3, 3, 0}, // BLACK SMALL SQUARE
     540    { 0x25AB, Infix, 3, 3, 0}, // WHITE SMALL SQUARE
     541    { 0x25AD, Infix, 3, 3, 0}, // WHITE RECTANGLE
     542    { 0x25AE, Infix, 3, 3, 0}, // BLACK VERTICAL RECTANGLE
     543    { 0x25AF, Infix, 3, 3, 0}, // WHITE VERTICAL RECTANGLE
     544    { 0x25B0, Infix, 3, 3, 0}, // BLACK PARALLELOGRAM
     545    { 0x25B1, Infix, 3, 3, 0}, // WHITE PARALLELOGRAM
     546    { 0x25B2, Infix, 4, 4, 0}, // BLACK UP-POINTING TRIANGLE
     547    { 0x25B3, Infix, 4, 4, 0}, // WHITE UP-POINTING TRIANGLE
     548    { 0x25B4, Infix, 4, 4, 0}, // BLACK UP-POINTING SMALL TRIANGLE
     549    { 0x25B5, Infix, 4, 4, 0}, // WHITE UP-POINTING SMALL TRIANGLE
     550    { 0x25B6, Infix, 4, 4, 0}, // BLACK RIGHT-POINTING TRIANGLE
     551    { 0x25B7, Infix, 4, 4, 0}, // WHITE RIGHT-POINTING TRIANGLE
     552    { 0x25B8, Infix, 4, 4, 0}, // BLACK RIGHT-POINTING SMALL TRIANGLE
     553    { 0x25B9, Infix, 4, 4, 0}, // WHITE RIGHT-POINTING SMALL TRIANGLE
     554    { 0x25BC, Infix, 4, 4, 0}, // BLACK DOWN-POINTING TRIANGLE
     555    { 0x25BD, Infix, 4, 4, 0}, // WHITE DOWN-POINTING TRIANGLE
     556    { 0x25BE, Infix, 4, 4, 0}, // BLACK DOWN-POINTING SMALL TRIANGLE
     557    { 0x25BF, Infix, 4, 4, 0}, // WHITE DOWN-POINTING SMALL TRIANGLE
     558    { 0x25C0, Infix, 4, 4, 0}, // BLACK LEFT-POINTING TRIANGLE
     559    { 0x25C1, Infix, 4, 4, 0}, // WHITE LEFT-POINTING TRIANGLE
     560    { 0x25C2, Infix, 4, 4, 0}, // BLACK LEFT-POINTING SMALL TRIANGLE
     561    { 0x25C3, Infix, 4, 4, 0}, // WHITE LEFT-POINTING SMALL TRIANGLE
     562    { 0x25C4, Infix, 4, 4, 0}, // BLACK LEFT-POINTING POINTER
     563    { 0x25C5, Infix, 4, 4, 0}, // WHITE LEFT-POINTING POINTER
     564    { 0x25C6, Infix, 4, 4, 0}, // BLACK DIAMOND
     565    { 0x25C7, Infix, 4, 4, 0}, // WHITE DIAMOND
     566    { 0x25C8, Infix, 4, 4, 0}, // WHITE DIAMOND CONTAINING BLACK SMALL DIAMOND
     567    { 0x25C9, Infix, 4, 4, 0}, // FISHEYE
     568    { 0x25CC, Infix, 4, 4, 0}, // DOTTED CIRCLE
     569    { 0x25CD, Infix, 4, 4, 0}, // CIRCLE WITH VERTICAL FILL
     570    { 0x25CE, Infix, 4, 4, 0}, // BULLSEYE
     571    { 0x25CF, Infix, 4, 4, 0}, // BLACK CIRCLE
     572    { 0x25D6, Infix, 4, 4, 0}, // LEFT HALF BLACK CIRCLE
     573    { 0x25D7, Infix, 4, 4, 0}, // RIGHT HALF BLACK CIRCLE
     574    { 0x25E6, Infix, 4, 4, 0}, // WHITE BULLET
     575    { 0x266D, Postfix, 0, 2, 0}, // MUSIC FLAT SIGN
     576    { 0x266E, Postfix, 0, 2, 0}, // MUSIC NATURAL SIGN
     577    { 0x266F, Postfix, 0, 2, 0}, // MUSIC SHARP SIGN
     578    { 0x2758, Infix, 5, 5, 0}, // LIGHT VERTICAL BAR
     579    { 0x2772, Prefix, 0, 0, Symmetric | Fence | Stretchy}, // LIGHT LEFT TORTOISE SHELL BRACKET ORNAMENT
     580    { 0x2773, Postfix, 0, 0, Symmetric | Fence | Stretchy}, // LIGHT RIGHT TORTOISE SHELL BRACKET ORNAMENT
     581    { 0x27E6, Prefix, 0, 0, Symmetric | Fence | Stretchy}, // MATHEMATICAL LEFT WHITE SQUARE BRACKET
     582    { 0x27E7, Postfix, 0, 0, Symmetric | Fence | Stretchy}, // MATHEMATICAL RIGHT WHITE SQUARE BRACKET
     583    { 0x27E8, Prefix, 0, 0, Symmetric | Fence | Stretchy}, // MATHEMATICAL LEFT ANGLE BRACKET
     584    { 0x27E9, Postfix, 0, 0, Symmetric | Fence | Stretchy}, // MATHEMATICAL RIGHT ANGLE BRACKET
     585    { 0x27EA, Prefix, 0, 0, Symmetric | Fence | Stretchy}, // MATHEMATICAL LEFT DOUBLE ANGLE BRACKET
     586    { 0x27EB, Postfix, 0, 0, Symmetric | Fence | Stretchy}, // MATHEMATICAL RIGHT DOUBLE ANGLE BRACKET
     587    { 0x27EC, Prefix, 0, 0, Symmetric | Fence | Stretchy}, // MATHEMATICAL LEFT WHITE TORTOISE SHELL BRACKET
     588    { 0x27ED, Postfix, 0, 0, Symmetric | Fence | Stretchy}, // MATHEMATICAL RIGHT WHITE TORTOISE SHELL BRACKET
     589    { 0x27EE, Prefix, 0, 0, Symmetric | Fence | Stretchy}, // MATHEMATICAL LEFT FLATTENED PARENTHESIS
     590    { 0x27EF, Postfix, 0, 0, Symmetric | Fence | Stretchy}, // MATHEMATICAL RIGHT FLATTENED PARENTHESIS
     591    { 0x27F0, Infix, 5, 5, Stretchy}, // UPWARDS QUADRUPLE ARROW
     592    { 0x27F1, Infix, 5, 5, Stretchy}, // DOWNWARDS QUADRUPLE ARROW
     593    { 0x27F5, Infix, 5, 5, Stretchy | Accent}, // LONG LEFTWARDS ARROW
     594    { 0x27F6, Infix, 5, 5, Stretchy | Accent}, // LONG RIGHTWARDS ARROW
     595    { 0x27F7, Infix, 5, 5, Stretchy | Accent}, // LONG LEFT RIGHT ARROW
     596    { 0x27F8, Infix, 5, 5, Stretchy | Accent}, // LONG LEFTWARDS DOUBLE ARROW
     597    { 0x27F9, Infix, 5, 5, Stretchy | Accent}, // LONG RIGHTWARDS DOUBLE ARROW
     598    { 0x27FA, Infix, 5, 5, Stretchy | Accent}, // LONG LEFT RIGHT DOUBLE ARROW
     599    { 0x27FB, Infix, 5, 5, Stretchy | Accent}, // LONG LEFTWARDS ARROW FROM BAR
     600    { 0x27FC, Infix, 5, 5, Stretchy | Accent}, // LONG RIGHTWARDS ARROW FROM BAR
     601    { 0x27FD, Infix, 5, 5, Stretchy | Accent}, // LONG LEFTWARDS DOUBLE ARROW FROM BAR
     602    { 0x27FE, Infix, 5, 5, Stretchy | Accent}, // LONG RIGHTWARDS DOUBLE ARROW FROM BAR
     603    { 0x27FF, Infix, 5, 5, Stretchy | Accent}, // LONG RIGHTWARDS SQUIGGLE ARROW
     604    { 0x2900, Infix, 5, 5, Accent}, // RIGHTWARDS TWO-HEADED ARROW WITH VERTICAL STROKE
     605    { 0x2901, Infix, 5, 5, Accent}, // RIGHTWARDS TWO-HEADED ARROW WITH DOUBLE VERTICAL STROKE
     606    { 0x2902, Infix, 5, 5, Accent}, // LEFTWARDS DOUBLE ARROW WITH VERTICAL STROKE
     607    { 0x2903, Infix, 5, 5, Accent}, // RIGHTWARDS DOUBLE ARROW WITH VERTICAL STROKE
     608    { 0x2904, Infix, 5, 5, Accent}, // LEFT RIGHT DOUBLE ARROW WITH VERTICAL STROKE
     609    { 0x2905, Infix, 5, 5, Accent}, // RIGHTWARDS TWO-HEADED ARROW FROM BAR
     610    { 0x2906, Infix, 5, 5, Accent}, // LEFTWARDS DOUBLE ARROW FROM BAR
     611    { 0x2907, Infix, 5, 5, Accent}, // RIGHTWARDS DOUBLE ARROW FROM BAR
     612    { 0x2908, Infix, 5, 5, 0}, // DOWNWARDS ARROW WITH HORIZONTAL STROKE
     613    { 0x2909, Infix, 5, 5, 0}, // UPWARDS ARROW WITH HORIZONTAL STROKE
     614    { 0x290A, Infix, 5, 5, Stretchy}, // UPWARDS TRIPLE ARROW
     615    { 0x290B, Infix, 5, 5, Stretchy}, // DOWNWARDS TRIPLE ARROW
     616    { 0x290C, Infix, 5, 5, Stretchy | Accent}, // LEFTWARDS DOUBLE DASH ARROW
     617    { 0x290D, Infix, 5, 5, Stretchy | Accent}, // RIGHTWARDS DOUBLE DASH ARROW
     618    { 0x290E, Infix, 5, 5, Stretchy | Accent}, // LEFTWARDS TRIPLE DASH ARROW
     619    { 0x290F, Infix, 5, 5, Stretchy | Accent}, // RIGHTWARDS TRIPLE DASH ARROW
     620    { 0x2910, Infix, 5, 5, Stretchy | Accent}, // RIGHTWARDS TWO-HEADED TRIPLE DASH ARROW
     621    { 0x2911, Infix, 5, 5, Accent}, // RIGHTWARDS ARROW WITH DOTTED STEM
     622    { 0x2912, Infix, 5, 5, Stretchy}, // UPWARDS ARROW TO BAR
     623    { 0x2913, Infix, 5, 5, Stretchy}, // DOWNWARDS ARROW TO BAR
     624    { 0x2914, Infix, 5, 5, Accent}, // RIGHTWARDS ARROW WITH TAIL WITH VERTICAL STROKE
     625    { 0x2915, Infix, 5, 5, Accent}, // RIGHTWARDS ARROW WITH TAIL WITH DOUBLE VERTICAL STROKE
     626    { 0x2916, Infix, 5, 5, Accent}, // RIGHTWARDS TWO-HEADED ARROW WITH TAIL
     627    { 0x2917, Infix, 5, 5, Accent}, // RIGHTWARDS TWO-HEADED ARROW WITH TAIL WITH VERTICAL STROKE
     628    { 0x2918, Infix, 5, 5, Accent}, // RIGHTWARDS TWO-HEADED ARROW WITH TAIL WITH DOUBLE VERTICAL STROKE
     629    { 0x2919, Infix, 5, 5, Accent}, // LEFTWARDS ARROW-TAIL
     630    { 0x291A, Infix, 5, 5, Accent}, // RIGHTWARDS ARROW-TAIL
     631    { 0x291B, Infix, 5, 5, Accent}, // LEFTWARDS DOUBLE ARROW-TAIL
     632    { 0x291C, Infix, 5, 5, Accent}, // RIGHTWARDS DOUBLE ARROW-TAIL
     633    { 0x291D, Infix, 5, 5, Accent}, // LEFTWARDS ARROW TO BLACK DIAMOND
     634    { 0x291E, Infix, 5, 5, Accent}, // RIGHTWARDS ARROW TO BLACK DIAMOND
     635    { 0x291F, Infix, 5, 5, Accent}, // LEFTWARDS ARROW FROM BAR TO BLACK DIAMOND
     636    { 0x2920, Infix, 5, 5, Accent}, // RIGHTWARDS ARROW FROM BAR TO BLACK DIAMOND
     637    { 0x2921, Infix, 5, 5, Stretchy}, // NORTH WEST AND SOUTH EAST ARROW
     638    { 0x2922, Infix, 5, 5, Stretchy}, // NORTH EAST AND SOUTH WEST ARROW
     639    { 0x2923, Infix, 5, 5, 0}, // NORTH WEST ARROW WITH HOOK
     640    { 0x2924, Infix, 5, 5, 0}, // NORTH EAST ARROW WITH HOOK
     641    { 0x2925, Infix, 5, 5, 0}, // SOUTH EAST ARROW WITH HOOK
     642    { 0x2926, Infix, 5, 5, 0}, // SOUTH WEST ARROW WITH HOOK
     643    { 0x2927, Infix, 5, 5, 0}, // NORTH WEST ARROW AND NORTH EAST ARROW
     644    { 0x2928, Infix, 5, 5, 0}, // NORTH EAST ARROW AND SOUTH EAST ARROW
     645    { 0x2929, Infix, 5, 5, 0}, // SOUTH EAST ARROW AND SOUTH WEST ARROW
     646    { 0x292A, Infix, 5, 5, 0}, // SOUTH WEST ARROW AND NORTH WEST ARROW
     647    { 0x292B, Infix, 5, 5, 0}, // RISING DIAGONAL CROSSING FALLING DIAGONAL
     648    { 0x292C, Infix, 5, 5, 0}, // FALLING DIAGONAL CROSSING RISING DIAGONAL
     649    { 0x292D, Infix, 5, 5, 0}, // SOUTH EAST ARROW CROSSING NORTH EAST ARROW
     650    { 0x292E, Infix, 5, 5, 0}, // NORTH EAST ARROW CROSSING SOUTH EAST ARROW
     651    { 0x292F, Infix, 5, 5, 0}, // FALLING DIAGONAL CROSSING NORTH EAST ARROW
     652    { 0x2930, Infix, 5, 5, 0}, // RISING DIAGONAL CROSSING SOUTH EAST ARROW
     653    { 0x2931, Infix, 5, 5, 0}, // NORTH EAST ARROW CROSSING NORTH WEST ARROW
     654    { 0x2932, Infix, 5, 5, 0}, // NORTH WEST ARROW CROSSING NORTH EAST ARROW
     655    { 0x2933, Infix, 5, 5, Accent}, // WAVE ARROW POINTING DIRECTLY RIGHT
     656    { 0x2934, Infix, 5, 5, 0}, // ARROW POINTING RIGHTWARDS THEN CURVING UPWARDS
     657    { 0x2935, Infix, 5, 5, 0}, // ARROW POINTING RIGHTWARDS THEN CURVING DOWNWARDS
     658    { 0x2936, Infix, 5, 5, 0}, // ARROW POINTING DOWNWARDS THEN CURVING LEFTWARDS
     659    { 0x2937, Infix, 5, 5, 0}, // ARROW POINTING DOWNWARDS THEN CURVING RIGHTWARDS
     660    { 0x2938, Infix, 5, 5, 0}, // RIGHT-SIDE ARC CLOCKWISE ARROW
     661    { 0x2939, Infix, 5, 5, 0}, // LEFT-SIDE ARC ANTICLOCKWISE ARROW
     662    { 0x293A, Infix, 5, 5, Accent}, // TOP ARC ANTICLOCKWISE ARROW
     663    { 0x293B, Infix, 5, 5, Accent}, // BOTTOM ARC ANTICLOCKWISE ARROW
     664    { 0x293C, Infix, 5, 5, Accent}, // TOP ARC CLOCKWISE ARROW WITH MINUS
     665    { 0x293D, Infix, 5, 5, Accent}, // TOP ARC ANTICLOCKWISE ARROW WITH PLUS
     666    { 0x293E, Infix, 5, 5, 0}, // LOWER RIGHT SEMICIRCULAR CLOCKWISE ARROW
     667    { 0x293F, Infix, 5, 5, 0}, // LOWER LEFT SEMICIRCULAR ANTICLOCKWISE ARROW
     668    { 0x2940, Infix, 5, 5, 0}, // ANTICLOCKWISE CLOSED CIRCLE ARROW
     669    { 0x2941, Infix, 5, 5, 0}, // CLOCKWISE CLOSED CIRCLE ARROW
     670    { 0x2942, Infix, 5, 5, Accent}, // RIGHTWARDS ARROW ABOVE SHORT LEFTWARDS ARROW
     671    { 0x2943, Infix, 5, 5, Accent}, // LEFTWARDS ARROW ABOVE SHORT RIGHTWARDS ARROW
     672    { 0x2944, Infix, 5, 5, Accent}, // SHORT RIGHTWARDS ARROW ABOVE LEFTWARDS ARROW
     673    { 0x2945, Infix, 5, 5, Accent}, // RIGHTWARDS ARROW WITH PLUS BELOW
     674    { 0x2946, Infix, 5, 5, Accent}, // LEFTWARDS ARROW WITH PLUS BELOW
     675    { 0x2947, Infix, 5, 5, Accent}, // RIGHTWARDS ARROW THROUGH X
     676    { 0x2948, Infix, 5, 5, Accent}, // LEFT RIGHT ARROW THROUGH SMALL CIRCLE
     677    { 0x2949, Infix, 5, 5, 0}, // UPWARDS TWO-HEADED ARROW FROM SMALL CIRCLE
     678    { 0x294A, Infix, 5, 5, Accent}, // LEFT BARB UP RIGHT BARB DOWN HARPOON
     679    { 0x294B, Infix, 5, 5, Accent}, // LEFT BARB DOWN RIGHT BARB UP HARPOON
     680    { 0x294C, Infix, 5, 5, 0}, // UP BARB RIGHT DOWN BARB LEFT HARPOON
     681    { 0x294D, Infix, 5, 5, 0}, // UP BARB LEFT DOWN BARB RIGHT HARPOON
     682    { 0x294E, Infix, 5, 5, Stretchy | Accent}, // LEFT BARB UP RIGHT BARB UP HARPOON
     683    { 0x294F, Infix, 5, 5, Stretchy}, // UP BARB RIGHT DOWN BARB RIGHT HARPOON
     684    { 0x2950, Infix, 5, 5, Stretchy | Accent}, // LEFT BARB DOWN RIGHT BARB DOWN HARPOON
     685    { 0x2951, Infix, 5, 5, Stretchy}, // UP BARB LEFT DOWN BARB LEFT HARPOON
     686    { 0x2952, Infix, 5, 5, Stretchy | Accent}, // LEFTWARDS HARPOON WITH BARB UP TO BAR
     687    { 0x2953, Infix, 5, 5, Stretchy | Accent}, // RIGHTWARDS HARPOON WITH BARB UP TO BAR
     688    { 0x2954, Infix, 5, 5, Stretchy}, // UPWARDS HARPOON WITH BARB RIGHT TO BAR
     689    { 0x2955, Infix, 5, 5, Stretchy}, // DOWNWARDS HARPOON WITH BARB RIGHT TO BAR
     690    { 0x2956, Infix, 5, 5, Stretchy}, // LEFTWARDS HARPOON WITH BARB DOWN TO BAR
     691    { 0x2957, Infix, 5, 5, Stretchy}, // RIGHTWARDS HARPOON WITH BARB DOWN TO BAR
     692    { 0x2958, Infix, 5, 5, Stretchy}, // UPWARDS HARPOON WITH BARB LEFT TO BAR
     693    { 0x2959, Infix, 5, 5, Stretchy}, // DOWNWARDS HARPOON WITH BARB LEFT TO BAR
     694    { 0x295A, Infix, 5, 5, Stretchy | Accent}, // LEFTWARDS HARPOON WITH BARB UP FROM BAR
     695    { 0x295B, Infix, 5, 5, Stretchy | Accent}, // RIGHTWARDS HARPOON WITH BARB UP FROM BAR
     696    { 0x295C, Infix, 5, 5, Stretchy}, // UPWARDS HARPOON WITH BARB RIGHT FROM BAR
     697    { 0x295D, Infix, 5, 5, Stretchy}, // DOWNWARDS HARPOON WITH BARB RIGHT FROM BAR
     698    { 0x295E, Infix, 5, 5, Stretchy | Accent}, // LEFTWARDS HARPOON WITH BARB DOWN FROM BAR
     699    { 0x295F, Infix, 5, 5, Stretchy | Accent}, // RIGHTWARDS HARPOON WITH BARB DOWN FROM BAR
     700    { 0x2960, Infix, 5, 5, Stretchy}, // UPWARDS HARPOON WITH BARB LEFT FROM BAR
     701    { 0x2961, Infix, 5, 5, Stretchy}, // DOWNWARDS HARPOON WITH BARB LEFT FROM BAR
     702    { 0x2962, Infix, 5, 5, Accent}, // LEFTWARDS HARPOON WITH BARB UP ABOVE LEFTWARDS HARPOON WITH BARB DOWN
     703    { 0x2963, Infix, 5, 5, 0}, // UPWARDS HARPOON WITH BARB LEFT BESIDE UPWARDS HARPOON WITH BARB RIGHT
     704    { 0x2964, Infix, 5, 5, Accent}, // RIGHTWARDS HARPOON WITH BARB UP ABOVE RIGHTWARDS HARPOON WITH BARB DOWN
     705    { 0x2965, Infix, 5, 5, 0}, // DOWNWARDS HARPOON WITH BARB LEFT BESIDE DOWNWARDS HARPOON WITH BARB RIGHT
     706    { 0x2966, Infix, 5, 5, Accent}, // LEFTWARDS HARPOON WITH BARB UP ABOVE RIGHTWARDS HARPOON WITH BARB UP
     707    { 0x2967, Infix, 5, 5, Accent}, // LEFTWARDS HARPOON WITH BARB DOWN ABOVE RIGHTWARDS HARPOON WITH BARB DOWN
     708    { 0x2968, Infix, 5, 5, Accent}, // RIGHTWARDS HARPOON WITH BARB UP ABOVE LEFTWARDS HARPOON WITH BARB UP
     709    { 0x2969, Infix, 5, 5, Accent}, // RIGHTWARDS HARPOON WITH BARB DOWN ABOVE LEFTWARDS HARPOON WITH BARB DOWN
     710    { 0x296A, Infix, 5, 5, Accent}, // LEFTWARDS HARPOON WITH BARB UP ABOVE LONG DASH
     711    { 0x296B, Infix, 5, 5, Accent}, // LEFTWARDS HARPOON WITH BARB DOWN BELOW LONG DASH
     712    { 0x296C, Infix, 5, 5, Accent}, // RIGHTWARDS HARPOON WITH BARB UP ABOVE LONG DASH
     713    { 0x296D, Infix, 5, 5, Accent}, // RIGHTWARDS HARPOON WITH BARB DOWN BELOW LONG DASH
     714    { 0x296E, Infix, 5, 5, Stretchy}, // UPWARDS HARPOON WITH BARB LEFT BESIDE DOWNWARDS HARPOON WITH BARB RIGHT
     715    { 0x296F, Infix, 5, 5, Stretchy}, // DOWNWARDS HARPOON WITH BARB LEFT BESIDE UPWARDS HARPOON WITH BARB RIGHT
     716    { 0x2970, Infix, 5, 5, Accent}, // RIGHT DOUBLE ARROW WITH ROUNDED HEAD
     717    { 0x2971, Infix, 5, 5, Accent}, // EQUALS SIGN ABOVE RIGHTWARDS ARROW
     718    { 0x2972, Infix, 5, 5, Accent}, // TILDE OPERATOR ABOVE RIGHTWARDS ARROW
     719    { 0x2973, Infix, 5, 5, Accent}, // LEFTWARDS ARROW ABOVE TILDE OPERATOR
     720    { 0x2974, Infix, 5, 5, Accent}, // RIGHTWARDS ARROW ABOVE TILDE OPERATOR
     721    { 0x2975, Infix, 5, 5, Accent}, // RIGHTWARDS ARROW ABOVE ALMOST EQUAL TO
     722    { 0x2976, Infix, 5, 5, Accent}, // LESS-THAN ABOVE LEFTWARDS ARROW
     723    { 0x2977, Infix, 5, 5, Accent}, // LEFTWARDS ARROW THROUGH LESS-THAN
     724    { 0x2978, Infix, 5, 5, Accent}, // GREATER-THAN ABOVE RIGHTWARDS ARROW
     725    { 0x2979, Infix, 5, 5, Accent}, // SUBSET ABOVE RIGHTWARDS ARROW
     726    { 0x297A, Infix, 5, 5, Accent}, // LEFTWARDS ARROW THROUGH SUBSET
     727    { 0x297B, Infix, 5, 5, Accent}, // SUPERSET ABOVE LEFTWARDS ARROW
     728    { 0x297C, Infix, 5, 5, Accent}, // LEFT FISH TAIL
     729    { 0x297D, Infix, 5, 5, Accent}, // RIGHT FISH TAIL
     730    { 0x297E, Infix, 5, 5, 0}, // UP FISH TAIL
     731    { 0x297F, Infix, 5, 5, 0}, // DOWN FISH TAIL
     732    { 0x2980, Prefix, 0, 0, Fence | Stretchy}, // TRIPLE VERTICAL BAR DELIMITER
     733    { 0x2980, Postfix, 0, 0, Fence | Stretchy}, // TRIPLE VERTICAL BAR DELIMITER
     734    { 0x2981, Infix, 3, 3, 0}, // Z NOTATION SPOT
     735    { 0x2982, Infix, 3, 3, 0}, // Z NOTATION TYPE COLON
     736    { 0x2983, Prefix, 0, 0, Symmetric | Fence | Stretchy}, // LEFT WHITE CURLY BRACKET
     737    { 0x2984, Postfix, 0, 0, Symmetric | Fence | Stretchy}, // RIGHT WHITE CURLY BRACKET
     738    { 0x2985, Prefix, 0, 0, Symmetric | Fence | Stretchy}, // LEFT WHITE PARENTHESIS
     739    { 0x2986, Postfix, 0, 0, Symmetric | Fence | Stretchy}, // RIGHT WHITE PARENTHESIS
     740    { 0x2987, Prefix, 0, 0, Symmetric | Fence | Stretchy}, // Z NOTATION LEFT IMAGE BRACKET
     741    { 0x2988, Postfix, 0, 0, Symmetric | Fence | Stretchy}, // Z NOTATION RIGHT IMAGE BRACKET
     742    { 0x2989, Prefix, 0, 0, Symmetric | Fence | Stretchy}, // Z NOTATION LEFT BINDING BRACKET
     743    { 0x298A, Postfix, 0, 0, Symmetric | Fence | Stretchy}, // Z NOTATION RIGHT BINDING BRACKET
     744    { 0x298B, Prefix, 0, 0, Symmetric | Fence | Stretchy}, // LEFT SQUARE BRACKET WITH UNDERBAR
     745    { 0x298C, Postfix, 0, 0, Symmetric | Fence | Stretchy}, // RIGHT SQUARE BRACKET WITH UNDERBAR
     746    { 0x298D, Prefix, 0, 0, Symmetric | Fence | Stretchy}, // LEFT SQUARE BRACKET WITH TICK IN TOP CORNER
     747    { 0x298E, Postfix, 0, 0, Symmetric | Fence | Stretchy}, // RIGHT SQUARE BRACKET WITH TICK IN BOTTOM CORNER
     748    { 0x298F, Prefix, 0, 0, Symmetric | Fence | Stretchy}, // LEFT SQUARE BRACKET WITH TICK IN BOTTOM CORNER
     749    { 0x2990, Postfix, 0, 0, Symmetric | Fence | Stretchy}, // RIGHT SQUARE BRACKET WITH TICK IN TOP CORNER
     750    { 0x2991, Prefix, 0, 0, Symmetric | Fence | Stretchy}, // LEFT ANGLE BRACKET WITH DOT
     751    { 0x2992, Postfix, 0, 0, Symmetric | Fence | Stretchy}, // RIGHT ANGLE BRACKET WITH DOT
     752    { 0x2993, Prefix, 0, 0, Symmetric | Fence | Stretchy}, // LEFT ARC LESS-THAN BRACKET
     753    { 0x2994, Postfix, 0, 0, Symmetric | Fence | Stretchy}, // RIGHT ARC GREATER-THAN BRACKET
     754    { 0x2995, Prefix, 0, 0, Symmetric | Fence | Stretchy}, // DOUBLE LEFT ARC GREATER-THAN BRACKET
     755    { 0x2996, Postfix, 0, 0, Symmetric | Fence | Stretchy}, // DOUBLE RIGHT ARC LESS-THAN BRACKET
     756    { 0x2997, Prefix, 0, 0, Symmetric | Fence | Stretchy}, // LEFT BLACK TORTOISE SHELL BRACKET
     757    { 0x2998, Postfix, 0, 0, Symmetric | Fence | Stretchy}, // RIGHT BLACK TORTOISE SHELL BRACKET
     758    { 0x2999, Infix, 3, 3, 0}, // DOTTED FENCE
     759    { 0x299A, Infix, 3, 3, 0}, // VERTICAL ZIGZAG LINE
     760    { 0x299B, Infix, 3, 3, 0}, // MEASURED ANGLE OPENING LEFT
     761    { 0x299C, Infix, 3, 3, 0}, // RIGHT ANGLE VARIANT WITH SQUARE
     762    { 0x299D, Infix, 3, 3, 0}, // MEASURED RIGHT ANGLE WITH DOT
     763    { 0x299E, Infix, 3, 3, 0}, // ANGLE WITH S INSIDE
     764    { 0x299F, Infix, 3, 3, 0}, // ACUTE ANGLE
     765    { 0x29A0, Infix, 3, 3, 0}, // SPHERICAL ANGLE OPENING LEFT
     766    { 0x29A1, Infix, 3, 3, 0}, // SPHERICAL ANGLE OPENING UP
     767    { 0x29A2, Infix, 3, 3, 0}, // TURNED ANGLE
     768    { 0x29A3, Infix, 3, 3, 0}, // REVERSED ANGLE
     769    { 0x29A4, Infix, 3, 3, 0}, // ANGLE WITH UNDERBAR
     770    { 0x29A5, Infix, 3, 3, 0}, // REVERSED ANGLE WITH UNDERBAR
     771    { 0x29A6, Infix, 3, 3, 0}, // OBLIQUE ANGLE OPENING UP
     772    { 0x29A7, Infix, 3, 3, 0}, // OBLIQUE ANGLE OPENING DOWN
     773    { 0x29A8, Infix, 3, 3, 0}, // MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING UP AND RIGHT
     774    { 0x29A9, Infix, 3, 3, 0}, // MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING UP AND LEFT
     775    { 0x29AA, Infix, 3, 3, 0}, // MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING DOWN AND RIGHT
     776    { 0x29AB, Infix, 3, 3, 0}, // MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING DOWN AND LEFT
     777    { 0x29AC, Infix, 3, 3, 0}, // MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING RIGHT AND UP
     778    { 0x29AD, Infix, 3, 3, 0}, // MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING LEFT AND UP
     779    { 0x29AE, Infix, 3, 3, 0}, // MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING RIGHT AND DOWN
     780    { 0x29AF, Infix, 3, 3, 0}, // MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING LEFT AND DOWN
     781    { 0x29B0, Infix, 3, 3, 0}, // REVERSED EMPTY SET
     782    { 0x29B1, Infix, 3, 3, 0}, // EMPTY SET WITH OVERBAR
     783    { 0x29B2, Infix, 3, 3, 0}, // EMPTY SET WITH SMALL CIRCLE ABOVE
     784    { 0x29B3, Infix, 3, 3, 0}, // EMPTY SET WITH RIGHT ARROW ABOVE
     785    { 0x29B4, Infix, 3, 3, 0}, // EMPTY SET WITH LEFT ARROW ABOVE
     786    { 0x29B5, Infix, 3, 3, 0}, // CIRCLE WITH HORIZONTAL BAR
     787    { 0x29B6, Infix, 4, 4, 0}, // CIRCLED VERTICAL BAR
     788    { 0x29B7, Infix, 4, 4, 0}, // CIRCLED PARALLEL
     789    { 0x29B8, Infix, 4, 4, 0}, // CIRCLED REVERSE SOLIDUS
     790    { 0x29B9, Infix, 4, 4, 0}, // CIRCLED PERPENDICULAR
     791    { 0x29BA, Infix, 4, 4, 0}, // CIRCLE DIVIDED BY HORIZONTAL BAR AND TOP HALF DIVIDED BY VERTICAL BAR
     792    { 0x29BB, Infix, 4, 4, 0}, // CIRCLE WITH SUPERIMPOSED X
     793    { 0x29BC, Infix, 4, 4, 0}, // CIRCLED ANTICLOCKWISE-ROTATED DIVISION SIGN
     794    { 0x29BD, Infix, 4, 4, 0}, // UP ARROW THROUGH CIRCLE
     795    { 0x29BE, Infix, 4, 4, 0}, // CIRCLED WHITE BULLET
     796    { 0x29BF, Infix, 4, 4, 0}, // CIRCLED BULLET
     797    { 0x29C0, Infix, 5, 5, 0}, // CIRCLED LESS-THAN
     798    { 0x29C1, Infix, 5, 5, 0}, // CIRCLED GREATER-THAN
     799    { 0x29C2, Infix, 3, 3, 0}, // CIRCLE WITH SMALL CIRCLE TO THE RIGHT
     800    { 0x29C3, Infix, 3, 3, 0}, // CIRCLE WITH TWO HORIZONTAL STROKES TO THE RIGHT
     801    { 0x29C4, Infix, 4, 4, 0}, // SQUARED RISING DIAGONAL SLASH
     802    { 0x29C5, Infix, 4, 4, 0}, // SQUARED FALLING DIAGONAL SLASH
     803    { 0x29C6, Infix, 4, 4, 0}, // SQUARED ASTERISK
     804    { 0x29C7, Infix, 4, 4, 0}, // SQUARED SMALL CIRCLE
     805    { 0x29C8, Infix, 4, 4, 0}, // SQUARED SQUARE
     806    { 0x29C9, Infix, 3, 3, 0}, // TWO JOINED SQUARES
     807    { 0x29CA, Infix, 3, 3, 0}, // TRIANGLE WITH DOT ABOVE
     808    { 0x29CB, Infix, 3, 3, 0}, // TRIANGLE WITH UNDERBAR
     809    { 0x29CC, Infix, 3, 3, 0}, // S IN TRIANGLE
     810    { 0x29CD, Infix, 3, 3, 0}, // TRIANGLE WITH SERIFS AT BOTTOM
     811    { 0x29CE, Infix, 5, 5, 0}, // RIGHT TRIANGLE ABOVE LEFT TRIANGLE
     812    { 0x29CF, Infix, 5, 5, 0}, // LEFT TRIANGLE BESIDE VERTICAL BAR
     813    { 0x29D0, Infix, 5, 5, 0}, // VERTICAL BAR BESIDE RIGHT TRIANGLE
     814    { 0x29D1, Infix, 5, 5, 0}, // BOWTIE WITH LEFT HALF BLACK
     815    { 0x29D2, Infix, 5, 5, 0}, // BOWTIE WITH RIGHT HALF BLACK
     816    { 0x29D3, Infix, 5, 5, 0}, // BLACK BOWTIE
     817    { 0x29D4, Infix, 5, 5, 0}, // TIMES WITH LEFT HALF BLACK
     818    { 0x29D5, Infix, 5, 5, 0}, // TIMES WITH RIGHT HALF BLACK
     819    { 0x29D6, Infix, 4, 4, 0}, // WHITE HOURGLASS
     820    { 0x29D7, Infix, 4, 4, 0}, // BLACK HOURGLASS
     821    { 0x29D8, Infix, 3, 3, 0}, // LEFT WIGGLY FENCE
     822    { 0x29D9, Infix, 3, 3, 0}, // RIGHT WIGGLY FENCE
     823    { 0x29DB, Infix, 3, 3, 0}, // RIGHT DOUBLE WIGGLY FENCE
     824    { 0x29DC, Infix, 3, 3, 0}, // INCOMPLETE INFINITY
     825    { 0x29DD, Infix, 3, 3, 0}, // TIE OVER INFINITY
     826    { 0x29DE, Infix, 5, 5, 0}, // INFINITY NEGATED WITH VERTICAL BAR
     827    { 0x29DF, Infix, 3, 3, 0}, // DOUBLE-ENDED MULTIMAP
     828    { 0x29E0, Infix, 3, 3, 0}, // SQUARE WITH CONTOURED OUTLINE
     829    { 0x29E1, Infix, 5, 5, 0}, // INCREASES AS
     830    { 0x29E2, Infix, 4, 4, 0}, // SHUFFLE PRODUCT
     831    { 0x29E3, Infix, 5, 5, 0}, // EQUALS SIGN AND SLANTED PARALLEL
     832    { 0x29E4, Infix, 5, 5, 0}, // EQUALS SIGN AND SLANTED PARALLEL WITH TILDE ABOVE
     833    { 0x29E5, Infix, 5, 5, 0}, // IDENTICAL TO AND SLANTED PARALLEL
     834    { 0x29E6, Infix, 5, 5, 0}, // GLEICH STARK
     835    { 0x29E7, Infix, 3, 3, 0}, // THERMODYNAMIC
     836    { 0x29E8, Infix, 3, 3, 0}, // DOWN-POINTING TRIANGLE WITH LEFT HALF BLACK
     837    { 0x29E9, Infix, 3, 3, 0}, // DOWN-POINTING TRIANGLE WITH RIGHT HALF BLACK
     838    { 0x29EA, Infix, 3, 3, 0}, // BLACK DIAMOND WITH DOWN ARROW
     839    { 0x29EB, Infix, 3, 3, 0}, // BLACK LOZENGE
     840    { 0x29EC, Infix, 3, 3, 0}, // WHITE CIRCLE WITH DOWN ARROW
     841    { 0x29ED, Infix, 3, 3, 0}, // BLACK CIRCLE WITH DOWN ARROW
     842    { 0x29EE, Infix, 3, 3, 0}, // ERROR-BARRED WHITE SQUARE
     843    { 0x29EF, Infix, 3, 3, 0}, // ERROR-BARRED BLACK SQUARE
     844    { 0x29F0, Infix, 3, 3, 0}, // ERROR-BARRED WHITE DIAMOND
     845    { 0x29F1, Infix, 3, 3, 0}, // ERROR-BARRED BLACK DIAMOND
     846    { 0x29F2, Infix, 3, 3, 0}, // ERROR-BARRED WHITE CIRCLE
     847    { 0x29F3, Infix, 3, 3, 0}, // ERROR-BARRED BLACK CIRCLE
     848    { 0x29F4, Infix, 5, 5, 0}, // RULE-DELAYED
     849    { 0x29F5, Infix, 4, 4, 0}, // REVERSE SOLIDUS OPERATOR
     850    { 0x29F6, Infix, 4, 4, 0}, // SOLIDUS WITH OVERBAR
     851    { 0x29F7, Infix, 4, 4, 0}, // REVERSE SOLIDUS WITH HORIZONTAL STROKE
     852    { 0x29F8, Infix, 3, 3, 0}, // BIG SOLIDUS
     853    { 0x29F9, Infix, 3, 3, 0}, // BIG REVERSE SOLIDUS
     854    { 0x29FA, Infix, 3, 3, 0}, // DOUBLE PLUS
     855    { 0x29FB, Infix, 3, 3, 0}, // TRIPLE PLUS
     856    { 0x29FC, Prefix, 0, 0, Symmetric | Fence | Stretchy}, // LEFT-POINTING CURVED ANGLE BRACKET
     857    { 0x29FD, Postfix, 0, 0, Symmetric | Fence | Stretchy}, // RIGHT-POINTING CURVED ANGLE BRACKET
     858    { 0x29FE, Infix, 4, 4, 0}, // TINY
     859    { 0x29FF, Infix, 4, 4, 0}, // MINY
     860    { 0x2A00, Prefix, 1, 2, Symmetric | LargeOp | MovableLimits}, // N-ARY CIRCLED DOT OPERATOR
     861    { 0x2A01, Prefix, 1, 2, Symmetric | LargeOp | MovableLimits}, // N-ARY CIRCLED PLUS OPERATOR
     862    { 0x2A02, Prefix, 1, 2, Symmetric | LargeOp | MovableLimits}, // N-ARY CIRCLED TIMES OPERATOR
     863    { 0x2A03, Prefix, 1, 2, Symmetric | LargeOp | MovableLimits}, // N-ARY UNION OPERATOR WITH DOT
     864    { 0x2A04, Prefix, 1, 2, Symmetric | LargeOp | MovableLimits}, // N-ARY UNION OPERATOR WITH PLUS
     865    { 0x2A05, Prefix, 1, 2, Symmetric | LargeOp | MovableLimits}, // N-ARY SQUARE INTERSECTION OPERATOR
     866    { 0x2A06, Prefix, 1, 2, Symmetric | LargeOp | MovableLimits}, // N-ARY SQUARE UNION OPERATOR
     867    { 0x2A07, Prefix, 1, 2, Symmetric | LargeOp | MovableLimits}, // TWO LOGICAL AND OPERATOR
     868    { 0x2A08, Prefix, 1, 2, Symmetric | LargeOp | MovableLimits}, // TWO LOGICAL OR OPERATOR
     869    { 0x2A09, Prefix, 1, 2, Symmetric | LargeOp | MovableLimits}, // N-ARY TIMES OPERATOR
     870    { 0x2A0A, Prefix, 1, 2, Symmetric | LargeOp | MovableLimits}, // MODULO TWO SUM
     871    { 0x2A0B, Prefix, 1, 2, Symmetric | LargeOp}, // SUMMATION WITH INTEGRAL
     872    { 0x2A0C, Prefix, 0, 1, Symmetric | LargeOp}, // QUADRUPLE INTEGRAL OPERATOR
     873    { 0x2A0D, Prefix, 1, 2, Symmetric | LargeOp}, // FINITE PART INTEGRAL
     874    { 0x2A0E, Prefix, 1, 2, Symmetric | LargeOp}, // INTEGRAL WITH DOUBLE STROKE
     875    { 0x2A0F, Prefix, 1, 2, Symmetric | LargeOp}, // INTEGRAL AVERAGE WITH SLASH
     876    { 0x2A10, Prefix, 1, 2, Symmetric | LargeOp | MovableLimits}, // CIRCULATION FUNCTION
     877    { 0x2A11, Prefix, 1, 2, Symmetric | LargeOp | MovableLimits}, // ANTICLOCKWISE INTEGRATION
     878    { 0x2A12, Prefix, 1, 2, Symmetric | LargeOp | MovableLimits}, // LINE INTEGRATION WITH RECTANGULAR PATH AROUND POLE
     879    { 0x2A13, Prefix, 1, 2, Symmetric | LargeOp | MovableLimits}, // LINE INTEGRATION WITH SEMICIRCULAR PATH AROUND POLE
     880    { 0x2A14, Prefix, 1, 2, Symmetric | LargeOp | MovableLimits}, // LINE INTEGRATION NOT INCLUDING THE POLE
     881    { 0x2A15, Prefix, 1, 2, Symmetric | LargeOp}, // INTEGRAL AROUND A POINT OPERATOR
     882    { 0x2A16, Prefix, 1, 2, Symmetric | LargeOp}, // QUATERNION INTEGRAL OPERATOR
     883    { 0x2A17, Prefix, 1, 2, Symmetric | LargeOp}, // INTEGRAL WITH LEFTWARDS ARROW WITH HOOK
     884    { 0x2A18, Prefix, 1, 2, Symmetric | LargeOp}, // INTEGRAL WITH TIMES SIGN
     885    { 0x2A19, Prefix, 1, 2, Symmetric | LargeOp}, // INTEGRAL WITH INTERSECTION
     886    { 0x2A1A, Prefix, 1, 2, Symmetric | LargeOp}, // INTEGRAL WITH UNION
     887    { 0x2A1B, Prefix, 1, 2, Symmetric | LargeOp}, // INTEGRAL WITH OVERBAR
     888    { 0x2A1C, Prefix, 1, 2, Symmetric | LargeOp}, // INTEGRAL WITH UNDERBAR
     889    { 0x2A1D, Infix, 3, 3, 0}, // JOIN
     890    { 0x2A1E, Infix, 3, 3, 0}, // LARGE LEFT TRIANGLE OPERATOR
     891    { 0x2A1F, Infix, 3, 3, 0}, // Z NOTATION SCHEMA COMPOSITION
     892    { 0x2A20, Infix, 3, 3, 0}, // Z NOTATION SCHEMA PIPING
     893    { 0x2A21, Infix, 3, 3, 0}, // Z NOTATION SCHEMA PROJECTION
     894    { 0x2A22, Infix, 4, 4, 0}, // PLUS SIGN WITH SMALL CIRCLE ABOVE
     895    { 0x2A23, Infix, 4, 4, 0}, // PLUS SIGN WITH CIRCUMFLEX ACCENT ABOVE
     896    { 0x2A24, Infix, 4, 4, 0}, // PLUS SIGN WITH TILDE ABOVE
     897    { 0x2A25, Infix, 4, 4, 0}, // PLUS SIGN WITH DOT BELOW
     898    { 0x2A26, Infix, 4, 4, 0}, // PLUS SIGN WITH TILDE BELOW
     899    { 0x2A27, Infix, 4, 4, 0}, // PLUS SIGN WITH SUBSCRIPT TWO
     900    { 0x2A28, Infix, 4, 4, 0}, // PLUS SIGN WITH BLACK TRIANGLE
     901    { 0x2A29, Infix, 4, 4, 0}, // MINUS SIGN WITH COMMA ABOVE
     902    { 0x2A2A, Infix, 4, 4, 0}, // MINUS SIGN WITH DOT BELOW
     903    { 0x2A2B, Infix, 4, 4, 0}, // MINUS SIGN WITH FALLING DOTS
     904    { 0x2A2C, Infix, 4, 4, 0}, // MINUS SIGN WITH RISING DOTS
     905    { 0x2A2D, Infix, 4, 4, 0}, // PLUS SIGN IN LEFT HALF CIRCLE
     906    { 0x2A2E, Infix, 4, 4, 0}, // PLUS SIGN IN RIGHT HALF CIRCLE
     907    { 0x2A2F, Infix, 4, 4, 0}, // VECTOR OR CROSS PRODUCT
     908    { 0x2A30, Infix, 4, 4, 0}, // MULTIPLICATION SIGN WITH DOT ABOVE
     909    { 0x2A31, Infix, 4, 4, 0}, // MULTIPLICATION SIGN WITH UNDERBAR
     910    { 0x2A32, Infix, 4, 4, 0}, // SEMIDIRECT PRODUCT WITH BOTTOM CLOSED
     911    { 0x2A33, Infix, 4, 4, 0}, // SMASH PRODUCT
     912    { 0x2A34, Infix, 4, 4, 0}, // MULTIPLICATION SIGN IN LEFT HALF CIRCLE
     913    { 0x2A35, Infix, 4, 4, 0}, // MULTIPLICATION SIGN IN RIGHT HALF CIRCLE
     914    { 0x2A36, Infix, 4, 4, 0}, // CIRCLED MULTIPLICATION SIGN WITH CIRCUMFLEX ACCENT
     915    { 0x2A37, Infix, 4, 4, 0}, // MULTIPLICATION SIGN IN DOUBLE CIRCLE
     916    { 0x2A38, Infix, 4, 4, 0}, // CIRCLED DIVISION SIGN
     917    { 0x2A39, Infix, 4, 4, 0}, // PLUS SIGN IN TRIANGLE
     918    { 0x2A3A, Infix, 4, 4, 0}, // MINUS SIGN IN TRIANGLE
     919    { 0x2A3B, Infix, 4, 4, 0}, // MULTIPLICATION SIGN IN TRIANGLE
     920    { 0x2A3C, Infix, 4, 4, 0}, // INTERIOR PRODUCT
     921    { 0x2A3D, Infix, 4, 4, 0}, // RIGHTHAND INTERIOR PRODUCT
     922    { 0x2A3E, Infix, 4, 4, 0}, // Z NOTATION RELATIONAL COMPOSITION
     923    { 0x2A3F, Infix, 4, 4, 0}, // AMALGAMATION OR COPRODUCT
     924    { 0x2A40, Infix, 4, 4, 0}, // INTERSECTION WITH DOT
     925    { 0x2A41, Infix, 4, 4, 0}, // UNION WITH MINUS SIGN
     926    { 0x2A42, Infix, 4, 4, 0}, // UNION WITH OVERBAR
     927    { 0x2A43, Infix, 4, 4, 0}, // INTERSECTION WITH OVERBAR
     928    { 0x2A44, Infix, 4, 4, 0}, // INTERSECTION WITH LOGICAL AND
     929    { 0x2A45, Infix, 4, 4, 0}, // UNION WITH LOGICAL OR
     930    { 0x2A46, Infix, 4, 4, 0}, // UNION ABOVE INTERSECTION
     931    { 0x2A47, Infix, 4, 4, 0}, // INTERSECTION ABOVE UNION
     932    { 0x2A48, Infix, 4, 4, 0}, // UNION ABOVE BAR ABOVE INTERSECTION
     933    { 0x2A49, Infix, 4, 4, 0}, // INTERSECTION ABOVE BAR ABOVE UNION
     934    { 0x2A4A, Infix, 4, 4, 0}, // UNION BESIDE AND JOINED WITH UNION
     935    { 0x2A4B, Infix, 4, 4, 0}, // INTERSECTION BESIDE AND JOINED WITH INTERSECTION
     936    { 0x2A4C, Infix, 4, 4, 0}, // CLOSED UNION WITH SERIFS
     937    { 0x2A4D, Infix, 4, 4, 0}, // CLOSED INTERSECTION WITH SERIFS
     938    { 0x2A4E, Infix, 4, 4, 0}, // DOUBLE SQUARE INTERSECTION
     939    { 0x2A4F, Infix, 4, 4, 0}, // DOUBLE SQUARE UNION
     940    { 0x2A50, Infix, 4, 4, 0}, // CLOSED UNION WITH SERIFS AND SMASH PRODUCT
     941    { 0x2A51, Infix, 4, 4, 0}, // LOGICAL AND WITH DOT ABOVE
     942    { 0x2A52, Infix, 4, 4, 0}, // LOGICAL OR WITH DOT ABOVE
     943    { 0x2A53, Infix, 4, 4, 0}, // DOUBLE LOGICAL AND
     944    { 0x2A54, Infix, 4, 4, 0}, // DOUBLE LOGICAL OR
     945    { 0x2A55, Infix, 4, 4, 0}, // TWO INTERSECTING LOGICAL AND
     946    { 0x2A56, Infix, 4, 4, 0}, // TWO INTERSECTING LOGICAL OR
     947    { 0x2A57, Infix, 4, 4, 0}, // SLOPING LARGE OR
     948    { 0x2A58, Infix, 4, 4, 0}, // SLOPING LARGE AND
     949    { 0x2A59, Infix, 5, 5, 0}, // LOGICAL OR OVERLAPPING LOGICAL AND
     950    { 0x2A5A, Infix, 4, 4, 0}, // LOGICAL AND WITH MIDDLE STEM
     951    { 0x2A5B, Infix, 4, 4, 0}, // LOGICAL OR WITH MIDDLE STEM
     952    { 0x2A5C, Infix, 4, 4, 0}, // LOGICAL AND WITH HORIZONTAL DASH
     953    { 0x2A5D, Infix, 4, 4, 0}, // LOGICAL OR WITH HORIZONTAL DASH
     954    { 0x2A5E, Infix, 4, 4, 0}, // LOGICAL AND WITH DOUBLE OVERBAR
     955    { 0x2A5F, Infix, 4, 4, 0}, // LOGICAL AND WITH UNDERBAR
     956    { 0x2A60, Infix, 4, 4, 0}, // LOGICAL AND WITH DOUBLE UNDERBAR
     957    { 0x2A61, Infix, 4, 4, 0}, // SMALL VEE WITH UNDERBAR
     958    { 0x2A62, Infix, 4, 4, 0}, // LOGICAL OR WITH DOUBLE OVERBAR
     959    { 0x2A63, Infix, 4, 4, 0}, // LOGICAL OR WITH DOUBLE UNDERBAR
     960    { 0x2A64, Infix, 4, 4, 0}, // Z NOTATION DOMAIN ANTIRESTRICTION
     961    { 0x2A65, Infix, 4, 4, 0}, // Z NOTATION RANGE ANTIRESTRICTION
     962    { 0x2A66, Infix, 5, 5, 0}, // EQUALS SIGN WITH DOT BELOW
     963    { 0x2A67, Infix, 5, 5, 0}, // IDENTICAL WITH DOT ABOVE
     964    { 0x2A68, Infix, 5, 5, 0}, // TRIPLE HORIZONTAL BAR WITH DOUBLE VERTICAL STROKE
     965    { 0x2A69, Infix, 5, 5, 0}, // TRIPLE HORIZONTAL BAR WITH TRIPLE VERTICAL STROKE
     966    { 0x2A6A, Infix, 5, 5, 0}, // TILDE OPERATOR WITH DOT ABOVE
     967    { 0x2A6B, Infix, 5, 5, 0}, // TILDE OPERATOR WITH RISING DOTS
     968    { 0x2A6C, Infix, 5, 5, 0}, // SIMILAR MINUS SIMILAR
     969    { 0x2A6D, Infix, 5, 5, 0}, // CONGRUENT WITH DOT ABOVE
     970    { 0x2A6E, Infix, 5, 5, 0}, // EQUALS WITH ASTERISK
     971    { 0x2A6F, Infix, 5, 5, 0}, // ALMOST EQUAL TO WITH CIRCUMFLEX ACCENT
     972    { 0x2A70, Infix, 5, 5, 0}, // APPROXIMATELY EQUAL OR EQUAL TO
     973    { 0x2A71, Infix, 4, 4, 0}, // EQUALS SIGN ABOVE PLUS SIGN
     974    { 0x2A72, Infix, 4, 4, 0}, // PLUS SIGN ABOVE EQUALS SIGN
     975    { 0x2A73, Infix, 5, 5, 0}, // EQUALS SIGN ABOVE TILDE OPERATOR
     976    { 0x2A74, Infix, 5, 5, 0}, // DOUBLE COLON EQUAL
     977    { 0x2A75, Infix, 5, 5, 0}, // TWO CONSECUTIVE EQUALS SIGNS
     978    { 0x2A76, Infix, 5, 5, 0}, // THREE CONSECUTIVE EQUALS SIGNS
     979    { 0x2A77, Infix, 5, 5, 0}, // EQUALS SIGN WITH TWO DOTS ABOVE AND TWO DOTS BELOW
     980    { 0x2A78, Infix, 5, 5, 0}, // EQUIVALENT WITH FOUR DOTS ABOVE
     981    { 0x2A79, Infix, 5, 5, 0}, // LESS-THAN WITH CIRCLE INSIDE
     982    { 0x2A7A, Infix, 5, 5, 0}, // GREATER-THAN WITH CIRCLE INSIDE
     983    { 0x2A7B, Infix, 5, 5, 0}, // LESS-THAN WITH QUESTION MARK ABOVE
     984    { 0x2A7C, Infix, 5, 5, 0}, // GREATER-THAN WITH QUESTION MARK ABOVE
     985    { 0x2A7D, Infix, 5, 5, 0}, // LESS-THAN OR SLANTED EQUAL TO
     986    { 0x2A7E, Infix, 5, 5, 0}, // GREATER-THAN OR SLANTED EQUAL TO
     987    { 0x2A7F, Infix, 5, 5, 0}, // LESS-THAN OR SLANTED EQUAL TO WITH DOT INSIDE
     988    { 0x2A80, Infix, 5, 5, 0}, // GREATER-THAN OR SLANTED EQUAL TO WITH DOT INSIDE
     989    { 0x2A81, Infix, 5, 5, 0}, // LESS-THAN OR SLANTED EQUAL TO WITH DOT ABOVE
     990    { 0x2A82, Infix, 5, 5, 0}, // GREATER-THAN OR SLANTED EQUAL TO WITH DOT ABOVE
     991    { 0x2A83, Infix, 5, 5, 0}, // LESS-THAN OR SLANTED EQUAL TO WITH DOT ABOVE RIGHT
     992    { 0x2A84, Infix, 5, 5, 0}, // GREATER-THAN OR SLANTED EQUAL TO WITH DOT ABOVE LEFT
     993    { 0x2A85, Infix, 5, 5, 0}, // LESS-THAN OR APPROXIMATE
     994    { 0x2A86, Infix, 5, 5, 0}, // GREATER-THAN OR APPROXIMATE
     995    { 0x2A87, Infix, 5, 5, 0}, // LESS-THAN AND SINGLE-LINE NOT EQUAL TO
     996    { 0x2A88, Infix, 5, 5, 0}, // GREATER-THAN AND SINGLE-LINE NOT EQUAL TO
     997    { 0x2A89, Infix, 5, 5, 0}, // LESS-THAN AND NOT APPROXIMATE
     998    { 0x2A8A, Infix, 5, 5, 0}, // GREATER-THAN AND NOT APPROXIMATE
     999    { 0x2A8B, Infix, 5, 5, 0}, // LESS-THAN ABOVE DOUBLE-LINE EQUAL ABOVE GREATER-THAN
     1000    { 0x2A8C, Infix, 5, 5, 0}, // GREATER-THAN ABOVE DOUBLE-LINE EQUAL ABOVE LESS-THAN
     1001    { 0x2A8D, Infix, 5, 5, 0}, // LESS-THAN ABOVE SIMILAR OR EQUAL
     1002    { 0x2A8E, Infix, 5, 5, 0}, // GREATER-THAN ABOVE SIMILAR OR EQUAL
     1003    { 0x2A8F, Infix, 5, 5, 0}, // LESS-THAN ABOVE SIMILAR ABOVE GREATER-THAN
     1004    { 0x2A90, Infix, 5, 5, 0}, // GREATER-THAN ABOVE SIMILAR ABOVE LESS-THAN
     1005    { 0x2A91, Infix, 5, 5, 0}, // LESS-THAN ABOVE GREATER-THAN ABOVE DOUBLE-LINE EQUAL
     1006    { 0x2A92, Infix, 5, 5, 0}, // GREATER-THAN ABOVE LESS-THAN ABOVE DOUBLE-LINE EQUAL
     1007    { 0x2A93, Infix, 5, 5, 0}, // LESS-THAN ABOVE SLANTED EQUAL ABOVE GREATER-THAN ABOVE SLANTED EQUAL
     1008    { 0x2A94, Infix, 5, 5, 0}, // GREATER-THAN ABOVE SLANTED EQUAL ABOVE LESS-THAN ABOVE SLANTED EQUAL
     1009    { 0x2A95, Infix, 5, 5, 0}, // SLANTED EQUAL TO OR LESS-THAN
     1010    { 0x2A96, Infix, 5, 5, 0}, // SLANTED EQUAL TO OR GREATER-THAN
     1011    { 0x2A97, Infix, 5, 5, 0}, // SLANTED EQUAL TO OR LESS-THAN WITH DOT INSIDE
     1012    { 0x2A98, Infix, 5, 5, 0}, // SLANTED EQUAL TO OR GREATER-THAN WITH DOT INSIDE
     1013    { 0x2A99, Infix, 5, 5, 0}, // DOUBLE-LINE EQUAL TO OR LESS-THAN
     1014    { 0x2A9A, Infix, 5, 5, 0}, // DOUBLE-LINE EQUAL TO OR GREATER-THAN
     1015    { 0x2A9B, Infix, 5, 5, 0}, // DOUBLE-LINE SLANTED EQUAL TO OR LESS-THAN
     1016    { 0x2A9C, Infix, 5, 5, 0}, // DOUBLE-LINE SLANTED EQUAL TO OR GREATER-THAN
     1017    { 0x2A9D, Infix, 5, 5, 0}, // SIMILAR OR LESS-THAN
     1018    { 0x2A9E, Infix, 5, 5, 0}, // SIMILAR OR GREATER-THAN
     1019    { 0x2A9F, Infix, 5, 5, 0}, // SIMILAR ABOVE LESS-THAN ABOVE EQUALS SIGN
     1020    { 0x2AA0, Infix, 5, 5, 0}, // SIMILAR ABOVE GREATER-THAN ABOVE EQUALS SIGN
     1021    { 0x2AA1, Infix, 5, 5, 0}, // DOUBLE NESTED LESS-THAN
     1022    { 0x2AA2, Infix, 5, 5, 0}, // DOUBLE NESTED GREATER-THAN
     1023    { 0x2AA3, Infix, 5, 5, 0}, // DOUBLE NESTED LESS-THAN WITH UNDERBAR
     1024    { 0x2AA4, Infix, 5, 5, 0}, // GREATER-THAN OVERLAPPING LESS-THAN
     1025    { 0x2AA5, Infix, 5, 5, 0}, // GREATER-THAN BESIDE LESS-THAN
     1026    { 0x2AA6, Infix, 5, 5, 0}, // LESS-THAN CLOSED BY CURVE
     1027    { 0x2AA7, Infix, 5, 5, 0}, // GREATER-THAN CLOSED BY CURVE
     1028    { 0x2AA8, Infix, 5, 5, 0}, // LESS-THAN CLOSED BY CURVE ABOVE SLANTED EQUAL
     1029    { 0x2AA9, Infix, 5, 5, 0}, // GREATER-THAN CLOSED BY CURVE ABOVE SLANTED EQUAL
     1030    { 0x2AAA, Infix, 5, 5, 0}, // SMALLER THAN
     1031    { 0x2AAB, Infix, 5, 5, 0}, // LARGER THAN
     1032    { 0x2AAC, Infix, 5, 5, 0}, // SMALLER THAN OR EQUAL TO
     1033    { 0x2AAD, Infix, 5, 5, 0}, // LARGER THAN OR EQUAL TO
     1034    { 0x2AAE, Infix, 5, 5, 0}, // EQUALS SIGN WITH BUMPY ABOVE
     1035    { 0x2AAF, Infix, 5, 5, 0}, // PRECEDES ABOVE SINGLE-LINE EQUALS SIGN
     1036    { 0x2AB0, Infix, 5, 5, 0}, // SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN
     1037    { 0x2AB1, Infix, 5, 5, 0}, // PRECEDES ABOVE SINGLE-LINE NOT EQUAL TO
     1038    { 0x2AB2, Infix, 5, 5, 0}, // SUCCEEDS ABOVE SINGLE-LINE NOT EQUAL TO
     1039    { 0x2AB3, Infix, 5, 5, 0}, // PRECEDES ABOVE EQUALS SIGN
     1040    { 0x2AB4, Infix, 5, 5, 0}, // SUCCEEDS ABOVE EQUALS SIGN
     1041    { 0x2AB5, Infix, 5, 5, 0}, // PRECEDES ABOVE NOT EQUAL TO
     1042    { 0x2AB6, Infix, 5, 5, 0}, // SUCCEEDS ABOVE NOT EQUAL TO
     1043    { 0x2AB7, Infix, 5, 5, 0}, // PRECEDES ABOVE ALMOST EQUAL TO
     1044    { 0x2AB8, Infix, 5, 5, 0}, // SUCCEEDS ABOVE ALMOST EQUAL TO
     1045    { 0x2AB9, Infix, 5, 5, 0}, // PRECEDES ABOVE NOT ALMOST EQUAL TO
     1046    { 0x2ABA, Infix, 5, 5, 0}, // SUCCEEDS ABOVE NOT ALMOST EQUAL TO
     1047    { 0x2ABB, Infix, 5, 5, 0}, // DOUBLE PRECEDES
     1048    { 0x2ABC, Infix, 5, 5, 0}, // DOUBLE SUCCEEDS
     1049    { 0x2ABD, Infix, 5, 5, 0}, // SUBSET WITH DOT
     1050    { 0x2ABE, Infix, 5, 5, 0}, // SUPERSET WITH DOT
     1051    { 0x2ABF, Infix, 5, 5, 0}, // SUBSET WITH PLUS SIGN BELOW
     1052    { 0x2AC0, Infix, 5, 5, 0}, // SUPERSET WITH PLUS SIGN BELOW
     1053    { 0x2AC1, Infix, 5, 5, 0}, // SUBSET WITH MULTIPLICATION SIGN BELOW
     1054    { 0x2AC2, Infix, 5, 5, 0}, // SUPERSET WITH MULTIPLICATION SIGN BELOW
     1055    { 0x2AC3, Infix, 5, 5, 0}, // SUBSET OF OR EQUAL TO WITH DOT ABOVE
     1056    { 0x2AC4, Infix, 5, 5, 0}, // SUPERSET OF OR EQUAL TO WITH DOT ABOVE
     1057    { 0x2AC5, Infix, 5, 5, 0}, // SUBSET OF ABOVE EQUALS SIGN
     1058    { 0x2AC6, Infix, 5, 5, 0}, // SUPERSET OF ABOVE EQUALS SIGN
     1059    { 0x2AC7, Infix, 5, 5, 0}, // SUBSET OF ABOVE TILDE OPERATOR
     1060    { 0x2AC8, Infix, 5, 5, 0}, // SUPERSET OF ABOVE TILDE OPERATOR
     1061    { 0x2AC9, Infix, 5, 5, 0}, // SUBSET OF ABOVE ALMOST EQUAL TO
     1062    { 0x2ACA, Infix, 5, 5, 0}, // SUPERSET OF ABOVE ALMOST EQUAL TO
     1063    { 0x2ACB, Infix, 5, 5, 0}, // SUBSET OF ABOVE NOT EQUAL TO
     1064    { 0x2ACC, Infix, 5, 5, 0}, // SUPERSET OF ABOVE NOT EQUAL TO
     1065    { 0x2ACD, Infix, 5, 5, 0}, // SQUARE LEFT OPEN BOX OPERATOR
     1066    { 0x2ACE, Infix, 5, 5, 0}, // SQUARE RIGHT OPEN BOX OPERATOR
     1067    { 0x2ACF, Infix, 5, 5, 0}, // CLOSED SUBSET
     1068    { 0x2AD0, Infix, 5, 5, 0}, // CLOSED SUPERSET
     1069    { 0x2AD1, Infix, 5, 5, 0}, // CLOSED SUBSET OR EQUAL TO
     1070    { 0x2AD2, Infix, 5, 5, 0}, // CLOSED SUPERSET OR EQUAL TO
     1071    { 0x2AD3, Infix, 5, 5, 0}, // SUBSET ABOVE SUPERSET
     1072    { 0x2AD4, Infix, 5, 5, 0}, // SUPERSET ABOVE SUBSET
     1073    { 0x2AD5, Infix, 5, 5, 0}, // SUBSET ABOVE SUBSET
     1074    { 0x2AD6, Infix, 5, 5, 0}, // SUPERSET ABOVE SUPERSET
     1075    { 0x2AD7, Infix, 5, 5, 0}, // SUPERSET BESIDE SUBSET
     1076    { 0x2AD8, Infix, 5, 5, 0}, // SUPERSET BESIDE AND JOINED BY DASH WITH SUBSET
     1077    { 0x2AD9, Infix, 5, 5, 0}, // ELEMENT OF OPENING DOWNWARDS
     1078    { 0x2ADA, Infix, 5, 5, 0}, // PITCHFORK WITH TEE TOP
     1079    { 0x2ADB, Infix, 5, 5, 0}, // TRANSVERSAL INTERSECTION
     1080    { 0x2ADD, Infix, 5, 5, 0}, // NONFORKING
     1081    { 0x2ADE, Infix, 5, 5, 0}, // SHORT LEFT TACK
     1082    { 0x2ADF, Infix, 5, 5, 0}, // SHORT DOWN TACK
     1083    { 0x2AE0, Infix, 5, 5, 0}, // SHORT UP TACK
     1084    { 0x2AE1, Infix, 5, 5, 0}, // PERPENDICULAR WITH S
     1085    { 0x2AE2, Infix, 5, 5, 0}, // VERTICAL BAR TRIPLE RIGHT TURNSTILE
     1086    { 0x2AE3, Infix, 5, 5, 0}, // DOUBLE VERTICAL BAR LEFT TURNSTILE
     1087    { 0x2AE4, Infix, 5, 5, 0}, // VERTICAL BAR DOUBLE LEFT TURNSTILE
     1088    { 0x2AE5, Infix, 5, 5, 0}, // DOUBLE VERTICAL BAR DOUBLE LEFT TURNSTILE
     1089    { 0x2AE6, Infix, 5, 5, 0}, // LONG DASH FROM LEFT MEMBER OF DOUBLE VERTICAL
     1090    { 0x2AE7, Infix, 5, 5, 0}, // SHORT DOWN TACK WITH OVERBAR
     1091    { 0x2AE8, Infix, 5, 5, 0}, // SHORT UP TACK WITH UNDERBAR
     1092    { 0x2AE9, Infix, 5, 5, 0}, // SHORT UP TACK ABOVE SHORT DOWN TACK
     1093    { 0x2AEA, Infix, 5, 5, 0}, // DOUBLE DOWN TACK
     1094    { 0x2AEB, Infix, 5, 5, 0}, // DOUBLE UP TACK
     1095    { 0x2AEC, Infix, 5, 5, 0}, // DOUBLE STROKE NOT SIGN
     1096    { 0x2AED, Infix, 5, 5, 0}, // REVERSED DOUBLE STROKE NOT SIGN
     1097    { 0x2AEE, Infix, 5, 5, 0}, // DOES NOT DIVIDE WITH REVERSED NEGATION SLASH
     1098    { 0x2AEF, Infix, 5, 5, 0}, // VERTICAL LINE WITH CIRCLE ABOVE
     1099    { 0x2AF0, Infix, 5, 5, 0}, // VERTICAL LINE WITH CIRCLE BELOW
     1100    { 0x2AF1, Infix, 5, 5, 0}, // DOWN TACK WITH CIRCLE BELOW
     1101    { 0x2AF2, Infix, 5, 5, 0}, // PARALLEL WITH HORIZONTAL STROKE
     1102    { 0x2AF3, Infix, 5, 5, 0}, // PARALLEL WITH TILDE OPERATOR
     1103    { 0x2AF4, Infix, 4, 4, 0}, // TRIPLE VERTICAL BAR BINARY RELATION
     1104    { 0x2AF5, Infix, 4, 4, 0}, // TRIPLE VERTICAL BAR WITH HORIZONTAL STROKE
     1105    { 0x2AF6, Infix, 4, 4, 0}, // TRIPLE COLON OPERATOR
     1106    { 0x2AF7, Infix, 5, 5, 0}, // TRIPLE NESTED LESS-THAN
     1107    { 0x2AF8, Infix, 5, 5, 0}, // TRIPLE NESTED GREATER-THAN
     1108    { 0x2AF9, Infix, 5, 5, 0}, // DOUBLE-LINE SLANTED LESS-THAN OR EQUAL TO
     1109    { 0x2AFA, Infix, 5, 5, 0}, // DOUBLE-LINE SLANTED GREATER-THAN OR EQUAL TO
     1110    { 0x2AFB, Infix, 4, 4, 0}, // TRIPLE SOLIDUS BINARY RELATION
     1111    { 0x2AFC, Prefix, 1, 2, Symmetric | LargeOp | MovableLimits}, // LARGE TRIPLE VERTICAL BAR OPERATOR
     1112    { 0x2AFD, Infix, 4, 4, 0}, // DOUBLE SOLIDUS OPERATOR
     1113    { 0x2AFE, Infix, 3, 3, 0}, // WHITE VERTICAL BAR
     1114    { 0x2AFF, Prefix, 1, 2, Symmetric | LargeOp | MovableLimits}, // N-ARY WHITE VERTICAL BAR
     1115    { 0x2B45, Infix, 5, 5, Stretchy}, // LEFTWARDS QUADRUPLE ARROW
     1116    { 0x2B46, Infix, 5, 5, Stretchy} // RIGHTWARDS QUADRUPLE ARROW
     1117};
     1118
     1119}
     1120
    661121RenderMathMLOperator::RenderMathMLOperator(MathMLElement& element, PassRef<RenderStyle> style)
    671122    : RenderMathMLBlock(element, std::move(style))
    681123    , m_stretchHeight(0)
    691124    , m_operator(0)
    70     , m_operatorType(Default)
    711125    , m_stretchyCharacter(nullptr)
    72 {
    73 }
    74 
    75 RenderMathMLOperator::RenderMathMLOperator(MathMLElement& element, PassRef<RenderStyle> style, UChar operatorChar)
     1126    , m_isFencedOperator(false)
     1127{
     1128    SetOperatorProperties();
     1129}
     1130
     1131RenderMathMLOperator::RenderMathMLOperator(MathMLElement& element, PassRef<RenderStyle> style, UChar operatorChar, MathMLOperatorDictionary::Form form, MathMLOperatorDictionary::Flag flag)
    761132    : RenderMathMLBlock(element, std::move(style))
    771133    , m_stretchHeight(0)
    78     , m_operator(convertHyphenMinusToMinusSign(operatorChar))
    79     , m_operatorType(Default)
     1134    , m_operator(operatorChar == hyphenMinus ? minusSign : operatorChar)
    801135    , m_stretchyCharacter(nullptr)
    81 {
     1136    , m_isFencedOperator(true)
     1137    , m_operatorForm(form)
     1138    , m_operatorFlags(flag)
     1139{
     1140    SetOperatorProperties();
     1141}
     1142
     1143void RenderMathMLOperator::setOperatorFlagFromAttribute(MathMLOperatorDictionary::Flag flag, const QualifiedName& name)
     1144{
     1145    const AtomicString& attributeValue = element().fastGetAttribute(name);
     1146    if (attributeValue == "true")
     1147        m_operatorFlags |= flag;
     1148    else if (attributeValue == "false")
     1149        m_operatorFlags &= ~flag;
     1150    // We ignore absent or invalid attributes.
     1151}
     1152
     1153void RenderMathMLOperator::setOperatorPropertiesFromOpDictEntry(const MathMLOperatorDictionary::Entry* entry)
     1154{
     1155    // If this operator has been created by RenderMathMLFenced, we preserve the Fence and Separator properties.
     1156    if (m_isFencedOperator)
     1157        m_operatorFlags = (m_operatorFlags & (MathMLOperatorDictionary::Fence | MathMLOperatorDictionary::Separator)) | entry->flags;
     1158    else
     1159        m_operatorFlags = entry->flags;
     1160
     1161    // Leading and trailing space is specified as multiple of 1/18em.
     1162    m_leadingSpace = entry->lspace * style().fontSize() / 18;
     1163    m_trailingSpace = entry->rspace * style().fontSize() / 18;
     1164}
     1165
     1166void RenderMathMLOperator::SetOperatorProperties()
     1167{
     1168    // We verify whether the operator text can be represented by a single UChar.
     1169    if (!m_isFencedOperator) {
     1170        // FIXME: This does not handle surrogate pairs (https://bugs.webkit.org/show_bug.cgi?id=122296).
     1171        // FIXME: This does not handle <mo> operators with multiple characters (https://bugs.webkit.org/show_bug.cgi?id=124828).
     1172        String opText = element().textContent().stripWhiteSpace().simplifyWhiteSpace().replace(hyphenMinus, minusSign).impl();
     1173        if (opText.length() == 1)
     1174            m_operator = opText[0];
     1175    }
     1176
     1177    // We determine the form of the operator.
     1178    bool explicitForm = true;
     1179    if (!m_isFencedOperator) {
     1180        const AtomicString& form = element().fastGetAttribute(MathMLNames::formAttr);
     1181        if (form == "prefix")
     1182            m_operatorForm = MathMLOperatorDictionary::Prefix;
     1183        else if (form == "infix")
     1184            m_operatorForm = MathMLOperatorDictionary::Infix;
     1185        else if (form == "postfix")
     1186            m_operatorForm = MathMLOperatorDictionary::Postfix;
     1187        else {
     1188            // 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).
     1189            explicitForm = false;
     1190            if (!element().previousSibling() && element().nextSibling())
     1191                m_operatorForm = MathMLOperatorDictionary::Prefix;
     1192            else if (element().previousSibling() && !element().nextSibling())
     1193                m_operatorForm = MathMLOperatorDictionary::Postfix;
     1194            else
     1195                m_operatorForm = MathMLOperatorDictionary::Infix;
     1196        }
     1197    }
     1198
     1199    // We determine the default values of the operator properties.
     1200
     1201    // First we initialize with the default values for unknown operators.
     1202    m_operatorFlags = 0; // This sets all the properties to "false".
     1203    m_leadingSpace = 5 * style().fontSize() / 18; // This sets leading space to "thickmathspace".
     1204    m_trailingSpace = 5 * style().fontSize() / 18; // This sets trailing space to "thickmathspace".
     1205    m_minSize = style().fontSize(); // This sets minsize to "1em".
     1206    m_maxSize = intMaxForLayoutUnit; // This sets maxsize to "infinity".
     1207
     1208    if (m_operator) {
     1209        // Then we try to find the default values from the operator dictionary.
     1210        if (const MathMLOperatorDictionary::Entry* entry = tryBinarySearch<const MathMLOperatorDictionary::Entry, MathMLOperatorDictionary::Key>(MathMLOperatorDictionary::dictionary, MATHML_OPDICT_SIZE, MathMLOperatorDictionary::Key(m_operator, m_operatorForm), MathMLOperatorDictionary::ExtractKey))
     1211            setOperatorPropertiesFromOpDictEntry(entry);
     1212        else if (!explicitForm) {
     1213            // 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.
     1214            // 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.
     1215            if (const MathMLOperatorDictionary::Entry* entry = tryBinarySearch<const MathMLOperatorDictionary::Entry, UChar>(MathMLOperatorDictionary::dictionary, MATHML_OPDICT_SIZE, m_operator, MathMLOperatorDictionary::ExtractChar)) {
     1216                // If the previous entry is another form for that operator, we move to that entry. Note that it only remains at most two forms so we don't need to move any further.
     1217                if (entry != MathMLOperatorDictionary::dictionary && (entry-1)->character == m_operator)
     1218                    entry--;
     1219                m_operatorForm = entry->form; // We override the form previously determined.
     1220                setOperatorPropertiesFromOpDictEntry(entry);
     1221            }
     1222        }
     1223    }
     1224#undef MATHML_OPDICT_SIZE
     1225
     1226    if (!m_isFencedOperator) {
     1227        // Finally, we make the attribute values override the default.
     1228
     1229        setOperatorFlagFromAttribute(MathMLOperatorDictionary::Fence, MathMLNames::fenceAttr);
     1230        setOperatorFlagFromAttribute(MathMLOperatorDictionary::Separator, MathMLNames::separatorAttr);
     1231        setOperatorFlagFromAttribute(MathMLOperatorDictionary::Stretchy, MathMLNames::stretchyAttr);
     1232        setOperatorFlagFromAttribute(MathMLOperatorDictionary::Symmetric, MathMLNames::symmetricAttr);
     1233        setOperatorFlagFromAttribute(MathMLOperatorDictionary::LargeOp, MathMLNames::largeopAttr);
     1234        setOperatorFlagFromAttribute(MathMLOperatorDictionary::MovableLimits, MathMLNames::movablelimitsAttr);
     1235        setOperatorFlagFromAttribute(MathMLOperatorDictionary::Accent, MathMLNames::accentAttr);
     1236
     1237        parseMathMLLength(element().fastGetAttribute(MathMLNames::lspaceAttr), m_leadingSpace, &style(), false); // FIXME: Negative leading space must be implemented (https://bugs.webkit.org/show_bug.cgi?id=124830).
     1238        parseMathMLLength(element().fastGetAttribute(MathMLNames::rspaceAttr), m_trailingSpace, &style(), false); // FIXME: Negative trailing space must be implemented (https://bugs.webkit.org/show_bug.cgi?id=124830).
     1239
     1240        // FIXME: Attributes minsize/maxsize are not implemented (https://bugs.webkit.org/show_bug.cgi?id=122567).
     1241        parseMathMLLength(element().fastGetAttribute(MathMLNames::minsizeAttr), m_minSize, &style(), false);
     1242        const AtomicString& maxsize = element().fastGetAttribute(MathMLNames::maxsizeAttr);
     1243        if (maxsize != "infinity")
     1244            parseMathMLLength(maxsize, m_maxSize, &style(), false);
     1245    }
    821246}
    831247
     
    1221286float RenderMathMLOperator::advanceForCharacter(UChar character)
    1231287{
    124     // Hyphen minus is always replaced by the minus sign in rendered text.
    125     GlyphData data = style().font().glyphDataForCharacter(convertHyphenMinusToMinusSign(character), false);
     1288    GlyphData data = style().font().glyphDataForCharacter(character, false);
    1261289    return data.fontData->widthForGlyph(data.glyph);
    1271290}
     
    1311294    ASSERT(preferredLogicalWidthsDirty());
    1321295
     1296    SetOperatorProperties();
    1331297    UChar stretchedCharacter;
    1341298    bool allowStretching = shouldAllowStretching(stretchedCharacter);
     
    1801344
    1811345    RenderPtr<RenderText> text;
    182     if (m_operator)
     1346    if (m_isFencedOperator)
    1831347        text = createRenderer<RenderText>(document(), String(&m_operator, 1));
    1841348    else
     
    1941358bool RenderMathMLOperator::shouldAllowStretching(UChar& stretchedCharacter)
    1951359{
    196     if (equalIgnoringCase(element().getAttribute(MathMLNames::stretchyAttr), "false"))
     1360    if (!hasOperatorFlag(MathMLOperatorDictionary::Stretchy))
    1971361        return false;
    1981362
    199     if (m_operator) {
    200         stretchedCharacter = m_operator;
    201         return true;
    202     }
    203 
    204     // FIXME: This does not handle surrogate pairs (http://wkbug.com/122296/).
    205     String opText = element().textContent();
    206     stretchedCharacter = 0;
    207     for (unsigned i = 0; i < opText.length(); ++i) {
    208         // If there's more than one non-whitespace character in this node, then don't even try to stretch it.
    209         if (stretchedCharacter && !isSpaceOrNewline(opText[i]))
    210             return false;
    211 
    212         if (!isSpaceOrNewline(opText[i]))
    213             stretchedCharacter = opText[i];
    214     }
    215 
     1363    stretchedCharacter = m_operator;
    2161364    return stretchedCharacter;
    2171365}
     
    2491397        return;
    2501398
     1399    SetOperatorProperties();
    2511400    UChar stretchedCharacter;
    2521401    bool allowStretching = shouldAllowStretching(stretchedCharacter);
  • trunk/Source/WebCore/rendering/mathml/RenderMathMLOperator.h

    r163793 r164418  
    3535namespace WebCore {
    3636   
     37namespace MathMLOperatorDictionary {
     38
     39enum Form { Infix, Prefix, Postfix };
     40enum Flag {
     41    Accent = 0x1, // FIXME: This must be used to implement accentunder/accent on munderover (https://bugs.webkit.org/show_bug.cgi?id=124826).
     42    Fence = 0x2, // This has no visual effect but allows to expose semantic information via the accessibility tree.
     43    LargeOp = 0x4, // FIXME: This must be used to implement displaystyle (https://bugs.webkit.org/show_bug.cgi?id=118737)
     44    MovableLimits = 0x8, // FIXME: This must be used to implement displaystyle  (https://bugs.webkit.org/show_bug.cgi?id=118737).
     45    Separator = 0x10, // This has no visual effect but allows to expose semantic information via the accessibility tree.
     46    Stretchy = 0x20,
     47    Symmetric = 0x40, // FIXME: This is not implemented yet (https://bugs.webkit.org/show_bug.cgi?id=124827).
     48};
     49struct Entry {
     50    UChar character;
     51    Form form;
     52    // FIXME: spacing around <mo> operators is not implemented yet (https://bugs.webkit.org/show_bug.cgi?id=115787).
     53    unsigned short lspace;
     54    unsigned short rspace;
     55    unsigned short flags;
     56};
     57
     58}
     59
    3760class RenderMathMLOperator final : public RenderMathMLBlock {
    3861public:
    3962    RenderMathMLOperator(MathMLElement&, PassRef<RenderStyle>);
    40     RenderMathMLOperator(MathMLElement&, PassRef<RenderStyle>, UChar operatorChar);
     63    RenderMathMLOperator(MathMLElement&, PassRef<RenderStyle>, UChar operatorChar, MathMLOperatorDictionary::Form, MathMLOperatorDictionary::Flag);
    4164
    4265    MathMLElement& element() { return toMathMLElement(nodeForNonAnonymous()); }
     
    4669    float expandedStretchHeight() const;
    4770   
    48     enum OperatorType { Default, Separator, Fence };
    49     void setOperatorType(OperatorType type) { m_operatorType = type; }
    50     OperatorType operatorType() const { return m_operatorType; }
     71    bool hasOperatorFlag(MathMLOperatorDictionary::Flag flag) const { return m_operatorFlags & flag; }
     72
    5173    void updateStyle();
    5274
     
    94116
    95117    UChar m_operator;
    96     OperatorType m_operatorType;
    97118    StretchyCharacter* m_stretchyCharacter;
     119    bool m_isFencedOperator;
     120    MathMLOperatorDictionary::Form m_operatorForm;
     121    unsigned short m_operatorFlags;
     122    LayoutUnit m_leadingSpace;
     123    LayoutUnit m_trailingSpace;
     124    LayoutUnit m_minSize;
     125    LayoutUnit m_maxSize;
     126
     127    void setOperatorFlagFromAttribute(MathMLOperatorDictionary::Flag, const QualifiedName&);
     128    void setOperatorPropertiesFromOpDictEntry(const MathMLOperatorDictionary::Entry*);
     129    void SetOperatorProperties();
    98130};
    99131
    100132RENDER_OBJECT_TYPE_CASTS(RenderMathMLOperator, isRenderMathMLOperator())
    101 
    102 inline UChar convertHyphenMinusToMinusSign(UChar glyph)
    103 {
    104     // When rendered as a mathematical operator, minus glyph should be larger.
    105     if (glyph == hyphenMinus)
    106         return minusSign;
    107    
    108     return glyph;
    109 }
    110133
    111134}
Note: See TracChangeset for help on using the changeset viewer.