Changeset 269773 in webkit


Ignore:
Timestamp:
Nov 13, 2020 6:12:39 AM (3 years ago)
Author:
Alan Bujtas
Message:

[LFC][Integration] Add initial bidi support
https://bugs.webkit.org/show_bug.cgi?id=218884

Reviewed by Antti Koivisto.

In this patch, we introduce the Bidi Run and the Iterator and use the BidiResolver to compute
the bidi boundaries.
Currently only single direction content is passed in to the BidiResolver which meas that we always
end up with one and only one Bidi run.

  • layout/integration/LayoutIntegrationInlineContentBuilder.cpp:

(WebCore::LayoutIntegration::Iterator::offset const):
(WebCore::LayoutIntegration::Iterator::currentRun const):
(WebCore::LayoutIntegration::Iterator::runOffset const):
(WebCore::LayoutIntegration::Iterator::operator== const):
(WebCore::LayoutIntegration::Iterator::operator!= const):
(WebCore::LayoutIntegration::Iterator::atEnd const):
(WebCore::LayoutIntegration::Iterator::Iterator):
(WebCore::LayoutIntegration::Iterator::direction const):
(WebCore::LayoutIntegration::Iterator::increment):
(WebCore::LayoutIntegration::BidiRun::start const):
(WebCore::LayoutIntegration::BidiRun::end const):
(WebCore::LayoutIntegration::BidiRun::level const):
(WebCore::LayoutIntegration::BidiRun::next const):
(WebCore::LayoutIntegration::BidiRun::setNext):
(WebCore::LayoutIntegration::BidiRun::takeNext):
(WebCore::LayoutIntegration::BidiRun::BidiRun):
(WebCore::LayoutIntegration::InlineContentBuilder::createDisplayLineRuns const):

