Changeset 159560 in webkit


Ignore:
Timestamp:
Nov 20, 2013, 7:14:00 AM (11 years ago)
Author:
Antti Koivisto
Message:

Don't paint simple text runs outside the paint rect
https://bugs.webkit.org/show_bug.cgi?id=124651

Reviewed by Anders Carlsson.

This speeds up partial paints for long text paragraphs.
Also add the same optimization for hit testing.

  • rendering/SimpleLineLayoutFunctions.cpp:

(WebCore::SimpleLineLayout::paintFlow):

Iterate over the run range that needs painting.

(WebCore::SimpleLineLayout::hitTestFlow):

Iterate over the line range that needs painting.

  • rendering/SimpleLineLayoutResolver.h:

(WebCore::SimpleLineLayout::Range::Range):
(WebCore::SimpleLineLayout::Range::begin):
(WebCore::SimpleLineLayout::Range::end):

Add Range type.

(WebCore::SimpleLineLayout::RunResolver::Iterator::Iterator):
(WebCore::SimpleLineLayout::RunResolver::Iterator::operator++):
(WebCore::SimpleLineLayout::RunResolver::Iterator::advance):
(WebCore::SimpleLineLayout::RunResolver::Iterator::advanceLines):

Optimize case where runCount==lineCount. In this case we can just directly jump
to the right run/line.

(WebCore::SimpleLineLayout::RunResolver::begin):
(WebCore::SimpleLineLayout::RunResolver::end):
(WebCore::SimpleLineLayout::RunResolver::lineIndexForHeight):
(WebCore::SimpleLineLayout::RunResolver::rangeForRect):

Get the range corresponding to a rect. This currently cares about y coordinates only.

(WebCore::SimpleLineLayout::LineResolver::Iterator::operator++):
(WebCore::SimpleLineLayout::LineResolver::Iterator::operator*):
(WebCore::SimpleLineLayout::LineResolver::rangeForRect):

