Changeset 279165 in webkit


Ignore:
Timestamp:
Jun 22, 2021 6:33:57 PM (13 months ago)
Author:
Darin Adler
Message:

Improve more of the CSS list style implementations
https://bugs.webkit.org/show_bug.cgi?id=227206

Reviewed by Antti Koivisto.

Source/WebCore:

Added support for 12 new values for list-style-type: disclosure-closed,
disclosure-open, ethiopic-numeric, japanese-formal, japanese-informal,
korean-hangul-formal, korean-hanja-formal, korean-hanja-informal,
simp-chinese-formal, simp-chinese-informal, trad-chinese-informal,
and trad-chinese-formal.

Improved implementation to match specification more closely for a few
existing values for list-style-type: armenian, cjk-ideographic, hebrew,
lower-armenian, lower-roman, upper-armenian, and upper-roman.

Fixed a rendering issue where we would position list items incorrectly
in list-style-position:inside cases because of measuring the list marker
widths and the list marker suffix widths separately and adding them
instead of measuring them together. This was causing some of the
Web Platform Tests, done using ref tests, to fail.

  • accessibility/AccessibilityObject.cpp:

(WebCore::listMarkerTextForNode): Updated since
RenderListItem::markerTextWithSuffix now returns a StringView.

  • accessibility/AccessibilityRenderObject.cpp:

(WebCore::AccessibilityRenderObject::stringValue const): Updated
to call RenderListMarker::textWithoutSuffix.

  • accessibility/atk/WebKitAccessibleHyperlink.cpp:

(rangeLengthForObject): Ditto.

  • accessibility/atk/WebKitAccessibleInterfaceText.cpp:

(accessibilityObjectLength): Ditto.
(webkitAccessibleTextGetText): Updated since
RenderListItem::markerTextWithSuffix now returns a StringView.

  • css/CSSPrimitiveValueMappings.h:

(WebCore::toCSSValueID): Factored this out into a separate helper.
Also made it take advantage of the relationship between the enumeration
and the CSS value keywords that the code in the other direction already
was relying on so we don't have to list all the keywords.
(WebCore::CSSPrimitiveValue::CSSPrimitiveValue): Refactored to call the
toCSSValueID function.

  • css/CSSValueKeywords.in: Added 12 new list-type-style constants:

disclosure-open, disclosure-closed, japanese-informal, japanese-formal,
korean-hangul-formal, korean-hanja-informal, korean-hanja-formal,
simp-chinese-informal, simp-chinese-formal, trad-chinese-informal,
trad-chinese-formal, and ethiopic-numeric.

  • css/parser/CSSPropertyParserHelpers.cpp:

(WebCore::CSSPropertyParserHelpers::isPredefinedCounterStyle): Updated
since the last predefined counter style is EthiopicNumeric.

  • rendering/RenderListItem.cpp:

(WebCore::RenderListItem::markerTextWithoutSuffix const): Renamed from
markerText, and changed to return a StringView.
(WebCore::RenderListItem::markerTextWithSuffix const): Return a StringView.

  • rendering/RenderListItem.h: Updated for the above.
  • rendering/RenderListMarker.cpp:

(WebCore::toRoman): Deleted.
(WebCore::toAlphabeticOrNumeric): Tweaked to use compile time instead of
runtime checks for alphabetic vs. numeric.
(WebCore::toSymbolic): Updated for above.
(WebCore::toAlphabetic): Ditto.
(WebCore::toNumeric): Ditto.
(WebCore::toHebrewUnder1000): Deleted.
(WebCore::toHebrew): Deleted.
(WebCore::toArmenianUnder10000): Deleted.
(WebCore::toArmenian): Deleted.
(WebCore::toGeorgian): Deleted.
(WebCore::toCJKIdeographic): Added handling for negative numbers and also
tweaked coding style a bit.
(WebCore::toPredefinedAdditiveSystem): Added. Implements the additive
system concept, which we use below to re-implement Hebrew, Armenian,
Georgian, Japanese, and Korean styles.
(WebCore::toEthiopicNumeric): Added.
(WebCore::effectiveListMarkerType): Added the new styles. Also updated the
allowable values for CJKIdeographic to allow negative numbers, and for Hebrew
to no longer allow 0 or numbers over 10999. Also sorted the sections by the
name of the first list style type in each section.
(WebCore::listMarkerSuffix): Changed to return a StringView instead of a
UChar, and include the trailing space. Choose the suffix based on the
specified type and not the effective type, so fallback does not cause the
suffix to fall back. Added the new types.
(WebCore::suffixRequiresSpace): Deleted.
(WebCore::listMarkerText): Added implementations for all the new types.
Also updated the implementation of CJKIdeographic, LowerRoman, UpperRoman,
Armenian, UpperArmenian, LowerArmenian, Georgian, and Hebrew to match a
newer CSS specification draft, and in most cases was able to use
toPredefinedAdditiveSystem instead of language-specific functions.
(WebCore::RenderListMarker::createInlineBox): Stop using the isText function,
which was only used here.
(WebCore::RenderListMarker::paint): Updated for the name change of
relativeMarkerRect. Removed unneeded special case for ListStyleType::None.
Use the new RenderListMarker::textRun function, moving all the code that
deals with direction and suffix in there.
(WebCore::reversed): Added. Helper used by textRun.
(WebCore::RenderListMarker::textRun const): Added. Composes a TextRun for
drawing or measuring text. By using the same function in all those places,
we guarantee we measure the text together instead of in pieces, which fixes
some layout errors leading to test failures that measuring separately and
adding the results together was causing.
(WebCore::RenderListMarker::addOverflowFromListMarker): Use the data
member m_lineOffsetForListItem instead of the lineOffsetForListItem
function, which was only used here.
(WebCore::RenderListMarker::updateMarginsAndContent): Moved the check of
preferredLogicalWidthsDirty and the comment about it here.
(WebCore::RenderListMarker::updateContent): Moved check of
preferredLogicalWidthsDirty out of this function since one caller asserts
it, and so the other caller can do the check itself. Added code to set
m_textWithSuffix, m_textWithoutSuffixLength, and m_textIsLeftToRightDirection.
Removed unneeded special cases for ListStyleType::None, Circle, Disc, and
Square, which are all handled correctly by the main algorithm. Added a FIXME
about the inadequacy of our bidi algorithm implementation for the general case.
(WebCore::RenderListMarker::computePreferredLogicalWidths): Use the new
textRun function, allowing us to remove some special case code, including
the special cases for ListStyleType::None, Asterisks, Footnotes, and String.
(WebCore::RenderListMarker::updateMargins): Removed unneeded special case for
ListStyleType::None, and updated string empty checks for the new name of the
m_textWithSuffix data member.
(WebCore::RenderListMarker::suffix const): Deleted.
(WebCore::RenderListMarker::relativeMarkerRect): Renamed from
getRelativeMarkerRect. Use the new textRun function, allowing us to remove
some special case code, including the special cases for ListTyleType::None,
Asterisks, Footnotes, and String.
(WebCore::RenderListMarker::textWithoutSuffix const): Added.

  • rendering/RenderListMarker.h: Marked functions as final instead of just

override. Got rid of unneeded suffix and lineOffsetForListItem functions.
Renamed text ot textWithoutSuffix and added textWithSuffix. Added textRun
private member function. Replaced m_text with m_textWithSuffix,
m_textWithoutSuffixLength, and m_textIsLeftToRightDirection.

  • rendering/RenderTreeAsText.cpp:

(WebCore::RenderTreeAsText::writeRenderObject): Use textWithoutSuffix.
(WebCore::markerTextForListItem): Use markerTextWithoutSuffix.

  • rendering/style/RenderStyleConstants.cpp:

(WebCore::operator<<): Use getValueName from CSSValueKeywords.h and
toCSSValueID to avoid repeating the names of all the list style types here.

  • rendering/style/RenderStyleConstants.h: Added the 12 new list style types.

Source/WTF:

  • wtf/unicode/CharacterNames.h: Added blackDown/Left/RightPointingSmallTriangle.

LayoutTests:

  • fast/lists/li-values-expected.txt: Updated to expect newly specified behavior. When

this test was written, the specification was different.

  • fast/lists/li-values.html: Ditto.
  • fast/lists/w3-css3-list-styles-fallback-style-expected.txt: Ditto. Also many of these

were expecting failures.

  • fast/lists/w3-css3-list-styles-fallback-style.html: Ditto.
  • fast/lists/w3-css3-list-styles-numeric-expected.txt: Ditto. Also added tests for

ethiopic-numeric.

  • fast/lists/w3-css3-list-styles-numeric.html: Ditto.
  • fast/lists/w3-list-styles-expected.txt: Updated expected result for 0 in Hebrew.
  • platform/mac/TestExpectations: Moved some image failure expectations from here to the

main TestExpectations because they do not seem to be platform-specific.