Location:
trunk/Source/WebCore
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r269772 r269773  
     12020-11-13  Zalan Bujtas  <zalan@apple.com>
     2
     3        [LFC][Integration] Add initial bidi support
     4        https://bugs.webkit.org/show_bug.cgi?id=218884
     5
     6        Reviewed by Antti Koivisto.
     7
     8        In this patch, we introduce the Bidi Run and the Iterator and use the BidiResolver to compute
     9        the bidi boundaries.
     10        Currently only single direction content is passed in to the BidiResolver which meas that we always
     11        end up with one and only one Bidi run.
     12
     13        * layout/integration/LayoutIntegrationInlineContentBuilder.cpp:
     14        (WebCore::LayoutIntegration::Iterator::offset const):
     15        (WebCore::LayoutIntegration::Iterator::currentRun const):
     16        (WebCore::LayoutIntegration::Iterator::runOffset const):
     17        (WebCore::LayoutIntegration::Iterator::operator== const):
     18        (WebCore::LayoutIntegration::Iterator::operator!= const):
     19        (WebCore::LayoutIntegration::Iterator::atEnd const):
     20        (WebCore::LayoutIntegration::Iterator::Iterator):
     21        (WebCore::LayoutIntegration::Iterator::direction const):
     22        (WebCore::LayoutIntegration::Iterator::increment):
     23        (WebCore::LayoutIntegration::BidiRun::start const):
     24        (WebCore::LayoutIntegration::BidiRun::end const):
     25        (WebCore::LayoutIntegration::BidiRun::level const):
     26        (WebCore::LayoutIntegration::BidiRun::next const):
     27        (WebCore::LayoutIntegration::BidiRun::setNext):
     28        (WebCore::LayoutIntegration::BidiRun::takeNext):
     29        (WebCore::LayoutIntegration::BidiRun::BidiRun):
     30        (WebCore::LayoutIntegration::InlineContentBuilder::createDisplayLineRuns const):
     31
    1322020-11-13  Miguel Gomez  <magomez@igalia.com>
    233
  • trunk/Source/WebCore/layout/integration/LayoutIntegrationInlineContentBuilder.cpp

    r269770 r269773  
    2929#if ENABLE(LAYOUT_FORMATTING_CONTEXT)
    3030
     31#include "BidiResolver.h"
    3132#include "InlineFormattingContext.h"
    3233#include "InlineFormattingState.h"
     
    5859    lineBoxLogicalWidth += endPadding;
    5960    return std::max(lineLogicalWidth, lineBoxLogicalWidth);
     61}
     62
     63class Iterator {
     64public:
     65    Iterator() = default;
     66    Iterator(const Layout::InlineLineRuns* runList, size_t currentRunIndex);
     67
     68    void increment();
     69    unsigned offset() const { return m_offset; }
     70    UCharDirection direction() const;
     71
     72    bool operator==(const Iterator& other) const { return offset() == other.offset(); }
     73    bool operator!=(const Iterator& other) const { return offset() != other.offset(); };
     74    bool atEnd() const { return !m_runList || m_runIndex == m_runList->size(); };
     75
     76private:
     77    const Layout::LineRun& currentRun() const { return m_runList->at(m_runIndex); }
     78
     79    const Layout::InlineLineRuns* m_runList { nullptr };
     80    size_t m_offset { 0 };
     81    size_t m_runIndex { 0 };
     82    size_t m_runOffset { 0 };
     83};
     84
     85Iterator::Iterator(const Layout::InlineLineRuns* runList, size_t runIndex)
     86    : m_runList(runList)
     87    , m_runIndex(runIndex)
     88{
     89}
     90
     91UCharDirection Iterator::direction() const
     92{
     93    ASSERT(m_runList);
     94    ASSERT(!atEnd());
     95    auto& textContent = currentRun().text();
     96    if (!textContent)
     97        return U_OTHER_NEUTRAL;
     98    return u_charDirection(textContent->content()[textContent->start() + m_runOffset]);
     99}
     100
     101void Iterator::increment()
     102{
     103    ASSERT(m_runList);
     104    ASSERT(!atEnd());
     105    ++m_offset;
     106    auto& currentRun = this->currentRun();
     107    if (auto& textContent = currentRun.text()) {
     108        if (++m_runOffset < textContent->length())
     109            return;
     110    }
     111    ++m_runIndex;
     112    m_runOffset = 0;
     113}
     114
     115class BidiRun {
     116    WTF_MAKE_FAST_ALLOCATED;
     117public:
     118    BidiRun(unsigned start, unsigned end, BidiContext*, UCharDirection);
     119
     120    size_t start() const { return m_start; }
     121    size_t end() const { return m_end; }
     122    unsigned char level() const { return m_level; }
     123
     124    BidiRun* next() const { return m_next.get(); }
     125    void setNext(std::unique_ptr<BidiRun>&& next) { m_next = WTFMove(next); }
     126    std::unique_ptr<BidiRun> takeNext() { return WTFMove(m_next); }
     127
     128private:
     129    std::unique_ptr<BidiRun> m_next;
     130    size_t m_start { 0 };
     131    size_t m_end { 0 };
     132    unsigned char m_level { 0 };
     133};
     134
     135BidiRun::BidiRun(unsigned start, unsigned end, BidiContext* context, UCharDirection direction)
     136    : m_start(start)
     137    , m_end(end)
     138    , m_level(context->level())
     139{
     140    ASSERT(context);
     141    if (direction == U_OTHER_NEUTRAL)
     142        direction = context->dir();
     143    if (m_level % 2)
     144        m_level = (direction == U_LEFT_TO_RIGHT || direction == U_ARABIC_NUMBER || direction == U_EUROPEAN_NUMBER) ? m_level + 1 : m_level;
     145    else
     146        m_level = (direction == U_RIGHT_TO_LEFT) ? m_level + 1 : (direction == U_ARABIC_NUMBER || direction == U_EUROPEAN_NUMBER) ? m_level + 2 : m_level;
    60147}
    61148
     
    113200        return;
    114201    auto& lines = inlineFormattingState.lines();
     202
     203    BidiResolver<Iterator, BidiRun> bidiResolver;
     204    // FIXME: Add support for override.
     205    bidiResolver.setStatus(BidiStatus(m_layoutState.root().style().direction(), false));
     206    // FIXME: Grab the nested isolates from the previous line.
     207    bidiResolver.setPosition(Iterator(&runList, 0), 0);
     208    bidiResolver.createBidiRunsForLine(Iterator(&runList, runList.size()));
     209
    115210    Vector<bool> hasAdjustedTrailingLineList(lines.size(), false);
    116211
     
    188283    };
    189284
    190     for (auto& lineRun : inlineFormattingState.lineRuns()) {
    191         if (auto& text = lineRun.text())
    192             createDisplayTextRunForRange(lineRun, text->start(), text->end());
    193         else
    194             createDisplayBoxRun(lineRun);
    195     }
     285    auto& bidiRuns = bidiResolver.runs();
     286    if (bidiRuns.runCount() == 1) {
     287        // Fast path for cases when there's no bidi boundary.
     288        for (auto& lineRun : inlineFormattingState.lineRuns()) {
     289            if (auto& text = lineRun.text())
     290                createDisplayTextRunForRange(lineRun, text->start(), text->end());
     291            else
     292                createDisplayBoxRun(lineRun);
     293        }
     294    } else
     295        ASSERT_NOT_IMPLEMENTED_YET();
    196296}
    197297
Note: See TracChangeset for help on using the changeset viewer.