Location:
trunk/Source/WebCore
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r159559 r159560  
     12013-11-20  Antti Koivisto  <antti@apple.com>
     2
     3        Don't paint simple text runs outside the paint rect
     4        https://bugs.webkit.org/show_bug.cgi?id=124651
     5
     6        Reviewed by Anders Carlsson.
     7       
     8        This speeds up partial paints for long text paragraphs.
     9        Also add the same optimization for hit testing.
     10
     11        * rendering/SimpleLineLayoutFunctions.cpp:
     12        (WebCore::SimpleLineLayout::paintFlow):
     13       
     14            Iterate over the run range that needs painting.
     15
     16        (WebCore::SimpleLineLayout::hitTestFlow):
     17       
     18            Iterate over the line range that needs painting.
     19
     20        * rendering/SimpleLineLayoutResolver.h:
     21        (WebCore::SimpleLineLayout::Range::Range):
     22        (WebCore::SimpleLineLayout::Range::begin):
     23        (WebCore::SimpleLineLayout::Range::end):
     24       
     25            Add Range type.
     26
     27        (WebCore::SimpleLineLayout::RunResolver::Iterator::Iterator):
     28        (WebCore::SimpleLineLayout::RunResolver::Iterator::operator++):
     29        (WebCore::SimpleLineLayout::RunResolver::Iterator::advance):
     30        (WebCore::SimpleLineLayout::RunResolver::Iterator::advanceLines):
     31       
     32            Optimize case where runCount==lineCount. In this case we can just directly jump
     33            to the right run/line.
     34
     35        (WebCore::SimpleLineLayout::RunResolver::begin):
     36        (WebCore::SimpleLineLayout::RunResolver::end):
     37        (WebCore::SimpleLineLayout::RunResolver::lineIndexForHeight):
     38        (WebCore::SimpleLineLayout::RunResolver::rangeForRect):
     39       
     40            Get the range corresponding to a rect. This currently cares about y coordinates only.
     41
     42        (WebCore::SimpleLineLayout::LineResolver::Iterator::operator++):
     43        (WebCore::SimpleLineLayout::LineResolver::Iterator::operator*):
     44        (WebCore::SimpleLineLayout::LineResolver::rangeForRect):
     45
    1462013-11-20  Antoine Quint  <graouts@apple.com>
    247
  • trunk/Source/WebCore/rendering/SimpleLineLayoutFunctions.cpp

    r159385 r159560  
    8282    updateGraphicsContext(context, textPaintStyle);
    8383
     84    LayoutRect paintRect = paintInfo.rect;
     85    paintRect.moveBy(-paintOffset);
     86
    8487    auto resolver = runResolver(flow, layout);
    85     for (auto it = resolver.begin(), end = resolver.end(); it != end; ++it) {
    86         auto run = *it;
     88    auto range = resolver.rangeForRect(paintRect);
     89    for (auto it = range.begin(), end = range.end(); it != end; ++it) {
     90        const auto& run = *it;
     91        if (!run.rect().intersects(paintRect))
     92            continue;
    8793        TextRun textRun(run.text());
    8894        textRun.setTabSize(!style.collapseWhiteSpace(), style.tabSize());
     
    107113    RenderText& textRenderer = toRenderText(*flow.firstChild());
    108114
     115    LayoutRect rangeRect = locationInContainer.boundingBox();
     116    rangeRect.moveBy(-accumulatedOffset);
     117
    109118    auto resolver = lineResolver(flow, layout);
    110     for (auto it = resolver.begin(), end = resolver.end(); it != end; ++it) {
     119    auto range = resolver.rangeForRect(rangeRect);
     120    for (auto it = range.begin(), end = range.end(); it != end; ++it) {
    111121        auto lineRect = *it;
    112122        lineRect.moveBy(accumulatedOffset);
     
    163173    auto resolver = runResolver(toRenderBlockFlow(*textRenderer.parent()), layout);
    164174    for (auto it = resolver.begin(), end = resolver.end(); it != end; ++it) {
    165         auto run = *it;
     175        const auto& run = *it;
    166176        auto rect = run.rect();
    167177        rects.append(enclosingIntRect(FloatRect(accumulatedOffset + rect.location(), rect.size())));
     
    175185    auto resolver = runResolver(toRenderBlockFlow(*textRenderer.parent()), layout);
    176186    for (auto it = resolver.begin(), end = resolver.end(); it != end; ++it) {
    177         auto run = *it;
     187        const auto& run = *it;
    178188        auto rect = run.rect();
    179189        quads.append(textRenderer.localToAbsoluteQuad(FloatQuad(rect), 0, wasFixed));
  • trunk/Source/WebCore/rendering/SimpleLineLayoutResolver.h

    r159345 r159560  
    3737namespace SimpleLineLayout {
    3838
     39template <class IteratorType>
     40class Range {
     41public:
     42    Range(IteratorType begin, IteratorType end) : m_begin(begin), m_end(end) { }
     43
     44    IteratorType begin() const { return m_begin; }
     45    IteratorType end() const { return m_end; }
     46
     47private:
     48    IteratorType m_begin;
     49    IteratorType m_end;
     50};
     51
    3952class RunResolver {
    4053public:
     
    6073    class Iterator {
    6174    public:
    62         Iterator(const RunResolver&, unsigned lineIndex);
     75        Iterator(const RunResolver&, unsigned runIndex, unsigned lineIndex);
    6376
    6477        Iterator& operator++();
     78
    6579        bool operator==(const Iterator&) const;
    6680        bool operator!=(const Iterator&) const;
    6781
    6882        Run operator*() const;
     83
     84        Iterator& advance();
     85        Iterator& advanceLines(unsigned);
    6986
    7087        const RunResolver& resolver() const { return m_resolver; }
     
    83100    Iterator end() const;
    84101
     102    Range<Iterator> rangeForRect(const LayoutRect&) const;
     103
    85104private:
     105    unsigned lineIndexForHeight(LayoutUnit) const;
     106
    86107    const Layout& m_layout;
    87108    const String m_string;
     
    117138    Iterator end() const;
    118139
     140    Range<Iterator> rangeForRect(const LayoutRect&) const;
     141
    119142private:
    120143    RunResolver m_runResolver;
     
    170193}
    171194
    172 inline RunResolver::Iterator::Iterator(const RunResolver& resolver, unsigned runIndex)
     195inline RunResolver::Iterator::Iterator(const RunResolver& resolver, unsigned runIndex, unsigned lineIndex)
    173196    : m_resolver(resolver)
    174197    , m_runIndex(runIndex)
    175     , m_lineIndex(0)
     198    , m_lineIndex(lineIndex)
    176199{
    177200}
    178201
    179202inline RunResolver::Iterator& RunResolver::Iterator::operator++()
     203{
     204    return advance();
     205}
     206
     207inline bool RunResolver::Iterator::operator==(const Iterator& other) const
     208{
     209    ASSERT(&m_resolver == &other.m_resolver);
     210    return m_runIndex == other.m_runIndex;
     211}
     212
     213inline bool RunResolver::Iterator::operator!=(const Iterator& other) const
     214{
     215    return !(*this == other);
     216}
     217
     218inline RunResolver::Run RunResolver::Iterator::operator*() const
     219{
     220    return Run(*this);
     221}
     222
     223inline RunResolver::Iterator& RunResolver::Iterator::advance()
    180224{
    181225    if (simpleRun().isEndOfLine)
     
    185229}
    186230
    187 inline bool RunResolver::Iterator::operator==(const Iterator& other) const
    188 {
    189     ASSERT(&m_resolver == &other.m_resolver);
    190     return m_runIndex == other.m_runIndex;
    191 }
    192 
    193 inline bool RunResolver::Iterator::operator!=(const Iterator& other) const
    194 {
    195     return !(*this == other);
    196 }
    197 
    198 inline RunResolver::Run RunResolver::Iterator::operator*() const
    199 {
    200     return Run(*this);
     231inline RunResolver::Iterator& RunResolver::Iterator::advanceLines(unsigned lineCount)
     232{
     233    unsigned runCount = m_resolver.m_layout.runCount();
     234    if (runCount == m_resolver.m_layout.lineCount()) {
     235        m_runIndex = std::min(runCount, m_runIndex + lineCount);
     236        m_lineIndex = m_runIndex;
     237        return *this;
     238    }
     239    unsigned target = m_lineIndex + lineCount;
     240    while (m_lineIndex < target && m_runIndex < runCount)
     241        advance();
     242
     243    return *this;
    201244}
    202245
     
    219262inline RunResolver::Iterator RunResolver::begin() const
    220263{
    221     return Iterator(*this, 0);
     264    return Iterator(*this, 0, 0);
    222265}
    223266
    224267inline RunResolver::Iterator RunResolver::end() const
    225268{
    226     return Iterator(*this, m_layout.runCount());
     269    return Iterator(*this, m_layout.runCount(), m_layout.lineCount());
     270}
     271
     272inline unsigned RunResolver::lineIndexForHeight(LayoutUnit height) const
     273{
     274    ASSERT(m_lineHeight);
     275    float y = std::max<float>(height - m_contentOffset.y() - m_baseline + m_ascent, 0);
     276    return std::min<unsigned>(y / m_lineHeight, m_layout.lineCount() - 1);
     277}
     278
     279inline Range<RunResolver::Iterator> RunResolver::rangeForRect(const LayoutRect& rect) const
     280{
     281    if (!m_lineHeight)
     282        return Range<Iterator>(begin(), end());
     283
     284    unsigned firstLine = lineIndexForHeight(rect.y());
     285    unsigned lastLine = lineIndexForHeight(rect.maxY());
     286
     287    auto rangeBegin = begin().advanceLines(firstLine);
     288    if (rangeBegin == end())
     289        return Range<Iterator>(end(), end());
     290    auto rangeEnd = rangeBegin;
     291    rangeEnd.advanceLines(lastLine - firstLine + 1);
     292    return Range<Iterator>(rangeBegin, rangeEnd);
    227293}
    228294
     
    234300inline LineResolver::Iterator& LineResolver::Iterator::operator++()
    235301{
    236     unsigned previousLine = m_runIterator.lineIndex();
    237     while ((++m_runIterator).lineIndex() == previousLine) { }
    238 
     302    m_runIterator.advanceLines(1);
    239303    return *this;
    240304}
     
    255319    auto it = m_runIterator;
    256320    LayoutRect rect = (*it).rect();
    257     while ((++it).lineIndex() == currentLine)
     321    while (it.advance().lineIndex() == currentLine)
    258322        rect.unite((*it).rect());
    259323
     
    276340}
    277341
     342inline Range<LineResolver::Iterator> LineResolver::rangeForRect(const LayoutRect& rect) const
     343{
     344    auto runRange = m_runResolver.rangeForRect(rect);
     345    return Range<Iterator>(Iterator(runRange.begin()), Iterator(runRange.end()));
     346}
     347
    278348inline RunResolver runResolver(const RenderBlockFlow& flow, const Layout& layout)
    279349{
Note: See TracChangeset for help on using the changeset viewer.