Location:
trunk
Files:
27 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r279158 r279165  
     12021-06-21  Darin Adler  <darin@apple.com>
     2
     3        Improve more of the CSS list style implementations
     4        https://bugs.webkit.org/show_bug.cgi?id=227206
     5
     6        Reviewed by Antti Koivisto.
     7
     8        * TestExpectations: Expect about 50 more css-counter-styles tests to pass.
     9
     10        * fast/lists/li-values-expected.txt: Updated to expect newly specified behavior. When
     11        this test was written, the specification was different.
     12        * fast/lists/li-values.html: Ditto.
     13        * fast/lists/w3-css3-list-styles-fallback-style-expected.txt: Ditto. Also many of these
     14        were expecting failures.
     15        * fast/lists/w3-css3-list-styles-fallback-style.html: Ditto.
     16        * fast/lists/w3-css3-list-styles-numeric-expected.txt: Ditto. Also added tests for
     17        ethiopic-numeric.
     18        * fast/lists/w3-css3-list-styles-numeric.html: Ditto.
     19
     20        * fast/lists/w3-list-styles-expected.txt: Updated expected result for 0 in Hebrew.
     21
     22        * platform/mac/TestExpectations: Moved some image failure expectations from here to the
     23        main TestExpectations because they do not seem to be platform-specific.
     24
    1252021-06-22  Amir Mark Jr  <amir_mark@apple.com>
    226
  • trunk/LayoutTests/TestExpectations

    r279108 r279165  
    47444744webkit.org/b/224357 imported/w3c/web-platform-tests/css/cssom-view/cssom-getBoundingClientRect-vertical-rl.html [ ImageOnlyFailure ]
    47454745
    4746 # @counter-style ref tests that currently fail
     4746# Counter style tests that fail on some platforms because of subtle character positioning differences, presumably from subpixel rounding.
     4747# These failures are slightly different per-platform, but it seems unwise to move the expectations into platform-specific expectations files.
     4748imported/w3c/web-platform-tests/css/css-counter-styles/bengali/css3-counter-styles-117.html [ Pass ImageOnlyFailure ]
     4749imported/w3c/web-platform-tests/css/css-counter-styles/gujarati/css3-counter-styles-123.html [ Pass ImageOnlyFailure ]
     4750imported/w3c/web-platform-tests/css/css-counter-styles/gurmukhi/css3-counter-styles-126.html [ Pass ImageOnlyFailure ]
     4751imported/w3c/web-platform-tests/css/css-counter-styles/hebrew/css3-counter-styles-016a.html [ Pass ImageOnlyFailure ]
     4752imported/w3c/web-platform-tests/css/css-counter-styles/lao/css3-counter-styles-132.html [ Pass ImageOnlyFailure ]
     4753imported/w3c/web-platform-tests/css/css-counter-styles/lower-armenian/css3-counter-styles-114.html [ Pass ImageOnlyFailure ]
     4754imported/w3c/web-platform-tests/css/css-counter-styles/lower-roman/css3-counter-styles-020.html [ Pass ImageOnlyFailure ]
     4755imported/w3c/web-platform-tests/css/css-counter-styles/upper-roman/css3-counter-styles-024.html [ Pass ImageOnlyFailure ]
     4756
     4757# Tests that fail because @counter-style is not implemented yet. Could skip the entire directory instead.
    47474758imported/w3c/web-platform-tests/css/css-counter-styles/cssom/cssom-additive-symbols-setter-invalid.html [ ImageOnlyFailure ]
    47484759imported/w3c/web-platform-tests/css/css-counter-styles/cssom/cssom-additive-symbols-setter.html [ ImageOnlyFailure ]
     
    47644775imported/w3c/web-platform-tests/css/css-counter-styles/cssom/cssom-system-setter-2.html [ ImageOnlyFailure ]
    47654776imported/w3c/web-platform-tests/css/css-counter-styles/cssom/cssom-system-setter-invalid.html [ ImageOnlyFailure ]
    4766 imported/w3c/web-platform-tests/css/css-counter-styles/hebrew/css3-counter-styles-016a.html [ ImageOnlyFailure ]
    4767 imported/w3c/web-platform-tests/css/css-counter-styles/japanese-formal/css3-counter-styles-047.html [ ImageOnlyFailure ]
    4768 imported/w3c/web-platform-tests/css/css-counter-styles/japanese-formal/css3-counter-styles-048.html [ ImageOnlyFailure ]
    4769 imported/w3c/web-platform-tests/css/css-counter-styles/japanese-formal/css3-counter-styles-049.html [ ImageOnlyFailure ]
    4770 imported/w3c/web-platform-tests/css/css-counter-styles/japanese-formal/css3-counter-styles-050.html [ ImageOnlyFailure ]
    4771 imported/w3c/web-platform-tests/css/css-counter-styles/japanese-formal/css3-counter-styles-051.html [ ImageOnlyFailure ]
    4772 imported/w3c/web-platform-tests/css/css-counter-styles/japanese-informal/css3-counter-styles-042.html [ ImageOnlyFailure ]
    4773 imported/w3c/web-platform-tests/css/css-counter-styles/japanese-informal/css3-counter-styles-043.html [ ImageOnlyFailure ]
    4774 imported/w3c/web-platform-tests/css/css-counter-styles/japanese-informal/css3-counter-styles-044.html [ ImageOnlyFailure ]
    4775 imported/w3c/web-platform-tests/css/css-counter-styles/japanese-informal/css3-counter-styles-045.html [ ImageOnlyFailure ]
    4776 imported/w3c/web-platform-tests/css/css-counter-styles/japanese-informal/css3-counter-styles-046.html [ ImageOnlyFailure ]
    4777 imported/w3c/web-platform-tests/css/css-counter-styles/korean-hangul-formal/css3-counter-styles-052.html [ ImageOnlyFailure ]
    4778 imported/w3c/web-platform-tests/css/css-counter-styles/korean-hangul-formal/css3-counter-styles-053.html [ ImageOnlyFailure ]
    4779 imported/w3c/web-platform-tests/css/css-counter-styles/korean-hangul-formal/css3-counter-styles-054.html [ ImageOnlyFailure ]
    4780 imported/w3c/web-platform-tests/css/css-counter-styles/korean-hangul-formal/css3-counter-styles-055.html [ ImageOnlyFailure ]
    4781 imported/w3c/web-platform-tests/css/css-counter-styles/korean-hangul-formal/css3-counter-styles-056.html [ ImageOnlyFailure ]
    4782 imported/w3c/web-platform-tests/css/css-counter-styles/korean-hanja-formal/css3-counter-styles-062.html [ ImageOnlyFailure ]
    4783 imported/w3c/web-platform-tests/css/css-counter-styles/korean-hanja-formal/css3-counter-styles-063.html [ ImageOnlyFailure ]
    4784 imported/w3c/web-platform-tests/css/css-counter-styles/korean-hanja-formal/css3-counter-styles-064.html [ ImageOnlyFailure ]
    4785 imported/w3c/web-platform-tests/css/css-counter-styles/korean-hanja-formal/css3-counter-styles-065.html [ ImageOnlyFailure ]
    4786 imported/w3c/web-platform-tests/css/css-counter-styles/korean-hanja-formal/css3-counter-styles-066.html [ ImageOnlyFailure ]
    4787 imported/w3c/web-platform-tests/css/css-counter-styles/korean-hanja-informal/css3-counter-styles-057.html [ ImageOnlyFailure ]
    4788 imported/w3c/web-platform-tests/css/css-counter-styles/korean-hanja-informal/css3-counter-styles-058.html [ ImageOnlyFailure ]
    4789 imported/w3c/web-platform-tests/css/css-counter-styles/korean-hanja-informal/css3-counter-styles-059.html [ ImageOnlyFailure ]
    4790 imported/w3c/web-platform-tests/css/css-counter-styles/korean-hanja-informal/css3-counter-styles-060.html [ ImageOnlyFailure ]
    4791 imported/w3c/web-platform-tests/css/css-counter-styles/korean-hanja-informal/css3-counter-styles-061.html [ ImageOnlyFailure ]
    4792 imported/w3c/web-platform-tests/css/css-counter-styles/lower-armenian/css3-counter-styles-114.html [ ImageOnlyFailure ]
    4793 imported/w3c/web-platform-tests/css/css-counter-styles/lower-roman/css3-counter-styles-019.html [ ImageOnlyFailure ]
    4794 imported/w3c/web-platform-tests/css/css-counter-styles/lower-roman/css3-counter-styles-020.html [ ImageOnlyFailure ]
    4795 imported/w3c/web-platform-tests/css/css-counter-styles/lower-roman/css3-counter-styles-020a.html [ ImageOnlyFailure ]
    4796 imported/w3c/web-platform-tests/css/css-counter-styles/lower-roman/css3-counter-styles-020b.html [ ImageOnlyFailure ]
    4797 imported/w3c/web-platform-tests/css/css-counter-styles/simp-chinese-formal/css3-counter-styles-076.html [ ImageOnlyFailure ]
    4798 imported/w3c/web-platform-tests/css/css-counter-styles/simp-chinese-formal/css3-counter-styles-077.html [ ImageOnlyFailure ]
    4799 imported/w3c/web-platform-tests/css/css-counter-styles/simp-chinese-formal/css3-counter-styles-078.html [ ImageOnlyFailure ]
    4800 imported/w3c/web-platform-tests/css/css-counter-styles/simp-chinese-formal/css3-counter-styles-079.html [ ImageOnlyFailure ]
    4801 imported/w3c/web-platform-tests/css/css-counter-styles/simp-chinese-formal/css3-counter-styles-080.html [ ImageOnlyFailure ]
    4802 imported/w3c/web-platform-tests/css/css-counter-styles/simp-chinese-informal/css3-counter-styles-071.html [ ImageOnlyFailure ]
    4803 imported/w3c/web-platform-tests/css/css-counter-styles/simp-chinese-informal/css3-counter-styles-072.html [ ImageOnlyFailure ]
    4804 imported/w3c/web-platform-tests/css/css-counter-styles/simp-chinese-informal/css3-counter-styles-073.html [ ImageOnlyFailure ]
    4805 imported/w3c/web-platform-tests/css/css-counter-styles/simp-chinese-informal/css3-counter-styles-074.html [ ImageOnlyFailure ]
    4806 imported/w3c/web-platform-tests/css/css-counter-styles/simp-chinese-informal/css3-counter-styles-075.html [ ImageOnlyFailure ]
    4807 imported/w3c/web-platform-tests/css/css-counter-styles/trad-chinese-formal/css3-counter-styles-086.html [ ImageOnlyFailure ]
    4808 imported/w3c/web-platform-tests/css/css-counter-styles/trad-chinese-formal/css3-counter-styles-087.html [ ImageOnlyFailure ]
    4809 imported/w3c/web-platform-tests/css/css-counter-styles/trad-chinese-formal/css3-counter-styles-088.html [ ImageOnlyFailure ]
    4810 imported/w3c/web-platform-tests/css/css-counter-styles/trad-chinese-formal/css3-counter-styles-089.html [ ImageOnlyFailure ]
    4811 imported/w3c/web-platform-tests/css/css-counter-styles/trad-chinese-formal/css3-counter-styles-090.html [ ImageOnlyFailure ]
    4812 imported/w3c/web-platform-tests/css/css-counter-styles/trad-chinese-informal/css3-counter-styles-081.html [ ImageOnlyFailure ]
    4813 imported/w3c/web-platform-tests/css/css-counter-styles/trad-chinese-informal/css3-counter-styles-082.html [ ImageOnlyFailure ]
    4814 imported/w3c/web-platform-tests/css/css-counter-styles/trad-chinese-informal/css3-counter-styles-083.html [ ImageOnlyFailure ]
    4815 imported/w3c/web-platform-tests/css/css-counter-styles/trad-chinese-informal/css3-counter-styles-084.html [ ImageOnlyFailure ]
    4816 imported/w3c/web-platform-tests/css/css-counter-styles/trad-chinese-informal/css3-counter-styles-085.html [ ImageOnlyFailure ]
    4817 imported/w3c/web-platform-tests/css/css-counter-styles/upper-roman/css3-counter-styles-023.html [ ImageOnlyFailure ]
    4818 imported/w3c/web-platform-tests/css/css-counter-styles/upper-roman/css3-counter-styles-024.html [ ImageOnlyFailure ]
    4819 imported/w3c/web-platform-tests/css/css-counter-styles/upper-roman/css3-counter-styles-024a.html [ ImageOnlyFailure ]
    48204777
    48214778# CSS will-change failures
  • trunk/LayoutTests/fast/lists/li-values-expected.txt

    r102290 r279165  
    14140 The list marker should fall back to decimal 0 (georgian: 1-19999).
    15150 The list marker should fall back to decimal 0 (ancient-tamil: 1-9999).
    16 -1 The list marker should fall back to cjk-decimal -1 (japanese-informal: 0-9999).
    17 -1 The list marker should fall back to cjk-decimal -1 (japanese-formal: 0-9999).
    18 -1 The list marker should fall back to decimal -1 (korean-hangul-formal: 0-9999).
    19 -1 The list marker should fall back to decimal -1 (korean-hanja-informal: 0-9999).
    20 -1 The list marker should fall back to decimal -1 (korean-hanja-formal: 0-9999).
     16一〇〇〇〇 The list marker should fall back to cjk-decimal 10000 (japanese-informal: -9999-9999).
     17-10000 The list marker should fall back to decimal -10000 (japanese-informal: -9999-9999).
     18一〇〇〇〇 The list marker should fall back to cjk-decimal 10000 (japanese-formal: -9999-9999).
     19-10000 The list marker should fall back to decimal -10000 (japanese-formal: -9999-9999).
     20-10000 The list marker should fall back to decimal -10000 (korean-hangul-formal: -9999-9999).
     21-10000 The list marker should fall back to decimal -10000 (korean-hanja-informal: -9999-9999).
     22-10000 The list marker should fall back to decimal -10000 (korean-hanja-formal: -9999-9999).
    21230 The list marker should fall back to decimal 0 (greek: 1-999).
    2224
  • trunk/LayoutTests/fast/lists/li-values.html

    r122687 r279165  
    4141    <li value="0" style="list-style-type: georgian;">The list marker should fall back to decimal 0 (georgian: 1-19999).</li>
    4242    <li value="0" style="list-style-type: ancient-tamil;">The list marker should fall back to decimal 0 (ancient-tamil: 1-9999).</li>
    43     <!-- FIXME: We don't currently support this list-style-type -> fall back to decimal -->
    44     <li value="-1" style="list-style-type: japanese-informal;">The list marker should fall back to cjk-decimal -1 (japanese-informal: 0-9999).</li>
    45     <!-- FIXME: We don't currently support this list-style-type -> fall back to decimal -->
    46     <li value="-1" style="list-style-type: japanese-formal;">The list marker should fall back to cjk-decimal -1 (japanese-formal: 0-9999).</li>
    47     <li value="-1" style="list-style-type: korean-hangul-formal;">The list marker should fall back to decimal -1 (korean-hangul-formal: 0-9999).</li>
    48     <li value="-1" style="list-style-type: korean-hanja-informal;">The list marker should fall back to decimal -1 (korean-hanja-informal: 0-9999).</li>
    49     <li value="-1" style="list-style-type: korean-hanja-formal;">The list marker should fall back to decimal -1 (korean-hanja-formal: 0-9999).</li>
     43    <li value="10000" style="list-style-type: japanese-informal;">The list marker should fall back to cjk-decimal 10000 (japanese-informal: -9999-9999).</li>
     44    <li value="-10000" style="list-style-type: japanese-informal;">The list marker should fall back to decimal -10000 (japanese-informal: -9999-9999).</li>
     45    <li value="10000" style="list-style-type: japanese-formal;">The list marker should fall back to cjk-decimal 10000 (japanese-formal: -9999-9999).</li>
     46    <li value="-10000" style="list-style-type: japanese-formal;">The list marker should fall back to decimal -10000 (japanese-formal: -9999-9999).</li>
     47    <li value="-10000" style="list-style-type: korean-hangul-formal;">The list marker should fall back to decimal -10000 (korean-hangul-formal: -9999-9999).</li>
     48    <li value="-10000" style="list-style-type: korean-hanja-informal;">The list marker should fall back to decimal -10000 (korean-hanja-informal: -9999-9999).</li>
     49    <li value="-10000" style="list-style-type: korean-hanja-formal;">The list marker should fall back to decimal -10000 (korean-hanja-formal: -9999-9999).</li>
    5050    <li value="0" style="list-style-type: greek;">The list marker should fall back to decimal 0 (greek: 1-999).</li>
    5151</ol>
  • trunk/LayoutTests/fast/lists/w3-css3-list-styles-fallback-style-expected.txt

    r279055 r279165  
    1212cjk-ideographic
    1313
    14 PASS list marker is -1.
     14PASS list marker is 負一.
    1515PASS list marker is 零.
    1616PASS list marker is 一.
     
    1919PASS list marker is -1.
    2020PASS list marker is 0.
    21 PASS list marker is 1.
     21PASS list marker is .
    2222georgian
    2323
     
    3131
    3232PASS list marker is -1.
    33 PASS list marker is אפס.
     33PASS list marker is 0.
    3434PASS list marker is א.
    35 PASS list marker is תתקצט'תתקצט.
     35PASS list marker is 999999.
    3636PASS list marker is 1000000.
    3737PASS list marker is 1000001.
    3838japanese-formal
    3939
    40 PASS list marker is -1.
    41 PASS list marker is 0.
    42 PASS list marker is 1.
     40PASS list marker is マイナス壱.
     41PASS list marker is .
     42PASS list marker is .
    4343japanese-informal
    4444
    45 PASS list marker is -1.
    46 PASS list marker is 0.
    47 PASS list marker is 1.
     45PASS list marker is マイナス一.
     46PASS list marker is .
     47PASS list marker is .
    4848lower-armenian
    4949
     
    5858simp-chinese-formal
    5959
    60 PASS list marker is -1.
    61 PASS list marker is 0.
    62 PASS list marker is 1.
     60PASS list marker is 负壹.
     61PASS list marker is .
     62PASS list marker is .
    6363simp-chinese-informal
    6464
    65 PASS list marker is -1.
    66 PASS list marker is 0.
    67 PASS list marker is 1.
     65PASS list marker is 负一.
     66PASS list marker is .
     67PASS list marker is .
    6868syriac
    6969
     
    7878trad-chinese-formal
    7979
    80 PASS list marker is -1.
    81 PASS list marker is 0.
    82 PASS list marker is 1.
     80PASS list marker is 負壹.
     81PASS list marker is .
     82PASS list marker is .
    8383trad-chinese-informal
    8484
    85 PASS list marker is -1.
    86 PASS list marker is 0.
    87 PASS list marker is 1.
     85PASS list marker is 負一.
     86PASS list marker is .
     87PASS list marker is .
    8888upper-armenian
    8989
  • trunk/LayoutTests/fast/lists/w3-css3-list-styles-fallback-style.html

    r279055 r279165  
    1616       
    1717        ol.armenian { list-style-type: armenian; }
    18        
    1918        ol.cjk-ideographic { list-style-type: cjk-ideographic; }
    20        
    2119        ol.ethiopic-numeric { list-style-type: ethiopic-numeric; }
    22        
    2320        ol.georgian { list-style-type: georgian; }
    24        
    2521        ol.hebrew { list-style-type: hebrew; }
    26        
    2722        ol.japanese-formal { list-style-type: japanese-formal; }
    28        
    2923        ol.japanese-informal { list-style-type: japanese-informal; }
    30        
    3124        ol.lower-armenian { list-style-type: lower-armenian; }
    32        
    3325        ol.lower-roman { list-style-type: lower-roman; }
    34        
    3526        ol.simp-chinese-formal { list-style-type: simp-chinese-formal; }
    36        
    3727        ol.simp-chinese-informal { list-style-type: simp-chinese-informal; }
    38        
    3928        ol.syriac { list-style-type: syriac; }
    40        
    4129        ol.tamil { list-style-type: tamil; }
    42        
    4330        ol.trad-chinese-formal { list-style-type: trad-chinese-formal; }
    44        
    4531        ol.trad-chinese-informal { list-style-type: trad-chinese-informal; }
    46        
    4732        ol.upper-armenian { list-style-type: upper-armenian; }
    48        
    4933        ol.upper-roman { list-style-type: upper-roman; }
    5034    </style>
     
    6751    <div id="description">
    6852        <p>This tests that we fallback to the decimal list style type when the ordinal is outside the representable range for the list style type as per the <a href="http://www.w3.org/TR/css3-lists/">CSS3 Lists module</a> (Draft 7 November 2002). This test PASSED if the list item matches its marker for every list item (below).</p>
    69         <p>Note, as of 12/04/2010, ethiopic-numeric; japanese-formal; japanese-informal; simp-chinese-formal; simp-chinese-informal; syriac; tamil; trad-chinese-formal; and trad-chinese-informal are unsupported and hence have expected failure results.</p>
     53        <p>Note, as of 2021-06-20, syriac is unsupported and hence has expected failure results.</p>
    7054    </div>
    7155    <hr/>
     
    8771        <h2>cjk-ideographic</h2>
    8872        <ol class="cjk-ideographic" start="-1">
    89             <li>-1</li>
     73            <li>&#x8CA0;&#x4E00;</li>
    9074            <li>&#x96F6;</li>
    9175            <li>&#x4E00;</li>
     
    9478   
    9579    <div class="test">
    96         <!-- FIXME: We don't currently support this list-style-type. These are expected failure results. -->
    9780        <h2>ethiopic-numeric</h2>
    9881        <ol class="ethiopic-numeric" start="-1">
    9982            <li>-1</li>
    10083            <li>0</li>
    101             <li>1</li>
     84            <li>&#x1369;</li>
    10285        </ol>
    10386    </div>
     
    120103        <ol class="hebrew" start="-1">
    121104            <li>-1</li>
    122             <li>&#x5D0;&#x5E4;&#x5E1;</li>
     105            <li>0</li>
    123106            <li>&#x5D0;</li>
    124107        </ol>
    125108        <ol class="hebrew" start="999999">
    126             <li>&#x5EA;&#x5EA;&#x5E7;&#x5E6;&#x5D8;&#x27;&#x5EA;&#x5EA;&#x5E7;&#x5E6;&#x5D8;</li>
     109            <li>999999</li>
    127110            <li>1000000</li>
    128111            <li>1000001</li>
     
    130113    </div>
    131114    <div class="test">
    132         <!-- FIXME: We don't currently support this list-style-type. These are expected failure results. -->
    133115        <h2>japanese-formal</h2>
    134116        <ol class="japanese-formal" start="-1">
    135             <li>-1</li>
    136             <li>0</li>
    137             <li>1</li>
    138         </ol>
    139     </div>
    140     <div class="test">
    141         <!-- FIXME: We don't currently support this list-style-type. These are expected failure results. -->
     117            <li>&#x30DE;&#x30A4;&#x30CA;&#x30B9;&#x58F1;</li>
     118            <li>&#x96F6;</li>
     119            <li>&#x58F1;</li>
     120        </ol>
     121    </div>
     122    <div class="test">
    142123        <h2>japanese-informal</h2>
    143124        <ol class="japanese-informal" start="-1">
    144             <li>-1</li>
    145             <li>0</li>
    146             <li>1</li>
     125            <li>&#x30DE;&#x30A4;&#x30CA;&#x30B9;&#x4E00;</li>
     126            <li>&#x3007;</li>
     127            <li>&#x4E00;</li>
    147128        </ol>
    148129    </div>
     
    164145    </div>
    165146    <div class="test">
    166         <!-- FIXME: We don't currently support this list-style-type. These are expected failure results. -->
    167147        <h2>simp-chinese-formal</h2>
    168148        <ol class="simp-chinese-formal" start="-1">
    169             <li>-1</li>
    170             <li>0</li>
    171             <li>1</li>
    172         </ol>
    173     </div>
    174     <div class="test">
    175         <!-- FIXME: We don't currently support this list-style-type. These are expected failure results. -->
     149            <li>&#x8D1F;&#x58F9;</li>
     150            <li>&#x96F6;</li>
     151            <li>&#x58F9;</li>
     152        </ol>
     153    </div>
     154    <div class="test">
    176155        <h2>simp-chinese-informal</h2>
    177156        <ol class="simp-chinese-informal" start="-1">
    178             <li>-1</li>
    179             <li>0</li>
    180             <li>1</li>
     157            <li>&#x8D1F;&#x4E00;</li>
     158            <li>&#x96F6;</li>
     159            <li>&#x4E00;</li>
    181160        </ol>
    182161    </div>
     
    199178    </div>
    200179    <div class="test">
    201         <!-- FIXME: We don't currently support this list-style-type. These are expected failure results. -->
    202180        <h2>trad-chinese-formal</h2>
    203181        <ol class="trad-chinese-formal" start="-1">
    204             <li>-1</li>
    205             <li>0</li>
    206             <li>1</li>
    207         </ol>
    208     </div>
    209     <div class="test">
    210         <!-- FIXME: We don't currently support this list-style-type. These are expected failure results. -->
     182            <li>&#x8CA0;&#x58F9;</li>
     183            <li>&#x96F6;</li>
     184            <li>&#x58F9;</li>
     185        </ol>
     186    </div>
     187    <div class="test">
    211188        <h2>trad-chinese-informal</h2>
    212189        <ol class="trad-chinese-informal" start="-1">
    213             <li>-1</li>
    214             <li>0</li>
    215             <li>1</li>
     190            <li>&#x8CA0;&#x4E00;</li>
     191            <li>&#x96F6;</li>
     192            <li>&#x4E00;</li>
    216193        </ol>
    217194    </div>
  • trunk/LayoutTests/fast/lists/w3-css3-list-styles-numeric-expected.txt

    r82713 r279165  
    387387PASS list marker is -80000000.
    388388PASS list marker is -7FFFFFFF.
    389 
     389ethiopic-numeric
     390
     391PASS list marker is ፩.
     392PASS list marker is ፪.
     393PASS list marker is ፫.
     394PASS list marker is ፬.
     395PASS list marker is ፭.
     396PASS list marker is ፮.
     397PASS list marker is ፯.
     398PASS list marker is ፰.
     399PASS list marker is ፱.
     400PASS list marker is ፲.
     401PASS list marker is ፲፩.
     402PASS list marker is 0.
     403PASS list marker is ፻.
     404PASS list marker is ፩.
     405PASS list marker is ፸፰፻፩፼፺፪.
     406PASS list marker is -2147483648.
     407PASS list marker is -2147483647.
     408
  • trunk/LayoutTests/fast/lists/w3-css3-list-styles-numeric.html

    r144524 r279165  
    55        .test ol { float: left; padding-right: 20px; }
    66        .test h2 { clear: left; }
     7        .right { padding-left: 120px; }
    78        .negative-number { padding-left: 300px; }
    89        .negative-number li:before { content: "\002D"; }
     
    1415       
    1516        ol.arabic-indic { list-style-type: arabic-indic; }
    16        
    1717        ol.binary { list-style-type: binary; }
    18        
    1918        ol.bengali { list-style-type: bengali; }
    20        
    2119        ol.cambodian { list-style-type: cambodian; }
    2220        ol.khmer { list-style-type: khmer; }
    23        
    2421        ol.decimal { list-style-type: decimal; }
    25        
    2622        ol.decimal-leading-zero { list-style-type: decimal-leading-zero; }
    27        
    2823        ol.devanagari { list-style-type: devanagari; }
    29        
    3024        ol.gujarati { list-style-type: gujarati; }
    31        
    3225        ol.gurmukhi { list-style-type: gurmukhi; }
    33        
    3426        ol.kannada { list-style-type: kannada; }
    35        
    3627        ol.lower-hexadecimal { list-style-type: lower-hexadecimal; }
    37        
    3828        ol.lao { list-style-type: lao; }
    39        
    4029        ol.malayalam { list-style-type: malayalam; }
    41        
    4230        ol.mongolian { list-style-type: mongolian; }
    43        
    4431        ol.myanmar { list-style-type: myanmar; }
    45        
    4632        ol.octal { list-style-type: octal; }
    47        
    4833        ol.oriya { list-style-type: oriya; }
    49        
    5034        ol.persian { list-style-type: persian; }
    5135        ol.urdu { list-style-type: urdu; }
    52        
    5336        ol.telugu { list-style-type: telugu; }
    54        
    5537        ol.tibetan { list-style-type: tibetan; }
    56        
    5738        ol.thai { list-style-type: thai; }
    58        
    5939        ol.upper-hexadecimal { list-style-type: upper-hexadecimal; }
    6040    </style>
     
    7252            if (!window.testRunner)
    7353                return;
    74            
     54
    7555            testRunner.dumpAsText();
    7656            filterListsWithReplacement(document.querySelectorAll(".test ol"), testListItemMarkerEqualsListItemText);
     
    706686        </ol>
    707687    </div>
     688
     689    <div class="test">
     690        <h2>ethiopic-numeric</h2>
     691        <ol style="list-style-type: ethiopic-numeric">
     692            <li>&#x1369;</li>
     693            <li>&#x136A;</li>
     694            <li>&#x136B;</li>
     695            <li>&#x136C;</li>
     696            <li>&#x136D;</li>
     697            <li>&#x136E;</li>
     698            <li>&#x136F;</li>
     699            <li>&#x1370;</li>
     700            <li>&#x1371;</li>
     701            <li>&#x1372;</li>
     702            <li>&#x1372;&#x1369;</li>
     703        </ol>
     704        <ol style="list-style-type: ethiopic-numeric" start="0">
     705            <li>0</li>
     706        </ol>
     707        <ol style="list-style-type: ethiopic-numeric" start="100">
     708            <li>&#x137B;</li>
     709        </ol>
     710        <ol style="list-style-type: ethiopic-numeric" start="-2147483649">
     711            <li>&#x1369;</li>
     712        </ol>
     713        <ol style="list-style-type: ethiopic-numeric" class="right" start="78010092">
     714            <li>&#x1378;&#x1370;&#x137B;&#x1369;&#x137C;&#x137A;&#x136A;</li>
     715        </ol>
     716        <ol style="list-style-type: ethiopic-numeric" class="negative-number" start="-2147483648">
     717            <li>2147483648</li>
     718            <li>2147483647</li>
     719        </ol>
     720    </div>
    708721</body>
    709722</html>
  • trunk/LayoutTests/fast/lists/w3-list-styles-expected.txt

    r64186 r279165  
    230230ק hundred, undefined, may show ק
    231231קא a hundred and one, undefined, may show קא
    232 אפס zero, undefined, may show אפס
     2320 zero, undefined, may show אפס
    233233א one, should show א
    234234georgian
  • trunk/LayoutTests/platform/mac/TestExpectations

    r279145 r279165  
    21642164# @counter-style WPT failures specific to Mac platforms
    21652165[ Mojave Catalina ] imported/w3c/web-platform-tests/css/css-counter-styles/lower-armenian/css3-counter-styles-112.html [ ImageOnlyFailure ]
    2166 imported/w3c/web-platform-tests/css/css-counter-styles/bengali/css3-counter-styles-117.html [ ImageOnlyFailure ]
    2167 imported/w3c/web-platform-tests/css/css-counter-styles/gujarati/css3-counter-styles-123.html [ ImageOnlyFailure ]
    2168 imported/w3c/web-platform-tests/css/css-counter-styles/gurmukhi/css3-counter-styles-126.html [ ImageOnlyFailure ]
    2169 imported/w3c/web-platform-tests/css/css-counter-styles/lao/css3-counter-styles-132.html [ ImageOnlyFailure ]
    21702166
    21712167webkit.org/b/222185 media/media-extension-with-fragment.html [ Crash ]
  • trunk/Source/WTF/ChangeLog

    r279164 r279165  
     12021-06-21  Darin Adler  <darin@apple.com>
     2
     3        Improve more of the CSS list style implementations
     4        https://bugs.webkit.org/show_bug.cgi?id=227206
     5
     6        Reviewed by Antti Koivisto.
     7
     8        * wtf/unicode/CharacterNames.h: Added blackDown/Left/RightPointingSmallTriangle.
     9
    1102021-06-22  Wenson Hsieh  <wenson_hsieh@apple.com>
    211
  • trunk/Source/WTF/wtf/unicode/CharacterNames.h

    r266681 r279165  
    4242constexpr UChar apostrophe = 0x0027;
    4343constexpr UChar blackCircle = 0x25CF;
     44constexpr UChar blackDownPointingSmallTriangle = 0x25BE;
     45constexpr UChar blackLeftPointingSmallTriangle = 0x25C2;
     46constexpr UChar blackRightPointingSmallTriangle = 0x25B8;
    4447constexpr UChar blackSquare = 0x25A0;
    4548constexpr UChar blackUpPointingTriangle = 0x25B2;
     
    114117using WTF::Unicode::aegeanWordSeparatorLine;
    115118using WTF::Unicode::blackCircle;
     119using WTF::Unicode::blackDownPointingSmallTriangle;
     120using WTF::Unicode::blackLeftPointingSmallTriangle;
     121using WTF::Unicode::blackRightPointingSmallTriangle;
    116122using WTF::Unicode::blackSquare;
    117123using WTF::Unicode::blackUpPointingTriangle;
  • trunk/Source/WebCore/ChangeLog

    r279164 r279165  
     12021-06-21  Darin Adler  <darin@apple.com>
     2
     3        Improve more of the CSS list style implementations
     4        https://bugs.webkit.org/show_bug.cgi?id=227206
     5
     6        Reviewed by Antti Koivisto.
     7
     8        Added support for 12 new values for list-style-type: disclosure-closed,
     9        disclosure-open, ethiopic-numeric, japanese-formal, japanese-informal,
     10        korean-hangul-formal, korean-hanja-formal, korean-hanja-informal,
     11        simp-chinese-formal, simp-chinese-informal, trad-chinese-informal,
     12        and trad-chinese-formal.
     13
     14        Improved implementation to match specification more closely for a few
     15        existing values for list-style-type: armenian, cjk-ideographic, hebrew,
     16        lower-armenian, lower-roman, upper-armenian, and upper-roman.
     17
     18        Fixed a rendering issue where we would position list items incorrectly
     19        in list-style-position:inside cases because of measuring the list marker
     20        widths and the list marker suffix widths separately and adding them
     21        instead of measuring them together. This was causing some of the
     22        Web Platform Tests, done using ref tests, to fail.
     23
     24        * accessibility/AccessibilityObject.cpp:
     25        (WebCore::listMarkerTextForNode): Updated since
     26        RenderListItem::markerTextWithSuffix now returns a StringView.
     27        * accessibility/AccessibilityRenderObject.cpp:
     28        (WebCore::AccessibilityRenderObject::stringValue const): Updated
     29        to call RenderListMarker::textWithoutSuffix.
     30        * accessibility/atk/WebKitAccessibleHyperlink.cpp:
     31        (rangeLengthForObject): Ditto.
     32        * accessibility/atk/WebKitAccessibleInterfaceText.cpp:
     33        (accessibilityObjectLength): Ditto.
     34        (webkitAccessibleTextGetText): Updated since
     35        RenderListItem::markerTextWithSuffix now returns a StringView.
     36
     37        * css/CSSPrimitiveValueMappings.h:
     38        (WebCore::toCSSValueID): Factored this out into a separate helper.
     39        Also made it take advantage of the relationship between the enumeration
     40        and the CSS value keywords that the code in the other direction already
     41        was relying on so we don't have to list all the keywords.
     42        (WebCore::CSSPrimitiveValue::CSSPrimitiveValue): Refactored to call the
     43        toCSSValueID function.
     44
     45        * css/CSSValueKeywords.in: Added 12 new list-type-style constants:
     46        disclosure-open, disclosure-closed, japanese-informal, japanese-formal,
     47        korean-hangul-formal, korean-hanja-informal, korean-hanja-formal,
     48        simp-chinese-informal, simp-chinese-formal, trad-chinese-informal,
     49        trad-chinese-formal, and ethiopic-numeric.
     50
     51        * css/parser/CSSPropertyParserHelpers.cpp:
     52        (WebCore::CSSPropertyParserHelpers::isPredefinedCounterStyle): Updated
     53        since the last predefined counter style is EthiopicNumeric.
     54
     55        * rendering/RenderListItem.cpp:
     56        (WebCore::RenderListItem::markerTextWithoutSuffix const): Renamed from
     57        markerText, and changed to return a StringView.
     58        (WebCore::RenderListItem::markerTextWithSuffix const): Return a StringView.
     59        * rendering/RenderListItem.h: Updated for the above.
     60
     61        * rendering/RenderListMarker.cpp:
     62        (WebCore::toRoman): Deleted.
     63        (WebCore::toAlphabeticOrNumeric): Tweaked to use compile time instead of
     64        runtime checks for alphabetic vs. numeric.
     65        (WebCore::toSymbolic): Updated for above.
     66        (WebCore::toAlphabetic): Ditto.
     67        (WebCore::toNumeric): Ditto.
     68        (WebCore::toHebrewUnder1000): Deleted.
     69        (WebCore::toHebrew): Deleted.
     70        (WebCore::toArmenianUnder10000): Deleted.
     71        (WebCore::toArmenian): Deleted.
     72        (WebCore::toGeorgian): Deleted.
     73        (WebCore::toCJKIdeographic): Added handling for negative numbers and also
     74        tweaked coding style a bit.
     75        (WebCore::toPredefinedAdditiveSystem): Added. Implements the additive
     76        system concept, which we use below to re-implement Hebrew, Armenian,
     77        Georgian, Japanese, and Korean styles.
     78        (WebCore::toEthiopicNumeric): Added.
     79        (WebCore::effectiveListMarkerType): Added the new styles. Also updated the
     80        allowable values for CJKIdeographic to allow negative numbers, and for Hebrew
     81        to no longer allow 0 or numbers over 10999. Also sorted the sections by the
     82        name of the first list style type in each section.
     83        (WebCore::listMarkerSuffix): Changed to return a StringView instead of a
     84        UChar, and include the trailing space. Choose the suffix based on the
     85        specified type and not the effective type, so fallback does not cause the
     86        suffix to fall back. Added the new types.
     87        (WebCore::suffixRequiresSpace): Deleted.
     88        (WebCore::listMarkerText): Added implementations for all the new types.
     89        Also updated the implementation of CJKIdeographic, LowerRoman, UpperRoman,
     90        Armenian, UpperArmenian, LowerArmenian, Georgian, and Hebrew to match a
     91        newer CSS specification draft, and in most cases was able to use
     92        toPredefinedAdditiveSystem instead of language-specific functions.
     93        (WebCore::RenderListMarker::createInlineBox): Stop using the isText function,
     94        which was only used here.
     95        (WebCore::RenderListMarker::paint): Updated for the name change of
     96        relativeMarkerRect. Removed unneeded special case for ListStyleType::None.
     97        Use the new RenderListMarker::textRun function, moving all the code that
     98        deals with direction and suffix in there.
     99        (WebCore::reversed): Added. Helper used by textRun.
     100        (WebCore::RenderListMarker::textRun const): Added. Composes a TextRun for
     101        drawing or measuring text. By using the same function in all those places,
     102        we guarantee we measure the text together instead of in pieces, which fixes
     103        some layout errors leading to test failures that measuring separately and
     104        adding the results together was causing.
     105        (WebCore::RenderListMarker::addOverflowFromListMarker): Use the data
     106        member m_lineOffsetForListItem instead of the lineOffsetForListItem
     107        function, which was only used here.
     108        (WebCore::RenderListMarker::updateMarginsAndContent): Moved the check of
     109        preferredLogicalWidthsDirty and the comment about it here.
     110        (WebCore::RenderListMarker::updateContent): Moved check of
     111        preferredLogicalWidthsDirty out of this function since one caller asserts
     112        it, and so the other caller can do the check itself. Added code to set
     113        m_textWithSuffix, m_textWithoutSuffixLength, and m_textIsLeftToRightDirection.
     114        Removed unneeded special cases for ListStyleType::None, Circle, Disc, and
     115        Square, which are all handled correctly by the main algorithm. Added a FIXME
     116        about the inadequacy of our bidi algorithm implementation for the general case.
     117        (WebCore::RenderListMarker::computePreferredLogicalWidths): Use the new
     118        textRun function, allowing us to remove some special case code, including
     119        the special cases for ListStyleType::None, Asterisks, Footnotes, and String.
     120        (WebCore::RenderListMarker::updateMargins): Removed unneeded special case for
     121        ListStyleType::None, and updated string empty checks for the new name of the
     122        m_textWithSuffix data member.
     123        (WebCore::RenderListMarker::suffix const): Deleted.
     124        (WebCore::RenderListMarker::relativeMarkerRect): Renamed from
     125        getRelativeMarkerRect. Use the new textRun function, allowing us to remove
     126        some special case code, including the special cases for ListTyleType::None,
     127        Asterisks, Footnotes, and String.
     128        (WebCore::RenderListMarker::textWithoutSuffix const): Added.
     129
     130        * rendering/RenderListMarker.h: Marked functions as final instead of just
     131        override. Got rid of unneeded suffix and lineOffsetForListItem functions.
     132        Renamed text ot textWithoutSuffix and added textWithSuffix. Added textRun
     133        private member function. Replaced m_text with m_textWithSuffix,
     134        m_textWithoutSuffixLength, and m_textIsLeftToRightDirection.
     135
     136        * rendering/RenderTreeAsText.cpp:
     137        (WebCore::RenderTreeAsText::writeRenderObject): Use textWithoutSuffix.
     138        (WebCore::markerTextForListItem): Use markerTextWithoutSuffix.
     139
     140        * rendering/style/RenderStyleConstants.cpp:
     141        (WebCore::operator<<): Use getValueName from CSSValueKeywords.h and
     142        toCSSValueID to avoid repeating the names of all the list style types here.
     143
     144        * rendering/style/RenderStyleConstants.h: Added the 12 new list style types.
     145
    11462021-06-22  Wenson Hsieh  <wenson_hsieh@apple.com>
    2147
  • trunk/Source/WebCore/accessibility/AccessibilityObject.cpp

    r278542 r279165  
    11611161    // because a RenderListMarker does not have a Node equivalent and thus does not appear
    11621162    // when iterating text.
    1163     return listItem->markerTextWithSuffix();
     1163    return listItem->markerTextWithSuffix().toString();
    11641164}
    11651165
  • trunk/Source/WebCore/accessibility/AccessibilityRenderObject.cpp

    r278907 r279165  
    771771   
    772772    if (is<RenderListMarker>(*m_renderer))
    773         return downcast<RenderListMarker>(*m_renderer).text();
     773        return downcast<RenderListMarker>(*m_renderer).textWithoutSuffix().toString();
    774774   
    775775    if (isWebArea())
  • trunk/Source/WebCore/accessibility/atk/WebKitAccessibleHyperlink.cpp

    r278542 r279165  
    178178        return baseLength;
    179179
    180     auto& marker = downcast<RenderListMarker>(*renderer);
    181     return baseLength + marker.text().length() + marker.suffix().length();
     180    return baseLength + downcast<RenderListMarker>(*renderer).textWithSuffix().length();
    182181}
    183182
  • trunk/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceText.cpp

    r278542 r279165  
    244244    // for those cases when it's needed to take it into account
    245245    // separately (as in getAccessibilityObjectForOffset)
    246     RenderObject* renderer = object->renderer();
    247     if (is<RenderListMarker>(renderer)) {
    248         auto& marker = downcast<RenderListMarker>(*renderer);
    249         return marker.text().length() + marker.suffix().length();
    250     }
     246    if (auto renderer = object->renderer(); is<RenderListMarker>(renderer))
     247        return downcast<RenderListMarker>(*renderer).textWithSuffix().length();
    251248
    252249    return 0;
     
    462459        RenderObject* objRenderer = coreObject->renderer();
    463460        if (is<RenderListItem>(objRenderer)) {
    464             String markerText = downcast<RenderListItem>(*objRenderer).markerTextWithSuffix();
     461            String markerText = downcast<RenderListItem>(*objRenderer).markerTextWithSuffix().toString();
    465462            ret = objRenderer->style().direction() == TextDirection::LTR ? markerText + ret : ret + markerText;
    466463            if (endOffset == -1)
  • trunk/Source/WebCore/css/CSSPrimitiveValueMappings.h

    r279055 r279165  
    17321732}
    17331733
    1734 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(ListStyleType e)
    1735     : CSSValue(PrimitiveClass)
    1736 {
    1737     setPrimitiveUnitType(CSSUnitType::CSS_VALUE_ID);
    1738     switch (e) {
    1739     case ListStyleType::Afar:
    1740         m_value.valueID = CSSValueAfar;
    1741         break;
    1742     case ListStyleType::Amharic:
    1743         m_value.valueID = CSSValueAmharic;
    1744         break;
    1745     case ListStyleType::AmharicAbegede:
    1746         m_value.valueID = CSSValueAmharicAbegede;
    1747         break;
    1748     case ListStyleType::ArabicIndic:
    1749         m_value.valueID = CSSValueArabicIndic;
    1750         break;
    1751     case ListStyleType::Armenian:
    1752         m_value.valueID = CSSValueArmenian;
    1753         break;
    1754     case ListStyleType::Asterisks:
    1755         m_value.valueID = CSSValueAsterisks;
    1756         break;
    1757     case ListStyleType::Binary:
    1758         m_value.valueID = CSSValueBinary;
    1759         break;
    1760     case ListStyleType::Bengali:
    1761         m_value.valueID = CSSValueBengali;
    1762         break;
    1763     case ListStyleType::CJKDecimal:
    1764         m_value.valueID = CSSValueCjkDecimal;
    1765         break;
    1766     case ListStyleType::CJKEarthlyBranch:
    1767         m_value.valueID = CSSValueCjkEarthlyBranch;
    1768         break;
    1769     case ListStyleType::CJKHeavenlyStem:
    1770         m_value.valueID = CSSValueCjkHeavenlyStem;
    1771         break;
    1772     case ListStyleType::CJKIdeographic:
    1773         m_value.valueID = CSSValueCjkIdeographic;
    1774         break;
    1775     case ListStyleType::Cambodian:
    1776         m_value.valueID = CSSValueCambodian;
    1777         break;
    1778     case ListStyleType::Circle:
    1779         m_value.valueID = CSSValueCircle;
    1780         break;
    1781     case ListStyleType::DecimalLeadingZero:
    1782         m_value.valueID = CSSValueDecimalLeadingZero;
    1783         break;
    1784     case ListStyleType::Decimal:
    1785         m_value.valueID = CSSValueDecimal;
    1786         break;
    1787     case ListStyleType::Devanagari:
    1788         m_value.valueID = CSSValueDevanagari;
    1789         break;
    1790     case ListStyleType::Disc:
    1791         m_value.valueID = CSSValueDisc;
    1792         break;
    1793     case ListStyleType::Ethiopic:
    1794         m_value.valueID = CSSValueEthiopic;
    1795         break;
    1796     case ListStyleType::EthiopicAbegede:
    1797         m_value.valueID = CSSValueEthiopicAbegede;
    1798         break;
    1799     case ListStyleType::EthiopicAbegedeAmEt:
    1800         m_value.valueID = CSSValueEthiopicAbegedeAmEt;
    1801         break;
    1802     case ListStyleType::EthiopicAbegedeGez:
    1803         m_value.valueID = CSSValueEthiopicAbegedeGez;
    1804         break;
    1805     case ListStyleType::EthiopicAbegedeTiEr:
    1806         m_value.valueID = CSSValueEthiopicAbegedeTiEr;
    1807         break;
    1808     case ListStyleType::EthiopicAbegedeTiEt:
    1809         m_value.valueID = CSSValueEthiopicAbegedeTiEt;
    1810         break;
    1811     case ListStyleType::EthiopicHalehameAaEr:
    1812         m_value.valueID = CSSValueEthiopicHalehameAaEr;
    1813         break;
    1814     case ListStyleType::EthiopicHalehameAaEt:
    1815         m_value.valueID = CSSValueEthiopicHalehameAaEt;
    1816         break;
    1817     case ListStyleType::EthiopicHalehameAmEt:
    1818         m_value.valueID = CSSValueEthiopicHalehameAmEt;
    1819         break;
    1820     case ListStyleType::EthiopicHalehameGez:
    1821         m_value.valueID = CSSValueEthiopicHalehameGez;
    1822         break;
    1823     case ListStyleType::EthiopicHalehameOmEt:
    1824         m_value.valueID = CSSValueEthiopicHalehameOmEt;
    1825         break;
    1826     case ListStyleType::EthiopicHalehameSidEt:
    1827         m_value.valueID = CSSValueEthiopicHalehameSidEt;
    1828         break;
    1829     case ListStyleType::EthiopicHalehameSoEt:
    1830         m_value.valueID = CSSValueEthiopicHalehameSoEt;
    1831         break;
    1832     case ListStyleType::EthiopicHalehameTiEr:
    1833         m_value.valueID = CSSValueEthiopicHalehameTiEr;
    1834         break;
    1835     case ListStyleType::EthiopicHalehameTiEt:
    1836         m_value.valueID = CSSValueEthiopicHalehameTiEt;
    1837         break;
    1838     case ListStyleType::EthiopicHalehameTig:
    1839         m_value.valueID = CSSValueEthiopicHalehameTig;
    1840         break;
    1841     case ListStyleType::Footnotes:
    1842         m_value.valueID = CSSValueFootnotes;
    1843         break;
    1844     case ListStyleType::Georgian:
    1845         m_value.valueID = CSSValueGeorgian;
    1846         break;
    1847     case ListStyleType::Gujarati:
    1848         m_value.valueID = CSSValueGujarati;
    1849         break;
    1850     case ListStyleType::Gurmukhi:
    1851         m_value.valueID = CSSValueGurmukhi;
    1852         break;
    1853     case ListStyleType::Hangul:
    1854         m_value.valueID = CSSValueHangul;
    1855         break;
    1856     case ListStyleType::HangulConsonant:
    1857         m_value.valueID = CSSValueHangulConsonant;
    1858         break;
    1859     case ListStyleType::Hebrew:
    1860         m_value.valueID = CSSValueHebrew;
    1861         break;
    1862     case ListStyleType::Hiragana:
    1863         m_value.valueID = CSSValueHiragana;
    1864         break;
    1865     case ListStyleType::HiraganaIroha:
    1866         m_value.valueID = CSSValueHiraganaIroha;
    1867         break;
    1868     case ListStyleType::Kannada:
    1869         m_value.valueID = CSSValueKannada;
    1870         break;
    1871     case ListStyleType::Katakana:
    1872         m_value.valueID = CSSValueKatakana;
    1873         break;
    1874     case ListStyleType::KatakanaIroha:
    1875         m_value.valueID = CSSValueKatakanaIroha;
    1876         break;
    1877     case ListStyleType::Khmer:
    1878         m_value.valueID = CSSValueKhmer;
    1879         break;
    1880     case ListStyleType::Lao:
    1881         m_value.valueID = CSSValueLao;
    1882         break;
    1883     case ListStyleType::LowerAlpha:
    1884         m_value.valueID = CSSValueLowerAlpha;
    1885         break;
    1886     case ListStyleType::LowerArmenian:
    1887         m_value.valueID = CSSValueLowerArmenian;
    1888         break;
    1889     case ListStyleType::LowerGreek:
    1890         m_value.valueID = CSSValueLowerGreek;
    1891         break;
    1892     case ListStyleType::LowerHexadecimal:
    1893         m_value.valueID = CSSValueLowerHexadecimal;
    1894         break;
    1895     case ListStyleType::LowerLatin:
    1896         m_value.valueID = CSSValueLowerLatin;
    1897         break;
    1898     case ListStyleType::LowerNorwegian:
    1899         m_value.valueID = CSSValueLowerNorwegian;
    1900         break;
    1901     case ListStyleType::LowerRoman:
    1902         m_value.valueID = CSSValueLowerRoman;
    1903         break;
    1904     case ListStyleType::Malayalam:
    1905         m_value.valueID = CSSValueMalayalam;
    1906         break;
    1907     case ListStyleType::Mongolian:
    1908         m_value.valueID = CSSValueMongolian;
    1909         break;
    1910     case ListStyleType::Myanmar:
    1911         m_value.valueID = CSSValueMyanmar;
    1912         break;
     1734inline CSSValueID toCSSValueID(ListStyleType style)
     1735{
     1736    switch (style) {
    19131737    case ListStyleType::None:
    1914         m_value.valueID = CSSValueNone;
    1915         break;
    1916     case ListStyleType::Octal:
    1917         m_value.valueID = CSSValueOctal;
    1918         break;
    1919     case ListStyleType::Oriya:
    1920         m_value.valueID = CSSValueOriya;
    1921         break;
    1922     case ListStyleType::Oromo:
    1923         m_value.valueID = CSSValueOromo;
    1924         break;
    1925     case ListStyleType::Persian:
    1926         m_value.valueID = CSSValuePersian;
    1927         break;
    1928     case ListStyleType::Sidama:
    1929         m_value.valueID = CSSValueSidama;
    1930         break;
    1931     case ListStyleType::Somali:
    1932         m_value.valueID = CSSValueSomali;
    1933         break;
    1934     case ListStyleType::Square:
    1935         m_value.valueID = CSSValueSquare;
    1936         break;
     1738        return CSSValueNone;
    19371739    case ListStyleType::String:
    19381740        ASSERT_NOT_REACHED();
    1939         m_value.valueID = CSSValueInvalid;
    1940         break;
    1941     case ListStyleType::Tamil:
    1942         m_value.valueID = CSSValueTamil;
    1943         break;
    1944     case ListStyleType::Telugu:
    1945         m_value.valueID = CSSValueTelugu;
    1946         break;
    1947     case ListStyleType::Thai:
    1948         m_value.valueID = CSSValueThai;
    1949         break;
    1950     case ListStyleType::Tibetan:
    1951         m_value.valueID = CSSValueTibetan;
    1952         break;
    1953     case ListStyleType::Tigre:
    1954         m_value.valueID = CSSValueTigre;
    1955         break;
    1956     case ListStyleType::TigrinyaEr:
    1957         m_value.valueID = CSSValueTigrinyaEr;
    1958         break;
    1959     case ListStyleType::TigrinyaErAbegede:
    1960         m_value.valueID = CSSValueTigrinyaErAbegede;
    1961         break;
    1962     case ListStyleType::TigrinyaEt:
    1963         m_value.valueID = CSSValueTigrinyaEt;
    1964         break;
    1965     case ListStyleType::TigrinyaEtAbegede:
    1966         m_value.valueID = CSSValueTigrinyaEtAbegede;
    1967         break;
    1968     case ListStyleType::UpperAlpha:
    1969         m_value.valueID = CSSValueUpperAlpha;
    1970         break;
    1971     case ListStyleType::UpperArmenian:
    1972         m_value.valueID = CSSValueUpperArmenian;
    1973         break;
    1974     case ListStyleType::UpperGreek:
    1975         m_value.valueID = CSSValueUpperGreek;
    1976         break;
    1977     case ListStyleType::UpperHexadecimal:
    1978         m_value.valueID = CSSValueUpperHexadecimal;
    1979         break;
    1980     case ListStyleType::UpperLatin:
    1981         m_value.valueID = CSSValueUpperLatin;
    1982         break;
    1983     case ListStyleType::UpperNorwegian:
    1984         m_value.valueID = CSSValueUpperNorwegian;
    1985         break;
    1986     case ListStyleType::UpperRoman:
    1987         m_value.valueID = CSSValueUpperRoman;
    1988         break;
    1989     case ListStyleType::Urdu:
    1990         m_value.valueID = CSSValueUrdu;
    1991         break;
    1992     }
     1741        return CSSValueInvalid;
     1742    default:
     1743        return static_cast<CSSValueID>(static_cast<int>(CSSValueDisc) + static_cast<uint8_t>(style));
     1744    }
     1745}
     1746
     1747template<> inline CSSPrimitiveValue::CSSPrimitiveValue(ListStyleType style)
     1748    : CSSValue(PrimitiveClass)
     1749{
     1750    setPrimitiveUnitType(CSSUnitType::CSS_VALUE_ID);
     1751    m_value.valueID = toCSSValueID(style);
    19931752}
    19941753
  • trunk/Source/WebCore/css/CSSValueKeywords.in

    r279055 r279165  
    447447cjk-decimal
    448448tamil
     449disclosure-open
     450disclosure-closed
     451japanese-informal
     452japanese-formal
     453korean-hangul-formal
     454korean-hanja-informal
     455korean-hanja-formal
     456simp-chinese-informal
     457simp-chinese-formal
     458trad-chinese-informal
     459trad-chinese-formal
     460ethiopic-numeric
    449461//none
    450462//
  • trunk/Source/WebCore/css/parser/CSSPropertyParserHelpers.cpp

    r279055 r279165  
    35343534bool isPredefinedCounterStyle(CSSValueID valueID)
    35353535{
    3536     return valueID >= CSSValueDisc && valueID <= CSSValueTamil;
     3536    return valueID >= CSSValueDisc && valueID <= CSSValueEthiopicNumeric;
    35373537}
    35383538
  • trunk/Source/WebCore/rendering/RenderListItem.cpp

    r278534 r279165  
    277277}
    278278
    279 const String& RenderListItem::markerText() const
    280 {
    281     if (m_marker)
    282         return m_marker->text();
    283     return nullAtom().string();
    284 }
    285 
    286 String RenderListItem::markerTextWithSuffix() const
     279StringView RenderListItem::markerTextWithoutSuffix() const
    287280{
    288281    if (!m_marker)
    289         return String();
    290 
    291     // Append the suffix for the marker in the right place depending
    292     // on the direction of the text (right-to-left or left-to-right).
    293     if (m_marker->style().isLeftToRightDirection())
    294         return m_marker->text() + m_marker->suffix();
    295     return m_marker->suffix() + m_marker->text();
     282        return { };
     283    return m_marker->textWithoutSuffix();
     284}
     285
     286StringView RenderListItem::markerTextWithSuffix() const
     287{
     288    if (!m_marker)
     289        return { };
     290    return m_marker->textWithSuffix();
    296291}
    297292
  • trunk/Source/WebCore/rendering/RenderListItem.h

    r278253 r279165  
    4747    bool notInList() const { return m_notInList; }
    4848
    49     WEBCORE_EXPORT const String& markerText() const;
    50     String markerTextWithSuffix() const;
     49    WEBCORE_EXPORT StringView markerTextWithoutSuffix() const;
     50    StringView markerTextWithSuffix() const;
    5151
    5252    void updateListMarkerNumbers();
     
    6363
    6464private:
    65 
    6665    const char* renderName() const final { return "RenderListItem"; }
    6766
  • trunk/Source/WebCore/rendering/RenderListMarker.cpp

    r279055 r279165  
    4242namespace WebCore {
    4343
    44 using namespace WTF::Unicode;
     44// As of June 2021, the Microsoft C++ compiler seems unable to include std::initializer_list in a constexpr.
     45#if COMPILER(MSVC)
     46#define CONSTEXPR_WITH_MSVC_INITIALIZER_LIST_WORKAROUND const
     47#else
     48#define CONSTEXPR_WITH_MSVC_INITIALIZER_LIST_WORKAROUND constexpr
     49#endif
    4550
    4651WTF_MAKE_ISO_ALLOCATED_IMPL(RenderListMarker);
     
    4853constexpr int cMarkerPadding = 7;
    4954
    50 enum class LetterCase { Lower, Upper };
    51 enum class SequenceType { Numeric, Alphabetic };
    52 
    53 static NEVER_INLINE String toRoman(int number, LetterCase letterCase)
    54 {
    55     // FIXME: CSS3 describes how to make this work for much larger numbers,
    56     // using overbars and special characters. It also specifies the characters
    57     // in the range U+2160 to U+217F instead of standard ASCII ones.
    58     ASSERT(number >= 1 && number <= 3999);
    59 
    60     // Big enough to store largest roman number less than 3999 which
    61     // is 3888 (MMMDCCCLXXXVIII)
    62     constexpr unsigned lettersSize = 15;
    63     LChar letters[lettersSize];
    64 
    65     unsigned length = 0;
    66     constexpr LChar ldigits[] = { 'i', 'v', 'x', 'l', 'c', 'd', 'm' };
    67     constexpr LChar udigits[] = { 'I', 'V', 'X', 'L', 'C', 'D', 'M' };
    68     const LChar* digits = letterCase == LetterCase::Upper ? udigits : ldigits;
    69     int d = 0;
    70     do {
    71         int num = number % 10;
    72         if (num % 5 < 4)
    73             for (int i = num % 5; i > 0; i--)
    74                 letters[lettersSize - ++length] = digits[d];
    75         if (num >= 4 && num <= 8)
    76             letters[lettersSize - ++length] = digits[d + 1];
    77         if (num == 9)
    78             letters[lettersSize - ++length] = digits[d + 2];
    79         if (num % 5 == 4)
    80             letters[lettersSize - ++length] = digits[d];
    81         number /= 10;
    82         d += 2;
    83     } while (number);
    84 
    85     ASSERT(length <= lettersSize);
    86     return { &letters[lettersSize - length], length };
    87 }
    88 
    89 template<typename CharacterType>
    90 static inline String toAlphabeticOrNumeric(int number, const CharacterType* sequence, unsigned sequenceSize, SequenceType type)
     55enum class SequenceType : bool { Numeric, Alphabetic };
     56enum class Formality : bool { Informal, Formal };
     57
     58template<SequenceType type, typename CharacterType> static String toAlphabeticOrNumeric(int number, const CharacterType* sequence, unsigned sequenceSize)
    9159{
    9260    ASSERT(sequenceSize >= 2);
     
    9967    bool isNegativeNumber = false;
    10068    unsigned numberShadow = number;
    101     if (type == SequenceType::Alphabetic) {
     69    if constexpr (type == SequenceType::Alphabetic) {
    10270        ASSERT(number > 0);
    10371        --numberShadow;
     
    10977    unsigned length = 1;
    11078
    111     if (type == SequenceType::Alphabetic) {
     79    if constexpr (type == SequenceType::Alphabetic) {
    11280        while ((numberShadow /= sequenceSize) > 0) {
    11381            --numberShadow;
     
    12593}
    12694
    127 template<typename CharacterType>
    128 static NEVER_INLINE String toSymbolic(int number, const CharacterType* symbols, unsigned symbolsSize)
     95template<typename CharacterType> static String toSymbolic(int number, const CharacterType* symbols, unsigned symbolsSize)
    12996{
    13097    ASSERT(number > 0);
     
    13299
    133100    // The asterisks list-style-type is the worst case; we show |number| asterisks.
    134     CharacterType symbol = symbols[(number - 1) % symbolsSize];
     101    auto symbol = symbols[(number - 1) % symbolsSize];
    135102    unsigned count = (number - 1) / symbolsSize + 1;
    136103
     
    142109}
    143110
    144 template<typename CharacterType>
    145 static NEVER_INLINE String toAlphabetic(int number, const CharacterType* alphabet, unsigned alphabetSize)
    146 {
    147     return toAlphabeticOrNumeric(number, alphabet, alphabetSize, SequenceType::Alphabetic);
    148 }
    149 
    150 template<typename CharacterType>
    151 static NEVER_INLINE String toNumeric(int number, const CharacterType* numerals, unsigned numeralsSize)
    152 {
    153     return toAlphabeticOrNumeric(number, numerals, numeralsSize, SequenceType::Numeric);
    154 }
    155 
    156 template<typename CharacterType, size_t size>
    157 static inline String toAlphabetic(int number, const CharacterType(&alphabet)[size])
     111template<typename CharacterType> static String toAlphabetic(int number, const CharacterType* alphabet, unsigned alphabetSize)
     112{
     113    return toAlphabeticOrNumeric<SequenceType::Alphabetic>(number, alphabet, alphabetSize);
     114}
     115
     116template<typename CharacterType> static String toNumeric(int number, const CharacterType* numerals, unsigned numeralsSize)
     117{
     118    return toAlphabeticOrNumeric<SequenceType::Numeric>(number, numerals, numeralsSize);
     119}
     120
     121template<typename CharacterType, size_t size> static String toAlphabetic(int number, const CharacterType(&alphabet)[size])
    158122{
    159123    return toAlphabetic(number, alphabet, size);
    160124}
    161125
    162 template<typename CharacterType, size_t size>
    163 static inline String toNumeric(int number, const CharacterType(&alphabet)[size])
     126template<typename CharacterType, size_t size> static String toNumeric(int number, const CharacterType(&alphabet)[size])
    164127{
    165128    return toNumeric(number, alphabet, size);
    166129}
    167130
    168 template<typename CharacterType, size_t size>
    169 static inline String toSymbolic(int number, const CharacterType(&alphabet)[size])
     131template<typename CharacterType, size_t size> static String toSymbolic(int number, const CharacterType(&alphabet)[size])
    170132{   
    171133    return toSymbolic(number, alphabet, size);
    172134}
    173135
    174 static NEVER_INLINE int toHebrewUnder1000(int number, UChar letters[5])
    175 {
    176     // FIXME: CSS3 mentions various refinements not implemented here.
    177     // FIXME: Should take a look at Mozilla's HebrewToText function (in nsBulletFrame).
    178     ASSERT(number >= 0 && number < 1000);
    179     int length = 0;
    180     int fourHundreds = number / 400;
    181     for (int i = 0; i < fourHundreds; i++)
    182         letters[length++] = 1511 + 3;
    183     number %= 400;
    184     if (number / 100)
    185         letters[length++] = 1511 + (number / 100) - 1;
    186     number %= 100;
    187     if (number == 15 || number == 16) {
    188         letters[length++] = 1487 + 9;
    189         letters[length++] = 1487 + number - 9;
    190     } else {
    191         if (int tens = number / 10) {
    192             static constexpr UChar hebrewTens[9] = { 1497, 1499, 1500, 1502, 1504, 1505, 1506, 1508, 1510 };
    193             letters[length++] = hebrewTens[tens - 1];
    194         }
    195         if (int ones = number % 10)
    196             letters[length++] = 1487 + ones;
    197     }
    198     ASSERT(length <= 5);
    199     return length;
    200 }
    201 
    202 static NEVER_INLINE String toHebrew(int number)
    203 {
    204     // FIXME: CSS3 mentions ways to make this work for much larger numbers.
    205     ASSERT(number >= 0 && number <= 999999);
    206 
    207     if (number == 0) {
    208         static constexpr UChar hebrewZero[3] = { 0x05D0, 0x05E4, 0x05E1 };
    209         return { hebrewZero, 3 };
    210     }
    211 
    212     constexpr unsigned lettersSize = 11; // big enough for two 5-digit sequences plus a quote mark between
    213     UChar letters[lettersSize];
    214 
    215     unsigned length;
    216     if (number < 1000)
    217         length = 0;
    218     else {
    219         length = toHebrewUnder1000(number / 1000, letters);
    220         letters[length++] = '\'';
    221         number = number % 1000;
    222     }
    223     length += toHebrewUnder1000(number, letters + length);
    224 
    225     ASSERT(length <= lettersSize);
    226     return { letters, length };
    227 }
    228 
    229 static NEVER_INLINE unsigned toArmenianUnder10000(int number, LetterCase letterCase, bool addCircumflex, UChar letters[9])
    230 {
    231     ASSERT(number >= 0 && number < 10000);
    232     unsigned length = 0;
    233 
    234     int lowerOffset = letterCase == LetterCase::Upper ? 0 : 0x0030;
    235 
    236     if (int thousands = number / 1000) {
    237         if (thousands == 7) {
    238             letters[length++] = 0x0552 + lowerOffset;
    239             if (addCircumflex)
    240                 letters[length++] = 0x0302;
    241         } else {
    242             letters[length++] = (0x054C - 1 + lowerOffset) + thousands;
    243             if (addCircumflex)
    244                 letters[length++] = 0x0302;
    245         }
    246     }
    247 
    248     if (int hundreds = (number / 100) % 10) {
    249         letters[length++] = (0x0543 - 1 + lowerOffset) + hundreds;
    250         if (addCircumflex)
    251             letters[length++] = 0x0302;
    252     }
    253 
    254     if (int tens = (number / 10) % 10) {
    255         letters[length++] = (0x053A - 1 + lowerOffset) + tens;
    256         if (addCircumflex)
    257             letters[length++] = 0x0302;
    258     }
    259 
    260     if (int ones = number % 10) {
    261         letters[length++] = (0x531 - 1 + lowerOffset) + ones;
    262         if (addCircumflex)
    263             letters[length++] = 0x0302;
    264     }
    265 
    266     return length;
    267 }
    268 
    269 static NEVER_INLINE String toArmenian(int number, LetterCase letterCase)
    270 {
    271     ASSERT(number >= 1 && number <= 99999999);
    272 
    273     constexpr unsigned lettersSize = 18; // twice what toArmenianUnder10000 needs
    274     UChar letters[lettersSize];
    275 
    276     unsigned length = toArmenianUnder10000(number / 10000, letterCase, true, letters);
    277     length += toArmenianUnder10000(number % 10000, letterCase, false, letters + length);
    278 
    279     ASSERT(length <= lettersSize);
    280     return { letters, length };
    281 }
    282 
    283 static NEVER_INLINE String toGeorgian(int number)
    284 {
    285     ASSERT(number >= 1 && number <= 19999);
    286 
    287     constexpr unsigned lettersSize = 5;
    288     UChar letters[lettersSize];
    289 
    290     unsigned length = 0;
    291 
    292     if (number > 9999)
    293         letters[length++] = 0x10F5;
    294 
    295     if (int thousands = (number / 1000) % 10) {
    296         static constexpr UChar georgianThousands[9] = {
    297             0x10E9, 0x10EA, 0x10EB, 0x10EC, 0x10ED, 0x10EE, 0x10F4, 0x10EF, 0x10F0
    298         };
    299         letters[length++] = georgianThousands[thousands - 1];
    300     }
    301 
    302     if (int hundreds = (number / 100) % 10) {
    303         static constexpr UChar georgianHundreds[9] = {
    304             0x10E0, 0x10E1, 0x10E2, 0x10F3, 0x10E4, 0x10E5, 0x10E6, 0x10E7, 0x10E8
    305         };
    306         letters[length++] = georgianHundreds[hundreds - 1];
    307     }
    308 
    309     if (int tens = (number / 10) % 10) {
    310         static constexpr UChar georgianTens[9] = {
    311             0x10D8, 0x10D9, 0x10DA, 0x10DB, 0x10DC, 0x10F2, 0x10DD, 0x10DE, 0x10DF
    312         };
    313         letters[length++] = georgianTens[tens - 1];
    314     }
    315 
    316     if (int ones = number % 10) {
    317         static constexpr UChar georgianOnes[9] = {
    318             0x10D0, 0x10D1, 0x10D2, 0x10D3, 0x10D4, 0x10D5, 0x10D6, 0x10F1, 0x10D7
    319         };
    320         letters[length++] = georgianOnes[ones - 1];
    321     }
    322 
    323     ASSERT(length <= lettersSize);
    324     return { letters, length };
    325 }
    326 
    327 // The table uses the order from the CSS3 specification:
    328 // first 3 group markers, then 3 digit markers, then ten digits.
    329 static NEVER_INLINE String toCJKIdeographic(int number, const UChar table[16])
    330 {
    331     ASSERT(number >= 0);
    332 
    333     enum AbstractCJKChar {
    334         noChar,
    335         secondGroupMarker, thirdGroupMarker, fourthGroupMarker,
    336         secondDigitMarker, thirdDigitMarker, fourthDigitMarker,
    337         digit0, digit1, digit2, digit3, digit4,
    338         digit5, digit6, digit7, digit8, digit9
     136// This table format was derived from an old draft of the CSS specification: 3 group markers, 3 digit markers, 10 digits, negative sign.
     137static String toCJKIdeographic(int number, const UChar table[17], Formality formality)
     138{
     139    enum AbstractCJKCharacter {
     140        NoChar,
     141        SecondGroupMarker, ThirdGroupMarker, FourthGroupMarker,
     142        SecondDigitMarker, ThirdDigitMarker, FourthDigitMarker,
     143        Digit0, Digit1, Digit2, Digit3, Digit4,
     144        Digit5, Digit6, Digit7, Digit8, Digit9,
     145        NegativeSign
    339146    };
    340147
    341148    if (!number)
    342         return { &table[digit0 - 1] , 1 };
     149        return { &table[Digit0 - 1] , 1 };
     150
     151    ASSERT(number != std::numeric_limits<int>::min());
     152    bool needsNegativeSign = number < 0;
     153    if (needsNegativeSign)
     154        number = -number;
    343155
    344156    constexpr unsigned groupLength = 8; // 4 digits, 3 digit markers, and a group marker
    345157    constexpr unsigned bufferLength = 4 * groupLength;
    346     AbstractCJKChar buffer[bufferLength] = { noChar };
     158    AbstractCJKCharacter buffer[bufferLength] = { NoChar };
    347159
    348160    for (int i = 0; i < 4; ++i) {
     
    351163
    352164        // Process least-significant group first, but put it in the buffer last.
    353         AbstractCJKChar* group = &buffer[(3 - i) * groupLength];
     165        auto group = &buffer[(3 - i) * groupLength];
    354166
    355167        if (groupValue && i)
    356             group[7] = static_cast<AbstractCJKChar>(secondGroupMarker - 1 + i);
     168            group[7] = static_cast<AbstractCJKCharacter>(SecondGroupMarker - 1 + i);
    357169
    358170        // Put in the four digits and digit markers for any non-zero digits.
    359         group[6] = static_cast<AbstractCJKChar>(digit0 + (groupValue % 10));
     171        group[6] = static_cast<AbstractCJKCharacter>(Digit0 + (groupValue % 10));
    360172        if (number != 0 || groupValue > 9) {
    361173            int digitValue = ((groupValue / 10) % 10);
    362             group[4] = static_cast<AbstractCJKChar>(digit0 + digitValue);
     174            group[4] = static_cast<AbstractCJKCharacter>(Digit0 + digitValue);
    363175            if (digitValue)
    364                 group[5] = secondDigitMarker;
     176                group[5] = SecondDigitMarker;
    365177        }
    366178        if (number != 0 || groupValue > 99) {
    367179            int digitValue = ((groupValue / 100) % 10);
    368             group[2] = static_cast<AbstractCJKChar>(digit0 + digitValue);
     180            group[2] = static_cast<AbstractCJKCharacter>(Digit0 + digitValue);
    369181            if (digitValue)
    370                 group[3] = thirdDigitMarker;
     182                group[3] = ThirdDigitMarker;
    371183        }
    372184        if (number != 0 || groupValue > 999) {
    373185            int digitValue = groupValue / 1000;
    374             group[0] = static_cast<AbstractCJKChar>(digit0 + digitValue);
     186            group[0] = static_cast<AbstractCJKCharacter>(Digit0 + digitValue);
    375187            if (digitValue)
    376                 group[1] = fourthDigitMarker;
     188                group[1] = FourthDigitMarker;
    377189        }
    378190
    379         // Remove the tens digit, but leave the marker, for any group that has
    380         // a value of less than 20.
    381         if (groupValue < 20) {
    382             ASSERT(group[4] == noChar || group[4] == digit0 || group[4] == digit1);
    383             group[4] = noChar;
     191        if (formality == Formality::Informal && groupValue < 20) {
     192            // Remove the tens digit, but leave the marker.
     193            ASSERT(group[4] == NoChar || group[4] == Digit0 || group[4] == Digit1);
     194            group[4] = NoChar;
    384195        }
    385196
     
    390201    // Convert into characters, omitting consecutive runs of digit0 and trailing digit0.
    391202    unsigned length = 0;
    392     UChar characters[bufferLength];
    393     AbstractCJKChar last = noChar;
     203    UChar characters[1 + bufferLength];
     204    auto last = NoChar;
     205    if (needsNegativeSign)
     206        characters[length++] = table[NegativeSign - 1];
    394207    for (unsigned i = 0; i < bufferLength; ++i) {
    395         AbstractCJKChar a = buffer[i];
    396         if (a != noChar) {
    397             if (a != digit0 || last != digit0)
    398                 characters[length++] = table[a - 1];
    399             last = a;
     208        auto character = buffer[i];
     209        if (character != NoChar) {
     210            if (character != Digit0 || last != Digit0)
     211                characters[length++] = table[character - 1];
     212            last = character;
    400213        }
    401214    }
    402     if (last == digit0)
     215    if (last == Digit0)
    403216        --length;
    404217
     
    406219}
    407220
     221struct AdditiveSymbol {
     222    int value;
     223    std::initializer_list<UChar> characters;
     224};
     225struct AdditiveSystem {
     226    std::initializer_list<AdditiveSymbol> symbols;
     227    std::initializer_list<UChar> negative;
     228};
     229
     230static String toPredefinedAdditiveSystem(int value, const AdditiveSystem& system)
     231{
     232    if (!value) {
     233        ASSERT(!system.symbols.end()[-1].value);
     234        auto& zeroCharacters = system.symbols.end()[-1].characters;
     235        return { zeroCharacters.begin(), static_cast<unsigned>(zeroCharacters.size()) };
     236    }
     237
     238    StringBuilder result;
     239    auto append = [&] (std::initializer_list<UChar> characters) {
     240        result.append(StringView { characters.begin(), static_cast<unsigned>(characters.size()) });
     241    };
     242    if (value < 0) {
     243        ASSERT(value != std::numeric_limits<int>::min());
     244        append(system.negative);
     245        value = -value;
     246    }
     247    for (auto& symbol : system.symbols) {
     248        while (value >= symbol.value) {
     249            append(symbol.characters);
     250            value -= symbol.value;
     251        }
     252        if (!value)
     253            break;
     254    }
     255    ASSERT(!value);
     256    return result.toString();
     257}
     258
     259static String toEthiopicNumeric(int value)
     260{
     261    ASSERT(value >= 1);
     262
     263    if (value == 1) {
     264        UChar ethiopicDigitOne = 0x1369;
     265        return { &ethiopicDigitOne, 1 };
     266    }
     267
     268    // Split the number into groups of two digits, starting with the least significant decimal digit.
     269    uint8_t groups[5];
     270    for (auto& group : groups) {
     271        group = value % 100;
     272        value /= 100;
     273    }
     274
     275    UChar buffer[std::size(groups) * 3];
     276    unsigned length = 0;
     277    bool isMostSignificantGroup = true;
     278    for (int i = std::size(groups) - 1; i >= 0; --i) {
     279        auto value = groups[i];
     280        bool isOddIndex = i & 1;
     281        // If the group has the value zero, or if the group is the most significant one and has the value 1,
     282        // or if the group has an odd index (as given in the previous step) and has the value 1,
     283        // then remove the digits (but leave the group, so it still has a separator appended below).
     284        if (!(value == 1 && (isMostSignificantGroup || isOddIndex))) {
     285            if (auto tens = value / 10)
     286                buffer[length++] = 0x1371 + tens;
     287            if (auto ones = value % 10)
     288                buffer[length++] = 0x1368 + ones;
     289        }
     290        if (value && isOddIndex)
     291            buffer[length++] = 0x137B;
     292        if ((value || !isMostSignificantGroup) && !isOddIndex && i)
     293            buffer[length++] = 0x137C;
     294        if (value)
     295            isMostSignificantGroup = false;
     296    }
     297
     298    return { buffer, length };
     299}
     300
    408301static ListStyleType effectiveListMarkerType(ListStyleType type, int value)
    409302{
    410     // FIXME: Types we need to add: japanese-formal, japanese-informal, korean-hangul-formal, korean-hanja-formal, korean-hanja-informal, simp-chinese-formal, simp-chinese-informal, tammil, trad-chinese-formal, trad-chinese-informal
    411 
    412303    // Note, the following switch statement has been explicitly grouped by list-style-type ordinal range.
    413304    switch (type) {
     
    421312    case ListStyleType::Devanagari:
    422313    case ListStyleType::Disc:
     314    case ListStyleType::DisclosureClosed:
     315    case ListStyleType::DisclosureOpen:
    423316    case ListStyleType::Gujarati:
    424317    case ListStyleType::Gurmukhi:
     
    442335    case ListStyleType::Urdu:
    443336        return type; // Can represent all ordinals.
    444     case ListStyleType::Armenian:
    445     case ListStyleType::LowerArmenian:
    446     case ListStyleType::UpperArmenian:
    447         return (value < 1 || value > 9999) ? ListStyleType::Decimal : type;
    448     case ListStyleType::CJKDecimal:
    449     case ListStyleType::CJKIdeographic:
    450         return (value < 0) ? ListStyleType::Decimal : type;
    451     case ListStyleType::Georgian:
    452         return (value < 1 || value > 19999) ? ListStyleType::Decimal : type;
    453     case ListStyleType::Hebrew:
    454         return (value < 0 || value > 999999) ? ListStyleType::Decimal : type;
    455     case ListStyleType::LowerRoman:
    456     case ListStyleType::UpperRoman:
    457         return (value < 1 || value > 3999) ? ListStyleType::Decimal : type;
    458337    case ListStyleType::Afar:
    459338    case ListStyleType::Amharic:
     
    478357    case ListStyleType::EthiopicHalehameTiEt:
    479358    case ListStyleType::EthiopicHalehameTig:
     359    case ListStyleType::EthiopicNumeric:
    480360    case ListStyleType::Footnotes:
    481361    case ListStyleType::Hangul:
     
    502382    case ListStyleType::UpperNorwegian:
    503383        return (value < 1) ? ListStyleType::Decimal : type;
     384    case ListStyleType::Armenian:
     385    case ListStyleType::LowerArmenian:
     386    case ListStyleType::UpperArmenian:
     387        return (value < 1 || value > 9999) ? ListStyleType::Decimal : type;
     388    case ListStyleType::CJKDecimal:
     389        return (value < 0) ? ListStyleType::Decimal : type;
     390    case ListStyleType::CJKIdeographic:
     391    case ListStyleType::JapaneseFormal:
     392    case ListStyleType::JapaneseInformal:
     393    case ListStyleType::SimplifiedChineseFormal:
     394    case ListStyleType::SimplifiedChineseInformal:
     395    case ListStyleType::TraditionalChineseFormal:
     396    case ListStyleType::TraditionalChineseInformal:
     397        return value < -9999 ? ListStyleType::Decimal : value > 9999 ? ListStyleType::CJKDecimal : type;
     398    case ListStyleType::Georgian:
     399        return (value < 1 || value > 19999) ? ListStyleType::Decimal : type;
     400    case ListStyleType::Hebrew:
     401        return (value < 1 || value > 10999) ? ListStyleType::Decimal : type;
     402    case ListStyleType::KoreanHangulFormal:
     403    case ListStyleType::KoreanHanjaInformal:
     404    case ListStyleType::KoreanHanjaFormal:
     405        return (value < -9999 || value > 9999) ? ListStyleType::Decimal : type;
     406    case ListStyleType::LowerRoman:
     407    case ListStyleType::UpperRoman:
     408        return (value < 1 || value > 3999) ? ListStyleType::Decimal : type;
    504409    case ListStyleType::String:
    505410        ASSERT_NOT_REACHED();
     
    511416}
    512417
    513 static UChar listMarkerSuffix(ListStyleType type, int value)
    514 {
    515     // Note, the following switch statement has been explicitly grouped by list-style-type suffix.
    516     switch (effectiveListMarkerType(type, value)) {
     418static StringView listMarkerSuffix(ListStyleType type)
     419{
     420    switch (type) {
    517421    case ListStyleType::Asterisks:
    518422    case ListStyleType::Circle:
    519423    case ListStyleType::Disc:
     424    case ListStyleType::DisclosureClosed:
     425    case ListStyleType::DisclosureOpen:
    520426    case ListStyleType::Footnotes:
    521427    case ListStyleType::None:
    522428    case ListStyleType::Square:
    523         return ' ';
     429        return { &space, 1 };
    524430    case ListStyleType::Afar:
    525431    case ListStyleType::Amharic:
     
    548454    case ListStyleType::TigrinyaErAbegede:
    549455    case ListStyleType::TigrinyaEt:
    550     case ListStyleType::TigrinyaEtAbegede:
    551         return ethiopicPrefaceColon;
     456    case ListStyleType::TigrinyaEtAbegede: {
     457        static constexpr UChar ethiopicPrefaceColonAndSpace[2] = { ethiopicPrefaceColon, ' ' };
     458        return { ethiopicPrefaceColonAndSpace, 2 };
     459    }
    552460    case ListStyleType::Armenian:
    553461    case ListStyleType::ArabicIndic:
     
    555463    case ListStyleType::Binary:
    556464    case ListStyleType::Cambodian:
    557     case ListStyleType::CJKIdeographic:
    558465    case ListStyleType::DecimalLeadingZero:
    559466    case ListStyleType::Decimal:
     
    593500    case ListStyleType::UpperRoman:
    594501    case ListStyleType::Urdu:
    595         return '.';
     502        return ". ";
    596503    case ListStyleType::CJKDecimal:
    597504    case ListStyleType::CJKEarthlyBranch:
    598505    case ListStyleType::CJKHeavenlyStem:
     506    case ListStyleType::CJKIdeographic:
    599507    case ListStyleType::Hiragana:
    600508    case ListStyleType::HiraganaIroha:
     509    case ListStyleType::JapaneseFormal:
     510    case ListStyleType::JapaneseInformal:
    601511    case ListStyleType::Katakana:
    602512    case ListStyleType::KatakanaIroha:
    603         return ideographicComma;
     513    case ListStyleType::SimplifiedChineseFormal:
     514    case ListStyleType::SimplifiedChineseInformal:
     515    case ListStyleType::TraditionalChineseFormal:
     516    case ListStyleType::TraditionalChineseInformal:
     517        return { &ideographicComma, 1 };
     518    case ListStyleType::EthiopicNumeric:
     519        return "/ ";
     520    case ListStyleType::KoreanHangulFormal:
     521    case ListStyleType::KoreanHanjaInformal:
     522    case ListStyleType::KoreanHanjaFormal:
     523        return ", ";
    604524    case ListStyleType::String:
    605525        ASSERT_NOT_REACHED();
     
    608528
    609529    ASSERT_NOT_REACHED();
    610     return '.';
    611 }
    612 
    613 static bool suffixRequiresSpace(UChar suffix)
    614 {
    615     return suffix == '.' || suffix == ethiopicPrefaceColon;
     530    return ". ";
    616531}
    617532
     
    626541        return toSymbolic(value, asterisksSymbols);
    627542    }
    628     // We use the same characters for text security.
    629     // See RenderText::setInternalString.
     543
     544    // We use the same characters for text security. See RenderText::setRenderedText.
    630545    case ListStyleType::Circle:
    631546        return { &whiteBullet, 1 };
     
    636551        return toSymbolic(value, footnotesSymbols);
    637552    }
     553
     554    // CSS specification calls for U+25FE BLACK MEDIUM SMALL SQUARE; we have been using U+25A0 BLACK SQUARE instead for a long time.
    638555    case ListStyleType::Square:
    639         // The CSS 2.1 test suite uses U+25EE BLACK MEDIUM SMALL SQUARE instead,
    640         // but we used this because we thought it looked better.
    641556        return { &blackSquare, 1 };
     557
     558    case ListStyleType::DisclosureClosed:
     559        return { &blackRightPointingSmallTriangle, 1 };
     560    case ListStyleType::DisclosureOpen:
     561        return { &blackDownPointingSmallTriangle, 1 };
    642562
    643563    case ListStyleType::Decimal:
     
    1026946        return toAlphabetic(value, upperNorwegianAlphabet);
    1027947    }
    1028     case ListStyleType::CJKIdeographic: {
    1029         static constexpr UChar traditionalChineseInformalTable[16] = {
     948
     949    case ListStyleType::SimplifiedChineseInformal: {
     950        static constexpr UChar simplifiedChineseInformalTable[17] = {
     951            0x842C, 0x5104, 0x5146, // These three group markers are probably wrong; OK because we don't use this on big enough numbers.
     952            0x5341, 0x767E, 0x5343,
     953            0x96F6, 0x4E00, 0x4E8C, 0x4E09, 0x56DB,
     954            0x4E94, 0x516D, 0x4E03, 0x516B, 0x4E5D,
     955            0x8D1F
     956        };
     957        return toCJKIdeographic(value, simplifiedChineseInformalTable, Formality::Informal);
     958    }
     959    case ListStyleType::SimplifiedChineseFormal: {
     960        static constexpr UChar simplifiedChineseFormalTable[17] = {
     961            0x842C, 0x5104, 0x5146, // These three group markers are probably wrong; OK because we don't use this on big enough numbers.
     962            0x62FE, 0x4F70, 0x4EDF,
     963            0x96F6, 0x58F9, 0x8D30, 0x53C1, 0x8086,
     964            0x4F0D, 0x9646, 0x67D2, 0x634C, 0x7396,
     965            0x8D1F
     966        };
     967        return toCJKIdeographic(value, simplifiedChineseFormalTable, Formality::Formal);
     968    }
     969    case ListStyleType::CJKIdeographic:
     970    case ListStyleType::TraditionalChineseInformal: {
     971        static constexpr UChar traditionalChineseInformalTable[17] = {
    1030972            0x842C, 0x5104, 0x5146,
    1031973            0x5341, 0x767E, 0x5343,
    1032974            0x96F6, 0x4E00, 0x4E8C, 0x4E09, 0x56DB,
    1033             0x4E94, 0x516D, 0x4E03, 0x516B, 0x4E5D
    1034         };
    1035         return toCJKIdeographic(value, traditionalChineseInformalTable);
    1036     }
    1037 
    1038     case ListStyleType::LowerRoman:
    1039         return toRoman(value, LetterCase::Lower);
    1040     case ListStyleType::UpperRoman:
    1041         return toRoman(value, LetterCase::Upper);
     975            0x4E94, 0x516D, 0x4E03, 0x516B, 0x4E5D,
     976            0x8CA0
     977        };
     978        return toCJKIdeographic(value, traditionalChineseInformalTable, Formality::Informal);
     979    }
     980    case ListStyleType::TraditionalChineseFormal: {
     981        static constexpr UChar traditionalChineseFormalTable[17] = {
     982            0x842C, 0x5104, 0x5146, // These three group markers are probably wrong; OK because we don't use this on big enough numbers.
     983            0x62FE, 0x4F70, 0x4EDF,
     984            0x96F6, 0x58F9, 0x8CB3, 0x53C3, 0x8086,
     985            0x4F0D, 0x9678, 0x67D2, 0x634C, 0x7396,
     986            0x8CA0
     987        };
     988        return toCJKIdeographic(value, traditionalChineseFormalTable, Formality::Formal);
     989    }
     990
     991    case ListStyleType::LowerRoman: {
     992        static CONSTEXPR_WITH_MSVC_INITIALIZER_LIST_WORKAROUND AdditiveSystem lowerRomanSystem {
     993            {
     994                { 1000, { 'm' } },
     995                { 900, { 'c', 'm' } },
     996                { 500, { 'd' } },
     997                { 400, { 'c', 'd' } },
     998                { 100, { 'c' } },
     999                { 90, { 'x', 'c' } },
     1000                { 50, { 'l' } },
     1001                { 40, { 'x', 'l' } },
     1002                { 10, { 'x' } },
     1003                { 9, { 'i', 'x' } },
     1004                { 5, { 'v' } },
     1005                { 4, { 'i', 'v' } },
     1006                { 1, { 'i' } }
     1007            },
     1008            { }
     1009        };
     1010        return toPredefinedAdditiveSystem(value, lowerRomanSystem);
     1011    }
     1012    case ListStyleType::UpperRoman: {
     1013        static CONSTEXPR_WITH_MSVC_INITIALIZER_LIST_WORKAROUND AdditiveSystem upperRomanSystem {
     1014            {
     1015                { 1000, { 'M' } },
     1016                { 900, { 'C', 'M' } },
     1017                { 500, { 'D' } },
     1018                { 400, { 'C', 'D' } },
     1019                { 100, { 'C' } },
     1020                { 90, { 'X', 'C' } },
     1021                { 50, { 'L' } },
     1022                { 40, { 'X', 'L' } },
     1023                { 10, { 'X' } },
     1024                { 9, { 'I', 'X' } },
     1025                { 5, { 'V' } },
     1026                { 4, { 'I', 'V' } },
     1027                { 1, { 'I' } }
     1028            },
     1029            { }
     1030        };
     1031        return toPredefinedAdditiveSystem(value, upperRomanSystem);
     1032    }
    10421033
    10431034    case ListStyleType::Armenian:
    1044     case ListStyleType::UpperArmenian:
    1045         return toArmenian(value, LetterCase::Upper);
    1046     case ListStyleType::LowerArmenian:
    1047         return toArmenian(value, LetterCase::Lower);
    1048 
    1049     case ListStyleType::Georgian:
    1050         return toGeorgian(value);
    1051     case ListStyleType::Hebrew:
    1052         return toHebrew(value);
     1035    case ListStyleType::UpperArmenian: {
     1036        static CONSTEXPR_WITH_MSVC_INITIALIZER_LIST_WORKAROUND AdditiveSystem upperArmenianSystem {
     1037            {
     1038                { 9000, { 0x554 } },
     1039                { 8000, { 0x553 } },
     1040                { 7000, { 0x552 } },
     1041                { 6000, { 0x551 } },
     1042                { 5000, { 0x550 } },
     1043                { 4000, { 0x54F } },
     1044                { 3000, { 0x54E } },
     1045                { 2000, { 0x54D } },
     1046                { 1000, { 0x54C } },
     1047                { 900, { 0x54B } },
     1048                { 800, { 0x54A } },
     1049                { 700, { 0x549 } },
     1050                { 600, { 0x548 } },
     1051                { 500, { 0x547 } },
     1052                { 400, { 0x546 } },
     1053                { 300, { 0x545 } },
     1054                { 200, { 0x544 } },
     1055                { 100, { 0x543 } },
     1056                { 90, { 0x542 } },
     1057                { 80, { 0x541 } },
     1058                { 70, { 0x540 } },
     1059                { 60, { 0x53F } },
     1060                { 50, { 0x53E } },
     1061                { 40, { 0x53D } },
     1062                { 30, { 0x53C } },
     1063                { 20, { 0x53B } },
     1064                { 10, { 0x53A } },
     1065                { 9, { 0x539 } },
     1066                { 8, { 0x538 } },
     1067                { 7, { 0x537 } },
     1068                { 6, { 0x536 } },
     1069                { 5, { 0x535 } },
     1070                { 4, { 0x534 } },
     1071                { 3, { 0x533 } },
     1072                { 2, { 0x532 } },
     1073                { 1, { 0x531 } }
     1074            },
     1075            { }
     1076        };
     1077        return toPredefinedAdditiveSystem(value, upperArmenianSystem);
     1078    }
     1079    case ListStyleType::LowerArmenian: {
     1080        static CONSTEXPR_WITH_MSVC_INITIALIZER_LIST_WORKAROUND AdditiveSystem lowerArmenianSystem {
     1081            {
     1082                { 9000, { 0x584 } },
     1083                { 8000, { 0x583 } },
     1084                { 7000, { 0x582 } },
     1085                { 6000, { 0x581 } },
     1086                { 5000, { 0x580 } },
     1087                { 4000, { 0x57F } },
     1088                { 3000, { 0x57E } },
     1089                { 2000, { 0x57D } },
     1090                { 1000, { 0x57C } },
     1091                { 900, { 0x57B } },
     1092                { 800, { 0x57A } },
     1093                { 700, { 0x579 } },
     1094                { 600, { 0x578 } },
     1095                { 500, { 0x577 } },
     1096                { 400, { 0x576 } },
     1097                { 300, { 0x575 } },
     1098                { 200, { 0x574 } },
     1099                { 100, { 0x573 } },
     1100                { 90, { 0x572 } },
     1101                { 80, { 0x571 } },
     1102                { 70, { 0x570 } },
     1103                { 60, { 0x56F } },
     1104                { 50, { 0x56E } },
     1105                { 40, { 0x56D } },
     1106                { 30, { 0x56C } },
     1107                { 20, { 0x56B } },
     1108                { 10, { 0x56A } },
     1109                { 9, { 0x569 } },
     1110                { 8, { 0x568 } },
     1111                { 7, { 0x567 } },
     1112                { 6, { 0x566 } },
     1113                { 5, { 0x565 } },
     1114                { 4, { 0x564 } },
     1115                { 3, { 0x563 } },
     1116                { 2, { 0x562 } },
     1117                { 1, { 0x561 } }
     1118            },
     1119            { }
     1120        };
     1121        return toPredefinedAdditiveSystem(value, lowerArmenianSystem);
     1122    }
     1123
     1124    case ListStyleType::Georgian: {
     1125        static CONSTEXPR_WITH_MSVC_INITIALIZER_LIST_WORKAROUND AdditiveSystem georgianSystem {
     1126            {
     1127                { 10000, { 0x10F5 } },
     1128                { 9000, { 0x10F0 } },
     1129                { 8000, { 0x10EF } },
     1130                { 7000, { 0x10F4 } },
     1131                { 6000, { 0x10EE } },
     1132                { 5000, { 0x10ED } },
     1133                { 4000, { 0x10EC } },
     1134                { 3000, { 0x10EB } },
     1135                { 2000, { 0x10EA } },
     1136                { 1000, { 0x10E9 } },
     1137                { 900, { 0x10E8 } },
     1138                { 800, { 0x10E7 } },
     1139                { 700, { 0x10E6 } },
     1140                { 600, { 0x10E5 } },
     1141                { 500, { 0x10E4 } },
     1142                { 400, { 0x10F3 } },
     1143                { 300, { 0x10E2 } },
     1144                { 200, { 0x10E1 } },
     1145                { 100, { 0x10E0 } },
     1146                { 90, { 0x10DF } },
     1147                { 80, { 0x10DE } },
     1148                { 70, { 0x10DD } },
     1149                { 60, { 0x10F2 } },
     1150                { 50, { 0x10DC } },
     1151                { 40, { 0x10DB } },
     1152                { 30, { 0x10DA } },
     1153                { 20, { 0x10D9 } },
     1154                { 10, { 0x10D8 } },
     1155                { 9, { 0x10D7 } },
     1156                { 8, { 0x10F1 } },
     1157                { 7, { 0x10D6 } },
     1158                { 6, { 0x10D5 } },
     1159                { 5, { 0x10D4 } },
     1160                { 4, { 0x10D3 } },
     1161                { 3, { 0x10D2 } },
     1162                { 2, { 0x10D1 } },
     1163                { 1, { 0x10D0 } }
     1164            },
     1165            { }
     1166        };
     1167        return toPredefinedAdditiveSystem(value, georgianSystem);
     1168    }
     1169    case ListStyleType::Hebrew: {
     1170        static CONSTEXPR_WITH_MSVC_INITIALIZER_LIST_WORKAROUND AdditiveSystem hebrewSystem {
     1171            {
     1172                { 10000, { 0x5D9, 0x5F3 } },
     1173                { 9000, { 0x5D8, 0x5F3 } },
     1174                { 8000, { 0x5D7, 0x5F3 } },
     1175                { 7000, { 0x5D6, 0x5F3 } },
     1176                { 6000, { 0x5D5, 0x5F3 } },
     1177                { 5000, { 0x5D4, 0x5F3 } },
     1178                { 4000, { 0x5D3, 0x5F3 } },
     1179                { 3000, { 0x5D2, 0x5F3 } },
     1180                { 2000, { 0x5D1, 0x5F3 } },
     1181                { 1000, { 0x5D0, 0x5F3 } },
     1182                { 400, { 0x5EA } },
     1183                { 300, { 0x5E9 } },
     1184                { 200, { 0x5E8 } },
     1185                { 100, { 0x5E7 } },
     1186                { 90, { 0x5E6 } },
     1187                { 80, { 0x5E4 } },
     1188                { 70, { 0x5E2 } },
     1189                { 60, { 0x5E1 } },
     1190                { 50, { 0x5E0 } },
     1191                { 40, { 0x5DE } },
     1192                { 30, { 0x5DC } },
     1193                { 20, { 0x5DB } },
     1194                { 19, { 0x5D9, 0x5D8 } },
     1195                { 18, { 0x5D9, 0x5D7 } },
     1196                { 17, { 0x5D9, 0x5D6 } },
     1197                { 16, { 0x5D8, 0x5D6 } },
     1198                { 15, { 0x5D8, 0x5D5 } },
     1199                { 10, { 0x5D9 } },
     1200                { 9, { 0x5D8 } },
     1201                { 8, { 0x5D7 } },
     1202                { 7, { 0x5D6 } },
     1203                { 6, { 0x5D5 } },
     1204                { 5, { 0x5D4 } },
     1205                { 4, { 0x5D3 } },
     1206                { 3, { 0x5D2 } },
     1207                { 2, { 0x5D1 } },
     1208                { 1, { 0x5D0 } }
     1209            },
     1210            { }
     1211        };
     1212        return toPredefinedAdditiveSystem(value, hebrewSystem);
     1213    }
    10531214
    10541215    case ListStyleType::CJKDecimal: {
     
    10641225        return toNumeric(value, tamilNumerals);
    10651226    }
     1227
     1228    case ListStyleType::JapaneseInformal: {
     1229        static CONSTEXPR_WITH_MSVC_INITIALIZER_LIST_WORKAROUND AdditiveSystem japaneseInformalSystem {
     1230            {
     1231                { 9000, { 0x4E5D, 0x5343 } },
     1232                { 8000, { 0x516B, 0x5343 } },
     1233                { 7000, { 0x4E03, 0x5343 } },
     1234                { 6000, { 0x516D, 0x5343 } },
     1235                { 5000, { 0x4E94, 0x5343 } },
     1236                { 4000, { 0x56DB, 0x5343 } },
     1237                { 3000, { 0x4E09, 0x5343 } },
     1238                { 2000, { 0x4E8C, 0x5343 } },
     1239                { 1000, { 0x5343 } },
     1240                { 900, { 0x4E5D, 0x767E } },
     1241                { 800, { 0x516B, 0x767E } },
     1242                { 700, { 0x4E03, 0x767E } },
     1243                { 600, { 0x516D, 0x767E } },
     1244                { 500, { 0x4E94, 0x767E } },
     1245                { 400, { 0x56DB, 0x767E } },
     1246                { 300, { 0x4E09, 0x767E } },
     1247                { 200, { 0x4E8C, 0x767E } },
     1248                { 100, { 0x767E } },
     1249                { 90, { 0x4E5D, 0x5341 } },
     1250                { 80, { 0x516B, 0x5341 } },
     1251                { 70, { 0x4E03, 0x5341 } },
     1252                { 60, { 0x516D, 0x5341 } },
     1253                { 50, { 0x4E94, 0x5341 } },
     1254                { 40, { 0x56DB, 0x5341 } },
     1255                { 30, { 0x4E09, 0x5341 } },
     1256                { 20, { 0x4E8C, 0x5341 } },
     1257                { 10, { 0x5341 } },
     1258                { 9, { 0x4E5D } },
     1259                { 8, { 0x516B } },
     1260                { 7, { 0x4E03 } },
     1261                { 6, { 0x516D } },
     1262                { 5, { 0x4E94 } },
     1263                { 4, { 0x56DB } },
     1264                { 3, { 0x4E09 } },
     1265                { 2, { 0x4E8C } },
     1266                { 1, { 0x4E00 } },
     1267                { 0, { 0x3007 } }
     1268            },
     1269            { 0x30DE, 0x30A4, 0x30CA, 0x30B9 }
     1270        };
     1271        return toPredefinedAdditiveSystem(value, japaneseInformalSystem);
     1272    }
     1273    case ListStyleType::JapaneseFormal: {
     1274        static CONSTEXPR_WITH_MSVC_INITIALIZER_LIST_WORKAROUND AdditiveSystem japaneseFormalSystem {
     1275            {
     1276                { 9000, { 0x4E5D, 0x9621 } },
     1277                { 8000, { 0x516B, 0x9621 } },
     1278                { 7000, { 0x4E03, 0x9621 } },
     1279                { 6000, { 0x516D, 0x9621 } },
     1280                { 5000, { 0x4F0D, 0x9621 } },
     1281                { 4000, { 0x56DB, 0x9621 } },
     1282                { 3000, { 0x53C2, 0x9621 } },
     1283                { 2000, { 0x5F10, 0x9621 } },
     1284                { 1000, { 0x58F1, 0x9621 } },
     1285                { 900, { 0x4E5D, 0x767E } },
     1286                { 800, { 0x516B, 0x767E } },
     1287                { 700, { 0x4E03, 0x767E } },
     1288                { 600, { 0x516D, 0x767E } },
     1289                { 500, { 0x4F0D, 0x767E } },
     1290                { 400, { 0x56DB, 0x767E } },
     1291                { 300, { 0x53C2, 0x767E } },
     1292                { 200, { 0x5F10, 0x767E } },
     1293                { 100, { 0x58F1, 0x767E } },
     1294                { 90, { 0x4E5D, 0x62FE } },
     1295                { 80, { 0x516B, 0x62FE } },
     1296                { 70, { 0x4E03, 0x62FE } },
     1297                { 60, { 0x516D, 0x62FE } },
     1298                { 50, { 0x4F0D, 0x62FE } },
     1299                { 40, { 0x56DB, 0x62FE } },
     1300                { 30, { 0x53C2, 0x62FE } },
     1301                { 20, { 0x5F10, 0x62FE } },
     1302                { 10, { 0x58F1, 0x62FE } },
     1303                { 9, { 0x4E5D } },
     1304                { 8, { 0x516B } },
     1305                { 7, { 0x4E03 } },
     1306                { 6, { 0x516D } },
     1307                { 5, { 0x4F0D } },
     1308                { 4, { 0x56DB } },
     1309                { 3, { 0x53C2 } },
     1310                { 2, { 0x5F10 } },
     1311                { 1, { 0x58F1 } },
     1312                { 0, { 0x96F6 } }
     1313            },
     1314            { 0x30DE, 0x30A4, 0x30CA, 0x30B9 }
     1315        };
     1316        return toPredefinedAdditiveSystem(value, japaneseFormalSystem);
     1317    }
     1318    case ListStyleType::KoreanHangulFormal: {
     1319        static CONSTEXPR_WITH_MSVC_INITIALIZER_LIST_WORKAROUND AdditiveSystem koreanHangulFormalSystem {
     1320            {
     1321                { 9000, { 0xAD6C, 0xCC9C } },
     1322                { 8000, { 0xD314, 0xCC9C } },
     1323                { 7000, { 0xCE60, 0xCC9C } },
     1324                { 6000, { 0xC721, 0xCC9C } },
     1325                { 5000, { 0xC624, 0xCC9C } },
     1326                { 4000, { 0xC0AC, 0xCC9C } },
     1327                { 3000, { 0xC0BC, 0xCC9C } },
     1328                { 2000, { 0xC774, 0xCC9C } },
     1329                { 1000, { 0xC77C, 0xCC9C } },
     1330                { 900, { 0xAD6C, 0xBC31 } },
     1331                { 800, { 0xD314, 0xBC31 } },
     1332                { 700, { 0xCE60, 0xBC31 } },
     1333                { 600, { 0xC721, 0xBC31 } },
     1334                { 500, { 0xC624, 0xBC31 } },
     1335                { 400, { 0xC0AC, 0xBC31 } },
     1336                { 300, { 0xC0BC, 0xBC31 } },
     1337                { 200, { 0xC774, 0xBC31 } },
     1338                { 100, { 0xC77C, 0xBC31 } },
     1339                { 90, { 0xAD6C, 0xC2ED } },
     1340                { 80, { 0xD314, 0xC2ED } },
     1341                { 70, { 0xCE60, 0xC2ED } },
     1342                { 60, { 0xC721, 0xC2ED } },
     1343                { 50, { 0xC624, 0xC2ED } },
     1344                { 40, { 0xC0AC, 0xC2ED } },
     1345                { 30, { 0xC0BC, 0xC2ED } },
     1346                { 20, { 0xC774, 0xC2ED } },
     1347                { 10, { 0xC77C, 0xC2ED } },
     1348                { 9, { 0xAD6C } },
     1349                { 8, { 0xD314 } },
     1350                { 7, { 0xCE60 } },
     1351                { 6, { 0xC721 } },
     1352                { 5, { 0xC624 } },
     1353                { 4, { 0xC0AC } },
     1354                { 3, { 0xC0BC } },
     1355                { 2, { 0xC774 } },
     1356                { 1, { 0xC77C } },
     1357                { 0, { 0xC601 } }
     1358            },
     1359            { 0xB9C8, 0xC774, 0xB108, 0xC2A4, ' ' }
     1360        };
     1361        return toPredefinedAdditiveSystem(value, koreanHangulFormalSystem);
     1362    }
     1363    case ListStyleType::KoreanHanjaInformal: {
     1364        static CONSTEXPR_WITH_MSVC_INITIALIZER_LIST_WORKAROUND AdditiveSystem koreanHanjaInformalSystem {
     1365            {
     1366                { 9000, { 0x4E5D, 0x5343 } },
     1367                { 8000, { 0x516B, 0x5343 } },
     1368                { 7000, { 0x4E03, 0x5343 } },
     1369                { 6000, { 0x516D, 0x5343 } },
     1370                { 5000, { 0x4E94, 0x5343 } },
     1371                { 4000, { 0x56DB, 0x5343 } },
     1372                { 3000, { 0x4E09, 0x5343 } },
     1373                { 2000, { 0x4E8C, 0x5343 } },
     1374                { 1000, { 0x5343 } },
     1375                { 900, { 0x4E5D, 0x767E } },
     1376                { 800, { 0x516B, 0x767E } },
     1377                { 700, { 0x4E03, 0x767E } },
     1378                { 600, { 0x516D, 0x767E } },
     1379                { 500, { 0x4E94, 0x767E } },
     1380                { 400, { 0x56DB, 0x767E } },
     1381                { 300, { 0x4E09, 0x767E } },
     1382                { 200, { 0x4E8C, 0x767E } },
     1383                { 100, { 0x767E } },
     1384                { 90, { 0x4E5D, 0x5341 } },
     1385                { 80, { 0x516B, 0x5341 } },
     1386                { 70, { 0x4E03, 0x5341 } },
     1387                { 60, { 0x516D, 0x5341 } },
     1388                { 50, { 0x4E94, 0x5341 } },
     1389                { 40, { 0x56DB, 0x5341 } },
     1390                { 30, { 0x4E09, 0x5341 } },
     1391                { 20, { 0x4E8C, 0x5341 } },
     1392                { 10, { 0x5341 } },
     1393                { 9, { 0x4E5D } },
     1394                { 8, { 0x516B } },
     1395                { 7, { 0x4E03 } },
     1396                { 6, { 0x516D } },
     1397                { 5, { 0x4E94 } },
     1398                { 4, { 0x56DB } },
     1399                { 3, { 0x4E09 } },
     1400                { 2, { 0x4E8C } },
     1401                { 1, { 0x4E00 } },
     1402                { 0, { 0x96F6 } }
     1403            },
     1404            { 0xB9C8, 0xC774, 0xB108, 0xC2A4, ' ' }
     1405        };
     1406        return toPredefinedAdditiveSystem(value, koreanHanjaInformalSystem);
     1407    }
     1408    case ListStyleType::KoreanHanjaFormal: {
     1409        static CONSTEXPR_WITH_MSVC_INITIALIZER_LIST_WORKAROUND AdditiveSystem koreanHanjaFormalSystem {
     1410            {
     1411                { 9000, { 0x4E5D, 0x4EDF } },
     1412                { 8000, { 0x516B, 0x4EDF } },
     1413                { 7000, { 0x4E03, 0x4EDF } },
     1414                { 6000, { 0x516D, 0x4EDF } },
     1415                { 5000, { 0x4E94, 0x4EDF } },
     1416                { 4000, { 0x56DB, 0x4EDF } },
     1417                { 3000, { 0x53C3, 0x4EDF } },
     1418                { 2000, { 0x8CB3, 0x4EDF } },
     1419                { 1000, { 0x58F9, 0x4EDF } },
     1420                { 900, { 0x4E5D, 0x767E } },
     1421                { 800, { 0x516B, 0x767E } },
     1422                { 700, { 0x4E03, 0x767E } },
     1423                { 600, { 0x516D, 0x767E } },
     1424                { 500, { 0x4E94, 0x767E } },
     1425                { 400, { 0x56DB, 0x767E } },
     1426                { 300, { 0x53C3, 0x767E } },
     1427                { 200, { 0x8CB3, 0x767E } },
     1428                { 100, { 0x58F9, 0x767E } },
     1429                { 90, { 0x4E5D, 0x62FE } },
     1430                { 80, { 0x516B, 0x62FE } },
     1431                { 70, { 0x4E03, 0x62FE } },
     1432                { 60, { 0x516D, 0x62FE } },
     1433                { 50, { 0x4E94, 0x62FE } },
     1434                { 40, { 0x56DB, 0x62FE } },
     1435                { 30, { 0x53C3, 0x62FE } },
     1436                { 20, { 0x8CB3, 0x62FE } },
     1437                { 10, { 0x58F9, 0x62FE } },
     1438                { 9, { 0x4E5D } },
     1439                { 8, { 0x516B } },
     1440                { 7, { 0x4E03 } },
     1441                { 6, { 0x516D } },
     1442                { 5, { 0x4E94 } },
     1443                { 4, { 0x56DB } },
     1444                { 3, { 0x53C3 } },
     1445                { 2, { 0x8CB3 } },
     1446                { 1, { 0x58F9 } },
     1447                { 0, { 0x96F6 } }
     1448            },
     1449            { 0xB9C8, 0xC774, 0xB108, 0xC2A4, ' ' }
     1450        };
     1451        return toPredefinedAdditiveSystem(value, koreanHanjaFormalSystem);
     1452    }
     1453
     1454    case ListStyleType::EthiopicNumeric:
     1455        return toEthiopicNumeric(value);
    10661456
    10671457    case ListStyleType::String:
     
    11211511{
    11221512    auto box = RenderBox::createInlineBox();
    1123     box->setBehavesLikeText(isText());
     1513    box->setBehavesLikeText(!isImage());
    11241514    return box;
    11251515}
     
    11421532}
    11431533
     1534static String reversed(StringView string)
     1535{
     1536    auto length = string.length();
     1537    if (length <= 1)
     1538        return string.toString();
     1539    UChar* characters;
     1540    auto result = String::createUninitialized(length, characters);
     1541    for (unsigned i = 0; i < length; ++i)
     1542        *characters++ = string[length - i - 1];
     1543    return result;
     1544}
     1545
     1546struct RenderListMarker::TextRunWithUnderlyingString {
     1547    TextRun textRun;
     1548    String underlyingString;
     1549    operator const TextRun&() const { return textRun; }
     1550};
     1551
     1552auto RenderListMarker::textRun() const -> TextRunWithUnderlyingString
     1553{
     1554    ASSERT(!m_textWithSuffix.isEmpty());
     1555
     1556    // Since the bidi algorithm doesn't run on this text, we instead reorder the characters here.
     1557    // We use u_charDirection to figure out if the marker text is RTL and assume the suffix matches the surrounding direction.
     1558    String textForRun;
     1559    if (m_textIsLeftToRightDirection) {
     1560        if (style().isLeftToRightDirection())
     1561            textForRun = m_textWithSuffix;
     1562        else {
     1563            if (style().listStyleType() == ListStyleType::DisclosureClosed)
     1564                textForRun = { &blackLeftPointingSmallTriangle, 1 };
     1565            else
     1566                textForRun = makeString(reversed(m_textWithSuffix.substring(m_textWithoutSuffixLength)), m_textWithSuffix.left(m_textWithoutSuffixLength));
     1567        }
     1568    } else {
     1569        if (!style().isLeftToRightDirection())
     1570            textForRun = reversed(m_textWithSuffix);
     1571        else
     1572            textForRun = makeString(reversed(m_textWithSuffix.left(m_textWithoutSuffixLength)), m_textWithSuffix.substring(m_textWithoutSuffixLength));
     1573    }
     1574    auto textRun = RenderBlock::constructTextRun(textForRun, style());
     1575    return { WTFMove(textRun), WTFMove(textForRun) };
     1576}
     1577
    11441578void RenderListMarker::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
    11451579{
     
    11581592    LayoutRect box(boxOrigin, size());
    11591593   
    1160     auto markerRect = getRelativeMarkerRect();
     1594    auto markerRect = relativeMarkerRect();
    11611595    markerRect.moveBy(boxOrigin);
    11621596    if (markerRect.isEmpty())
     
    11881622    context.setFillColor(color);
    11891623
    1190     auto type = style().listStyleType();
    1191     switch (type) {
     1624    switch (style().listStyleType()) {
    11921625    case ListStyleType::Disc:
    11931626        context.drawEllipse(markerRect);
     
    12001633        context.drawRect(markerRect);
    12011634        return;
    1202     case ListStyleType::None:
    1203         return;
    12041635    default:
    12051636        break;
    12061637    }
    1207     if (m_text.isEmpty())
     1638    if (m_textWithSuffix.isEmpty())
    12081639        return;
    1209 
    1210     const FontCascade& font = style().fontCascade();
    1211     TextRun textRun = RenderBlock::constructTextRun(m_text, style());
    12121640
    12131641    GraphicsContextStateSaver stateSaver(context, false);
     
    12241652    FloatPoint textOrigin = FloatPoint(markerRect.x(), markerRect.y() + style().fontMetrics().ascent());
    12251653    textOrigin = roundPointToDevicePixels(LayoutPoint(textOrigin), document().deviceScaleFactor(), style().isLeftToRightDirection());
    1226 
    1227     if (type == ListStyleType::Asterisks || type == ListStyleType::Footnotes || type == ListStyleType::String)
    1228         context.drawText(font, textRun, textOrigin);
    1229     else {
    1230         auto suffix = listMarkerSuffix(type, m_listItem->value());
    1231 
    1232         // FIXME: Could use a Vector with inline capacity instead of String to avoid
    1233         // memory allocation here.
    1234         String textToDraw;
    1235 
    1236         // Since marker text is not arbitrary, we can judge its direction just by
    1237         // checking the first character, and only need to handle U_RIGHT_TO_LEFT.
    1238         // FIXME: Could check more efficiently than u_charDirection, since we know
    1239         // only certain characters are used and only need to check for U_RIGHT_TO_LEFT.
    1240         bool shouldAddSpace = suffixRequiresSpace(suffix);
    1241         if (u_charDirection(m_text[0]) == U_RIGHT_TO_LEFT) {
    1242             unsigned length = m_text.length();
    1243             UChar* characters;
    1244             textToDraw = String::createUninitialized(length + 1 + shouldAddSpace, characters);
    1245             if (!style().isLeftToRightDirection()) {
    1246                 if (shouldAddSpace)
    1247                     *characters++ = space;
    1248                 *characters++ = suffix;
    1249             }
    1250             for (unsigned i = 0; i < length; ++i)
    1251                 *characters++ = m_text[length - i - 1];
    1252             if (style().isLeftToRightDirection()) {
    1253                 *characters++ = suffix;
    1254                 if (shouldAddSpace)
    1255                     *characters++ = space;
    1256             }
    1257         } else {
    1258             if (style().isLeftToRightDirection())
    1259                 textToDraw = makeString(m_text, suffix, shouldAddSpace ? " " : "");
    1260             else
    1261                 textToDraw = makeString(shouldAddSpace ? " " : "", suffix, m_text);
    1262         }
    1263         textRun.setText(textToDraw);
    1264 
    1265         context.drawText(font, textRun, textOrigin);
    1266     }
     1654    context.drawText(style().fontCascade(), textRun(), textOrigin);
    12671655}
    12681656
     
    13061694    // FIXME: Need to account for relative positioning in the layout overflow.
    13071695    if (m_listItem->style().isLeftToRightDirection()) {
    1308         markerLogicalLeft = lineOffsetForListItem() - lineOffset - m_listItem->paddingStart() - m_listItem->borderStart() + marginStart();
     1696        markerLogicalLeft = m_lineOffsetForListItem - lineOffset - m_listItem->paddingStart() - m_listItem->borderStart() + marginStart();
    13091697        inlineBoxWrapper()->adjustLineDirectionPosition(markerLogicalLeft - markerOldLogicalLeft);
    13101698        for (auto* box = inlineBoxWrapper()->parent(); box; box = box->parent()) {
     
    13281716        }
    13291717    } else {
    1330         markerLogicalLeft = lineOffsetForListItem() - lineOffset + m_listItem->paddingStart() + m_listItem->borderStart() + marginEnd();
     1718        markerLogicalLeft = m_lineOffsetForListItem - lineOffset + m_listItem->paddingStart() + m_listItem->borderStart() + marginEnd();
    13311719        inlineBoxWrapper()->adjustLineDirectionPosition(markerLogicalLeft - markerOldLogicalLeft);
    13321720        for (auto* box = inlineBoxWrapper()->parent(); box; box = box->parent()) {
     
    14241812void RenderListMarker::updateMarginsAndContent()
    14251813{
    1426     updateContent();
     1814    // FIXME: It's messy to use the preferredLogicalWidths dirty bit for this optimization, also unclear if this is premature optimization.
     1815    if (preferredLogicalWidthsDirty())
     1816        updateContent();
    14271817    updateMargins();
    14281818}
     
    14301820void RenderListMarker::updateContent()
    14311821{
    1432     // FIXME: This if-statement is just a performance optimization, but it's messy to use the preferredLogicalWidths dirty bit for this.
    1433     // It's unclear if this is a premature optimization.
    1434     if (!preferredLogicalWidthsDirty())
    1435         return;
    1436 
    1437     m_text = emptyString();
    1438 
    14391822    if (isImage()) {
    14401823        // FIXME: This is a somewhat arbitrary width.  Generated images for markers really won't become particularly useful
     
    14441827        LayoutSize imageSize = calculateImageIntrinsicDimensions(m_image.get(), defaultBulletSize, DoNotScaleByEffectiveZoom);
    14451828        m_image->setContainerContextForRenderer(*this, imageSize, style().effectiveZoom());
     1829        m_textWithSuffix = emptyString();
     1830        m_textWithoutSuffixLength = 0;
     1831        m_textIsLeftToRightDirection = true;
    14461832        return;
    14471833    }
     
    14491835    auto type = style().listStyleType();
    14501836    switch (type) {
    1451     case ListStyleType::None:
    1452         break;
    14531837    case ListStyleType::String:
    1454         m_text = style().listStyleStringValue();
    1455         break;
    1456     case ListStyleType::Circle:
    1457     case ListStyleType::Disc:
    1458     case ListStyleType::Square:
    1459         m_text = listMarkerText(type, 0); // value is ignored for these types
     1838        m_textWithSuffix = style().listStyleStringValue();
     1839        m_textWithoutSuffixLength = m_textWithSuffix.length();
     1840        // FIXME: Depending on the string value, we may need the real bidi algorithm.
     1841        m_textIsLeftToRightDirection = u_charDirection(m_textWithSuffix[0]) != U_RIGHT_TO_LEFT;
    14601842        break;
    14611843    default:
    1462         m_text = listMarkerText(type, m_listItem->value());
     1844        auto text = listMarkerText(type, m_listItem->value());
     1845        m_textWithSuffix = makeString(text, listMarkerSuffix(type));
     1846        m_textWithoutSuffixLength = text.length();
     1847        m_textIsLeftToRightDirection = u_charDirection(text[0]) != U_RIGHT_TO_LEFT;
    14631848        break;
    14641849    }
     
    14811866
    14821867    LayoutUnit logicalWidth;
    1483     auto type = style().listStyleType();
    1484     switch (type) {
    1485     case ListStyleType::None:
    1486         break;
    1487     case ListStyleType::Asterisks:
    1488     case ListStyleType::Footnotes:
    1489     case ListStyleType::String:
    1490         if (!m_text.isEmpty()) {
    1491             TextRun run = RenderBlock::constructTextRun(m_text, style());
    1492             logicalWidth = font.width(run); // no suffix for these types
    1493         }
    1494         break;
     1868    switch (style().listStyleType()) {
    14951869    case ListStyleType::Circle:
    14961870    case ListStyleType::Disc:
     
    14991873        break;
    15001874    default:
    1501         if (m_text.isEmpty())
    1502             logicalWidth = 0;
    1503         else {
    1504             TextRun run = RenderBlock::constructTextRun(m_text, style());
    1505             LayoutUnit itemWidth { font.width(run) };
    1506             UChar suffix[2] = { listMarkerSuffix(type, m_listItem->value()), ' ' };
    1507             LayoutUnit suffixWidth { font.width(RenderBlock::constructTextRun(suffix, suffixRequiresSpace(suffix[0]) ? 2 : 1, style())) };
    1508             logicalWidth = itemWidth + suffixWidth;
    1509         }
     1875        if (!m_textWithSuffix.isEmpty())
     1876            logicalWidth = font.width(textRun());
    15101877        break;
    15111878    }
     
    15511918            marginEnd = offset + cMarkerPadding + 1 - minPreferredLogicalWidth();
    15521919            break;
    1553         case ListStyleType::None:
    1554             break;
    15551920        case ListStyleType::String:
    1556             if (!m_text.isEmpty())
     1921            if (!m_textWithSuffix.isEmpty())
    15571922                marginStart = -minPreferredLogicalWidth();
    15581923            break;
    15591924        default:
    1560             if (!m_text.isEmpty()) {
     1925            if (!m_textWithSuffix.isEmpty()) {
    15611926                marginStart = -minPreferredLogicalWidth() - offset / 2;
    15621927                marginEnd = offset / 2;
     
    15831948}
    15841949
    1585 String RenderListMarker::suffix() const
    1586 {
    1587     auto type = style().listStyleType();
    1588     if (type == ListStyleType::String)
    1589         return emptyString();
    1590 
    1591     auto suffix = listMarkerSuffix(type, m_listItem->value());
    1592 
    1593     if (suffix == ' ')
    1594         return " "_str;
    1595     if (!suffixRequiresSpace(suffix))
    1596         return { &suffix, 1 };
    1597 
    1598     UChar data[2];
    1599     if (style().isLeftToRightDirection()) {
    1600         data[0] = suffix;
    1601         data[1] = ' ';
    1602     } else {
    1603         data[0] = ' ';
    1604         data[1] = suffix;
    1605     }
    1606     return { data, 2 };
    1607 }
    1608 
    16091950bool RenderListMarker::isInside() const
    16101951{
     
    16121953}
    16131954
    1614 FloatRect RenderListMarker::getRelativeMarkerRect()
     1955FloatRect RenderListMarker::relativeMarkerRect()
    16151956{
    16161957    if (isImage())
    16171958        return FloatRect(0, 0, m_image->imageSize(this, style().effectiveZoom()).width(), m_image->imageSize(this, style().effectiveZoom()).height());
    1618    
     1959
    16191960    FloatRect relativeRect;
    1620     auto type = style().listStyleType();
    1621     switch (type) {
    1622     case ListStyleType::Asterisks:
    1623     case ListStyleType::Footnotes:
    1624     case ListStyleType::String: {
    1625         if (m_text.isEmpty())
    1626             return FloatRect();
    1627         const FontCascade& font = style().fontCascade();
    1628         TextRun run = RenderBlock::constructTextRun(m_text, style());
    1629         relativeRect = FloatRect(0, 0, font.width(run), font.fontMetrics().height());
    1630         break;
    1631     }
     1961    switch (style().listStyleType()) {
    16321962    case ListStyleType::Disc:
    16331963    case ListStyleType::Circle:
     
    16401970        break;
    16411971    }
    1642     case ListStyleType::None:
    1643         return FloatRect();
    16441972    default:
    1645         if (m_text.isEmpty())
     1973        if (m_textWithSuffix.isEmpty())
    16461974            return FloatRect();
    1647         const FontCascade& font = style().fontCascade();
    1648         TextRun run = RenderBlock::constructTextRun(m_text, style());
    1649         float itemWidth = font.width(run);
    1650         UChar suffix[2] = { listMarkerSuffix(type, m_listItem->value()), ' ' };
    1651         float suffixWidth = font.width(RenderBlock::constructTextRun(suffix, suffixRequiresSpace(suffix[0]) ? 2 : 1, style()));
    1652         relativeRect = FloatRect(0, 0, itemWidth + suffixWidth, font.fontMetrics().height());
     1975        auto& font = style().fontCascade();
     1976        relativeRect = FloatRect(0, 0, font.width(textRun()), font.fontMetrics().height());
     1977        break;
    16531978    }
    16541979
     
    16762001}
    16772002
     2003StringView RenderListMarker::textWithoutSuffix() const
     2004{
     2005    return StringView { m_textWithSuffix }.left(m_textWithoutSuffixLength);
     2006}
     2007
    16782008} // namespace WebCore
  • trunk/Source/WebCore/rendering/RenderListMarker.h

    r278534 r279165  
    22 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
    33 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
    4  * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2009 Apple Inc. All rights reserved.
     4 * Copyright (C) 2003-2021 Apple Inc. All rights reserved.
    55 *
    66 * This library is free software; you can redistribute it and/or
     
    3939    virtual ~RenderListMarker();
    4040
    41     const String& text() const { return m_text; }
    42     String suffix() const;
     41    StringView textWithoutSuffix() const;
     42    StringView textWithSuffix() const { return m_textWithSuffix; }
    4343
    4444    bool isInside() const;
    4545
    46     LayoutUnit lineOffsetForListItem() const { return m_lineOffsetForListItem; }
    47 
    4846    void updateMarginsAndContent();
    49 
    5047    void addOverflowFromListMarker();
    5148
    5249private:
    53     void willBeDestroyed() override;
     50    void willBeDestroyed() final;
     51    const char* renderName() const final { return "RenderListMarker"; }
     52    void computePreferredLogicalWidths() final;
     53    bool isListMarker() const final { return true; }
     54    bool canHaveChildren() const final { return false; }
     55    void paint(PaintInfo&, const LayoutPoint&) final;
     56    void layout() final;
     57    void imageChanged(WrappedImagePtr, const IntRect*) final;
     58    std::unique_ptr<LegacyInlineElementBox> createInlineBox() final;
     59    LayoutUnit lineHeight(bool firstLine, LineDirectionMode, LinePositionMode) const final;
     60    LayoutUnit baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode) const final;
     61    bool isImage() const final;
     62    LayoutRect selectionRectForRepaint(const RenderLayerModelObject* repaintContainer, bool clipToVisibleContent) final;
     63    bool canBeSelectionLeaf() const final { return true; }
     64    void styleDidChange(StyleDifference, const RenderStyle* oldStyle) final;
    5465
    5566    void element() const = delete;
    5667
    57     const char* renderName() const override { return "RenderListMarker"; }
    58     void computePreferredLogicalWidths() override;
    59 
    60     bool isListMarker() const override { return true; }
    61     bool canHaveChildren() const override { return false; }
    62 
    63     void paint(PaintInfo&, const LayoutPoint&) override;
    64 
    65     void layout() override;
    66 
    67     void imageChanged(WrappedImagePtr, const IntRect* = 0) override;
    68 
    69     std::unique_ptr<LegacyInlineElementBox> createInlineBox() override;
    70 
    71     LayoutUnit lineHeight(bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const override;
    72     LayoutUnit baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const override;
    73 
    74     bool isImage() const override;
    75     bool isText() const { return !isImage(); }
    76 
    77     LayoutRect selectionRectForRepaint(const RenderLayerModelObject* repaintContainer, bool clipToVisibleContent = true) override;
    78     bool canBeSelectionLeaf() const override { return true; }
    79 
    8068    void updateMargins();
    8169    void updateContent();
    82 
    83     void styleDidChange(StyleDifference, const RenderStyle* oldStyle) override;
    84 
    8570    RenderBox* parentBox(RenderBox&);
    86 
    87     FloatRect getRelativeMarkerRect();
     71    FloatRect relativeMarkerRect();
    8872    LayoutRect localSelectionRect();
    8973
    90     String m_text;
     74    struct TextRunWithUnderlyingString;
     75    TextRunWithUnderlyingString textRun() const;
     76
     77    String m_textWithSuffix;
     78    uint8_t m_textWithoutSuffixLength { 0 };
     79    bool m_textIsLeftToRightDirection { true };
    9180    RefPtr<StyleImage> m_image;
    9281    WeakPtr<RenderListItem> m_listItem;
  • trunk/Source/WebCore/rendering/RenderTreeAsText.cpp

    r278669 r279165  
    441441
    442442    if (is<RenderListMarker>(o)) {
    443         String text = downcast<RenderListMarker>(o).text();
     443        String text = downcast<RenderListMarker>(o).textWithoutSuffix().toString();
    444444        if (!text.isEmpty()) {
    445445            if (text.length() != 1)
     
    958958        return String();
    959959
    960     return downcast<RenderListItem>(*renderer).markerText();
     960    return downcast<RenderListItem>(*renderer).markerTextWithoutSuffix().toString();
    961961}
    962962
  • trunk/Source/WebCore/rendering/style/RenderStyleConstants.cpp

    r279055 r279165  
    11/*
    2  * Copyright (C) 2015-2020 Apple Inc. All rights reserved.
     2 * Copyright (C) 2015-2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    715715TextStream& operator<<(TextStream& ts, ListStyleType styleType)
    716716{
    717     switch (styleType) {
    718     case ListStyleType::Afar: ts << "afar"; break;
    719     case ListStyleType::Amharic: ts << "amharic"; break;
    720     case ListStyleType::AmharicAbegede: ts << "amharic-abegede"; break;
    721     case ListStyleType::ArabicIndic: ts << "arabic-indic"; break;
    722     case ListStyleType::Armenian: ts << "armenian"; break;
    723     case ListStyleType::Asterisks: ts << "asterisks"; break;
    724     case ListStyleType::Bengali: ts << "bengali"; break;
    725     case ListStyleType::Binary: ts << "binary"; break;
    726     case ListStyleType::CJKDecimal: ts << "cjk-decimal"; break;
    727     case ListStyleType::CJKIdeographic: ts << "cjk-ideographic"; break;
    728     case ListStyleType::Cambodian: ts << "cambodian"; break;
    729     case ListStyleType::Circle: ts << "circle"; break;
    730     case ListStyleType::CJKEarthlyBranch: ts << "cjk-earthly-branch"; break;
    731     case ListStyleType::CJKHeavenlyStem: ts << "cjk-heavenly-stem"; break;
    732     case ListStyleType::Decimal: ts << "decimal"; break;
    733     case ListStyleType::DecimalLeadingZero: ts << "decimal-leading-zero"; break;
    734     case ListStyleType::Devanagari: ts << "devanagari"; break;
    735     case ListStyleType::Disc: ts << "disc"; break;
    736     case ListStyleType::Ethiopic: ts << "ethiopic"; break;
    737     case ListStyleType::EthiopicAbegede: ts << "ethiopic-abegede"; break;
    738     case ListStyleType::EthiopicAbegedeAmEt: ts << "ethiopic-abegede-am-et"; break;
    739     case ListStyleType::EthiopicAbegedeGez: ts << "ethiopic-abegede-gez"; break;
    740     case ListStyleType::EthiopicAbegedeTiEr: ts << "ethiopic-abegede-ti-er"; break;
    741     case ListStyleType::EthiopicAbegedeTiEt: ts << "ethiopic-abegede-ti-et"; break;
    742     case ListStyleType::EthiopicHalehameAaEr: ts << "ethiopic-halehame-aa-er"; break;
    743     case ListStyleType::EthiopicHalehameAaEt: ts << "ethiopic-halehame-aa-et"; break;
    744     case ListStyleType::EthiopicHalehameAmEt: ts << "ethiopic-halehame-am-et"; break;
    745     case ListStyleType::EthiopicHalehameGez: ts << "ethiopic-halehame-gez"; break;
    746     case ListStyleType::EthiopicHalehameOmEt: ts << "ethiopic-halehame-om-et"; break;
    747     case ListStyleType::EthiopicHalehameSidEt: ts << "ethiopic-halehame-sid-et"; break;
    748     case ListStyleType::EthiopicHalehameSoEt: ts << "ethiopic-halehame-so-et"; break;
    749     case ListStyleType::EthiopicHalehameTiEr: ts << "ethiopic-halehame-ti-er"; break;
    750     case ListStyleType::EthiopicHalehameTiEt: ts << "ethiopic-halehame-ti-et"; break;
    751     case ListStyleType::EthiopicHalehameTig: ts << "ethiopic-halehame-tig"; break;
    752     case ListStyleType::Footnotes: ts << "footnotes"; break;
    753     case ListStyleType::Georgian: ts << "georgian"; break;
    754     case ListStyleType::Gujarati: ts << "gujarati"; break;
    755     case ListStyleType::Gurmukhi: ts << "gurmukhi"; break;
    756     case ListStyleType::Hangul: ts << "hangul"; break;
    757     case ListStyleType::HangulConsonant: ts << "hangul-consonant"; break;
    758     case ListStyleType::Hebrew: ts << "hebrew"; break;
    759     case ListStyleType::Hiragana: ts << "hiragana"; break;
    760     case ListStyleType::HiraganaIroha: ts << "hiragana-iroha"; break;
    761     case ListStyleType::Kannada: ts << "kannada"; break;
    762     case ListStyleType::Katakana: ts << "katakana"; break;
    763     case ListStyleType::KatakanaIroha: ts << "katakana-iroha"; break;
    764     case ListStyleType::Khmer: ts << "khmer"; break;
    765     case ListStyleType::Lao: ts << "lao"; break;
    766     case ListStyleType::LowerAlpha: ts << "lower-alpha"; break;
    767     case ListStyleType::LowerArmenian: ts << "lower-armenian"; break;
    768     case ListStyleType::LowerGreek: ts << "lower-greek"; break;
    769     case ListStyleType::LowerHexadecimal: ts << "lower-hexadecimal"; break;
    770     case ListStyleType::LowerLatin: ts << "lower-latin"; break;
    771     case ListStyleType::LowerNorwegian: ts << "lower-norwegian"; break;
    772     case ListStyleType::LowerRoman: ts << "lower-roman"; break;
    773     case ListStyleType::Malayalam: ts << "malayalam"; break;
    774     case ListStyleType::Mongolian: ts << "mongolian"; break;
    775     case ListStyleType::Myanmar: ts << "myanmar"; break;
    776     case ListStyleType::None: ts << "none"; break;
    777     case ListStyleType::Octal: ts << "octal"; break;
    778     case ListStyleType::Oriya: ts << "oriya"; break;
    779     case ListStyleType::Oromo: ts << "oromo"; break;
    780     case ListStyleType::Persian: ts << "persian"; break;
    781     case ListStyleType::Sidama: ts << "sidama"; break;
    782     case ListStyleType::Somali: ts << "somali"; break;
    783     case ListStyleType::Square: ts << "square"; break;
    784     case ListStyleType::String: ts << "string"; break;
    785     case ListStyleType::Tamil: ts << "tamil"; break;
    786     case ListStyleType::Telugu: ts << "telugu"; break;
    787     case ListStyleType::Thai: ts << "thai"; break;
    788     case ListStyleType::Tibetan: ts << "tibetan"; break;
    789     case ListStyleType::Tigre: ts << "tigre"; break;
    790     case ListStyleType::TigrinyaEr: ts << "tigrinya-er"; break;
    791     case ListStyleType::TigrinyaErAbegede: ts << "tigrinya-er-abegede"; break;
    792     case ListStyleType::TigrinyaEt: ts << "tigrinya-et"; break;
    793     case ListStyleType::TigrinyaEtAbegede: ts << "tigrinya-et-abegede"; break;
    794     case ListStyleType::UpperAlpha: ts << "upper-alpha"; break;
    795     case ListStyleType::UpperArmenian: ts << "upper-armenian"; break;
    796     case ListStyleType::UpperGreek: ts << "upper-greek"; break;
    797     case ListStyleType::UpperHexadecimal: ts << "upper-hexadecimal"; break;
    798     case ListStyleType::UpperLatin: ts << "upper-latin"; break;
    799     case ListStyleType::UpperNorwegian: ts << "upper-norwegian"; break;
    800     case ListStyleType::UpperRoman: ts << "upper-roman"; break;
    801     case ListStyleType::Urdu: ts << "urdu"; break;
    802     }
    803     return ts;
     717    return ts << getValueName(toCSSValueID(styleType));
    804718}
    805719
  • trunk/Source/WebCore/rendering/style/RenderStyleConstants.h

    r279055 r279165  
    659659    CJKDecimal,
    660660    Tamil,
     661    DisclosureOpen,
     662    DisclosureClosed,
     663    JapaneseInformal,
     664    JapaneseFormal,
     665    KoreanHangulFormal,
     666    KoreanHanjaInformal,
     667    KoreanHanjaFormal,
     668    SimplifiedChineseInformal,
     669    SimplifiedChineseFormal,
     670    TraditionalChineseInformal,
     671    TraditionalChineseFormal,
     672    EthiopicNumeric,
    661673    String,
    662674    None
Note: See TracChangeset for help on using the changeset viewer.