Changeset 149007 in webkit


Ignore:
Timestamp:
Apr 23, 2013 5:18:27 PM (11 years ago)
Author:
rniwa@webkit.org
Message:

logicalLeftSelectionGap and logicalRightSelectionGap call availableLogicalWidth() multiple times
https://bugs.webkit.org/show_bug.cgi?id=113479

Reviewed by David Hyatt.

Introduced LogicalSelectionOffsetCaches to cache the containing blocks and their logical left and right
selection offsets in computing selection gaps. An instance of this class stores the containing block for
each position type and caches their logical selection offsets when none of their block ancestors up until
its nearest selection root do no have any floating objects or regions and exclusions.

When blockSelectionGaps recurses to another level, it creates a new cache instance by "inheriting"
(like RenderStyle) from the old cache, overriding those containing blocks that are replaced by "this".

This eliminates the need to traverse containing block ancestors in RenderBlock::logicalLeftSelectionOffset
and RenderBlock::logicalRightSelectionOffset, and improves WebKit's performance by roughly 20%.

Performance Tests: Interactive/SelectAll.html

  • GNUmakefile.list.am:
  • Target.pri:
  • WebCore.xcodeproj/project.pbxproj:
  • rendering/LogicalSelectionOffsetCaches.h: Added.

(WebCore::isContainingBlockCandidateForAbsolutelyPositionedObject): Moved from RenderObject.h.
(WebCore::isNonRenderBlockInline): Ditto.
(WebCore::containingBlockForFixedPosition): Extracted from RenderObject::containingBlock.
(WebCore::containingBlockForAbsolutePosition): Ditto.
(WebCore::containingBlockForObjectInFlow): Ditto.

(WebCore::LogicalSelectionOffsetCaches): Added.
(WebCore::LogicalSelectionOffsetCaches::ContainingBlockInfo::ContainingBlockInfo): Added.
(WebCore::LogicalSelectionOffsetCaches::ContainingBlockInfo::setBlock): Added. m_hasFloatsOrRegions is
or'ed with itself when ContainingBlockInfo is copy constructed since m_hasFloatsOrRegions needs be true
for a block when any of its containing block ancestors have floats or regions.
(WebCore::LogicalSelectionOffsetCaches::ContainingBlockInfo::block): Added.
(WebCore::LogicalSelectionOffsetCaches::ContainingBlockInfo::cache): Added.
(WebCore::LogicalSelectionOffsetCaches::ContainingBlockInfo::logicalLeftSelectionOffset): Added. Caches
the logical selection offset if it hasn't.
(WebCore::LogicalSelectionOffsetCaches::ContainingBlockInfo::logicalRightSelectionOffset): Ditto.

(WebCore::LogicalSelectionOffsetCaches::LogicalSelectionOffsetCaches): The first constructor is used
for a selection root. The second one is used for inheriting from another cache. In the latter case,
copy all containing block information except ones that need to be overridden by this block.
(WebCore::LogicalSelectionOffsetCaches::containingBlockInfo): Returns a ContainingBlockInfo based on
object's position value.

  • rendering/RenderBlock.cpp:

(WebCore::RenderBlock::selectionGapRectsForRepaint):
(WebCore::RenderBlock::paintSelection):
(WebCore::RenderBlock::selectionGaps):
(WebCore::RenderBlock::inlineSelectionGaps):
(WebCore::RenderBlock::blockSelectionGaps): Exit before instantiating a new LogicalSelectionOffsetCaches
if there is no child to recurse.
(WebCore::RenderBlock::blockSelectionGap):
(WebCore::RenderBlock::logicalLeftSelectionGap):
(WebCore::RenderBlock::logicalRightSelectionGap):
(WebCore::RenderBlock::logicalLeftSelectionOffset): Use LogicalSelectionOffsetCaches to get its containing
block and its logical selection offset.
(WebCore::RenderBlock::logicalRightSelectionOffset): Ditto.

  • rendering/RenderBlock.h:

(WebCore::RenderBlock):

  • rendering/RenderObject.cpp:

(WebCore::RenderObject::containingBlock): Extracted code into LogicalSelectionOffsetCaches.h.

  • rendering/RootInlineBox.cpp:

(WebCore::RootInlineBox::lineSelectionGap):

  • rendering/RootInlineBox.h:

(WebCore::RootInlineBox):

Location:
trunk/Source/WebCore
Files:
1 added
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r149005 r149007  
     12013-04-22  Ryosuke Niwa  <rniwa@webkit.org>
     2
     3        logicalLeftSelectionGap and logicalRightSelectionGap call availableLogicalWidth() multiple times
     4        https://bugs.webkit.org/show_bug.cgi?id=113479
     5
     6        Reviewed by David Hyatt.
     7
     8        Introduced LogicalSelectionOffsetCaches to cache the containing blocks and their logical left and right
     9        selection offsets in computing selection gaps. An instance of this class stores the containing block for
     10        each position type and caches their logical selection offsets when none of their block ancestors up until
     11        its nearest selection root do no have any floating objects or regions and exclusions.
     12
     13        When blockSelectionGaps recurses to another level, it creates a new cache instance by "inheriting"
     14        (like RenderStyle) from the old cache, overriding those containing blocks that are replaced by "this".
     15
     16        This eliminates the need to traverse containing block ancestors in RenderBlock::logicalLeftSelectionOffset
     17        and RenderBlock::logicalRightSelectionOffset, and improves WebKit's performance by roughly 20%.
     18
     19        Performance Tests: Interactive/SelectAll.html
     20
     21        * GNUmakefile.list.am:
     22        * Target.pri:
     23        * WebCore.xcodeproj/project.pbxproj:
     24
     25        * rendering/LogicalSelectionOffsetCaches.h: Added.
     26        (WebCore::isContainingBlockCandidateForAbsolutelyPositionedObject): Moved from RenderObject.h.
     27        (WebCore::isNonRenderBlockInline): Ditto.
     28        (WebCore::containingBlockForFixedPosition): Extracted from RenderObject::containingBlock.
     29        (WebCore::containingBlockForAbsolutePosition): Ditto.
     30        (WebCore::containingBlockForObjectInFlow): Ditto.
     31
     32        (WebCore::LogicalSelectionOffsetCaches): Added.
     33        (WebCore::LogicalSelectionOffsetCaches::ContainingBlockInfo::ContainingBlockInfo): Added.
     34        (WebCore::LogicalSelectionOffsetCaches::ContainingBlockInfo::setBlock): Added. m_hasFloatsOrRegions is
     35        or'ed with itself when ContainingBlockInfo is copy constructed since m_hasFloatsOrRegions needs be true
     36        for a block when any of its containing block ancestors have floats or regions.
     37        (WebCore::LogicalSelectionOffsetCaches::ContainingBlockInfo::block): Added.
     38        (WebCore::LogicalSelectionOffsetCaches::ContainingBlockInfo::cache): Added.
     39        (WebCore::LogicalSelectionOffsetCaches::ContainingBlockInfo::logicalLeftSelectionOffset): Added. Caches
     40        the logical selection offset if it hasn't.
     41        (WebCore::LogicalSelectionOffsetCaches::ContainingBlockInfo::logicalRightSelectionOffset): Ditto.
     42
     43        (WebCore::LogicalSelectionOffsetCaches::LogicalSelectionOffsetCaches): The first constructor is used
     44        for a selection root. The second one is used for inheriting from another cache. In the latter case,
     45        copy all containing block information except ones that need to be overridden by this block.
     46        (WebCore::LogicalSelectionOffsetCaches::containingBlockInfo): Returns a ContainingBlockInfo based on
     47        object's position value.
     48
     49        * rendering/RenderBlock.cpp:
     50        (WebCore::RenderBlock::selectionGapRectsForRepaint):
     51        (WebCore::RenderBlock::paintSelection):
     52        (WebCore::RenderBlock::selectionGaps):
     53        (WebCore::RenderBlock::inlineSelectionGaps):
     54        (WebCore::RenderBlock::blockSelectionGaps): Exit before instantiating a new LogicalSelectionOffsetCaches
     55        if there is no child to recurse.
     56        (WebCore::RenderBlock::blockSelectionGap):
     57        (WebCore::RenderBlock::logicalLeftSelectionGap):
     58        (WebCore::RenderBlock::logicalRightSelectionGap):
     59        (WebCore::RenderBlock::logicalLeftSelectionOffset): Use LogicalSelectionOffsetCaches to get its containing
     60        block and its logical selection offset.
     61        (WebCore::RenderBlock::logicalRightSelectionOffset): Ditto.
     62
     63        * rendering/RenderBlock.h:
     64        (WebCore::RenderBlock):
     65
     66        * rendering/RenderObject.cpp:
     67        (WebCore::RenderObject::containingBlock): Extracted code into LogicalSelectionOffsetCaches.h.
     68
     69        * rendering/RootInlineBox.cpp:
     70        (WebCore::RootInlineBox::lineSelectionGap):
     71
     72        * rendering/RootInlineBox.h:
     73        (WebCore::RootInlineBox):
     74
    1752013-04-23  Eric Carlson  <eric.carlson@apple.com>
    276
  • trunk/Source/WebCore/GNUmakefile.list.am

    r148921 r149007  
    44414441        Source/WebCore/rendering/LayoutState.cpp \
    44424442        Source/WebCore/rendering/LayoutState.h \
     4443        Source/WebCore/rendering/LogicalSelectionOffsetCaches.h \
    44434444        Source/WebCore/rendering/LayoutRepainter.h \
    44444445        Source/WebCore/rendering/LayoutRepainter.cpp \
  • trunk/Source/WebCore/Target.pri

    r148921 r149007  
    24492449    rendering/InlineFlowBox.h \
    24502450    rendering/InlineTextBox.h \
     2451    rendering/LayoutRepainter.h \
    24512452    rendering/LayoutState.h \
    2452     rendering/LayoutRepainter.h \
     2453    rendering/LogicalSelectionOffsetCaches.h \
    24532454    rendering/mathml/RenderMathMLBlock.h \
    24542455    rendering/mathml/RenderMathMLFenced.h \
  • trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj

    r148921 r149007  
    33093309                9B7E78BD16F16CC600126914 /* HTMLTreeBuilderSimulator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B7E78BA16F16CAE00126914 /* HTMLTreeBuilderSimulator.cpp */; };
    33103310                9B7E78BE16F16CC800126914 /* HTMLTreeBuilderSimulator.h in Headers */ = {isa = PBXBuildFile; fileRef = 9B7E78BB16F16CAE00126914 /* HTMLTreeBuilderSimulator.h */; };
     3311                9BA273F4172206BB0097CE47 /* LogicalSelectionOffsetCaches.h in Headers */ = {isa = PBXBuildFile; fileRef = 9BA273F3172206BB0097CE47 /* LogicalSelectionOffsetCaches.h */; };
    33113312                9BAB6C6C12550631001626D4 /* EditingStyle.h in Headers */ = {isa = PBXBuildFile; fileRef = 9BAB6C6A12550631001626D4 /* EditingStyle.h */; settings = {ATTRIBUTES = (Private, ); }; };
    33123313                9BAB6C6D12550631001626D4 /* EditingStyle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9BAB6C6B12550631001626D4 /* EditingStyle.cpp */; };
     
    97859786                9B7E78BA16F16CAE00126914 /* HTMLTreeBuilderSimulator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = HTMLTreeBuilderSimulator.cpp; path = parser/HTMLTreeBuilderSimulator.cpp; sourceTree = "<group>"; };
    97869787                9B7E78BB16F16CAE00126914 /* HTMLTreeBuilderSimulator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HTMLTreeBuilderSimulator.h; path = parser/HTMLTreeBuilderSimulator.h; sourceTree = "<group>"; };
     9788                9BA273F3172206BB0097CE47 /* LogicalSelectionOffsetCaches.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LogicalSelectionOffsetCaches.h; sourceTree = "<group>"; };
    97879789                9BAB6C6A12550631001626D4 /* EditingStyle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EditingStyle.h; sourceTree = "<group>"; };
    97889790                9BAB6C6B12550631001626D4 /* EditingStyle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EditingStyle.cpp; sourceTree = "<group>"; };
     
    1260212604                FABE72FB1059C21100D999DD /* MathMLElementFactory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MathMLElementFactory.cpp; sourceTree = "<group>"; };
    1260312605                FABE72FC1059C21100D999DD /* MathMLNames.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MathMLNames.cpp; sourceTree = "<group>"; };
    12604                 FB1A66D917225A6600BAA7AF /* CustomFilterColorParameter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CustomFilterColorParameter.h; path = filters/CustomFilterColorParameter.h; sourceTree = "<group>"; };
    1260512606                FB0B75EE1723428500F05D2A /* WebKitCSSMatFunctionValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebKitCSSMatFunctionValue.cpp; sourceTree = "<group>"; };
    1260612607                FB0B75EF1723428500F05D2A /* WebKitCSSMatFunctionValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebKitCSSMatFunctionValue.h; sourceTree = "<group>"; };
     12608                FB1A66D917225A6600BAA7AF /* CustomFilterColorParameter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CustomFilterColorParameter.h; path = filters/CustomFilterColorParameter.h; sourceTree = "<group>"; };
    1260712609                FB2C15C2165D64900039C9F8 /* CachedSVGDocumentReference.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CachedSVGDocumentReference.h; sourceTree = "<group>"; };
    1260812610                FB3056C1169E5DAC0096A232 /* CSSGroupingRule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSGroupingRule.h; sourceTree = "<group>"; };
     
    2002320025                                2D9066040BE141D400956998 /* LayoutState.cpp */,
    2002420026                                2D9066050BE141D400956998 /* LayoutState.h */,
     20027                                9BA273F3172206BB0097CE47 /* LogicalSelectionOffsetCaches.h */,
    2002520028                                3774ABA30FA21EB400AD7DE9 /* OverlapTestRequestClient.h */,
    2002620029                                9377AB9F15DEFEEF0031FD04 /* Pagination.h */,
     
    2288422887                                BCE1C41B0D982980003B02F2 /* Location.h in Headers */,
    2288522888                                A8239E0109B3CF8A00B60641 /* Logging.h in Headers */,
     22889                                9BA273F4172206BB0097CE47 /* LogicalSelectionOffsetCaches.h in Headers */,
    2288622890                                E187056316E54A0D00585E97 /* MainThreadTask.h in Headers */,
    2288722891                                1A8F6BC60DB55CDC001DB794 /* ManifestParser.h in Headers */,
  • trunk/Source/WebCore/rendering/RenderBlock.cpp

    r148921 r149007  
    4242#include "InlineTextBox.h"
    4343#include "LayoutRepainter.h"
     44#include "LogicalSelectionOffsetCaches.h"
    4445#include "OverflowEvent.h"
    4546#include "PODFreeListArena.h"
     
    33983399        offsetFromRepaintContainer -= scrolledContentOffset();
    33993400
     3401    LogicalSelectionOffsetCaches cache(this);
    34003402    LayoutUnit lastTop = 0;
    3401     LayoutUnit lastLeft = logicalLeftSelectionOffset(this, lastTop);
    3402     LayoutUnit lastRight = logicalRightSelectionOffset(this, lastTop);
    3403    
    3404     return selectionGaps(this, offsetFromRepaintContainer, IntSize(), lastTop, lastLeft, lastRight);
     3403    LayoutUnit lastLeft = logicalLeftSelectionOffset(this, lastTop, cache);
     3404    LayoutUnit lastRight = logicalRightSelectionOffset(this, lastTop, cache);
     3405   
     3406    return selectionGaps(this, offsetFromRepaintContainer, IntSize(), lastTop, lastLeft, lastRight, cache);
    34053407}
    34063408
     
    34083410{
    34093411    if (shouldPaintSelectionGaps() && paintInfo.phase == PaintPhaseForeground) {
     3412        LogicalSelectionOffsetCaches cache(this);
    34103413        LayoutUnit lastTop = 0;
    3411         LayoutUnit lastLeft = logicalLeftSelectionOffset(this, lastTop);
    3412         LayoutUnit lastRight = logicalRightSelectionOffset(this, lastTop);
     3414        LayoutUnit lastLeft = logicalLeftSelectionOffset(this, lastTop, cache);
     3415        LayoutUnit lastRight = logicalRightSelectionOffset(this, lastTop, cache);
    34133416        GraphicsContextStateSaver stateSaver(*paintInfo.context);
    34143417
    3415         LayoutRect gapRectsBounds = selectionGaps(this, paintOffset, LayoutSize(), lastTop, lastLeft, lastRight, &paintInfo);
     3418        LayoutRect gapRectsBounds = selectionGaps(this, paintOffset, LayoutSize(), lastTop, lastLeft, lastRight, cache, &paintInfo);
    34163419        if (!gapRectsBounds.isEmpty()) {
    34173420            if (RenderLayer* layer = enclosingLayer()) {
     
    34653468
    34663469GapRects RenderBlock::selectionGaps(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
    3467                                     LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const PaintInfo* paintInfo)
     3470    LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const LogicalSelectionOffsetCaches& cache, const PaintInfo* paintInfo)
    34683471{
    34693472    // IMPORTANT: Callers of this method that intend for painting to happen need to do a save/restore.
     
    35023505        // FIXME: We should learn how to gap fill multiple columns and transforms eventually.
    35033506        lastLogicalTop = blockDirectionOffset(rootBlock, offsetFromRootBlock) + logicalHeight();
    3504         lastLogicalLeft = logicalLeftSelectionOffset(rootBlock, logicalHeight());
    3505         lastLogicalRight = logicalRightSelectionOffset(rootBlock, logicalHeight());
     3507        lastLogicalLeft = logicalLeftSelectionOffset(rootBlock, logicalHeight(), cache);
     3508        lastLogicalRight = logicalRightSelectionOffset(rootBlock, logicalHeight(), cache);
    35063509        return result;
    35073510    }
    35083511
    35093512    if (childrenInline())
    3510         result = inlineSelectionGaps(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, lastLogicalTop, lastLogicalLeft, lastLogicalRight, paintInfo);
     3513        result = inlineSelectionGaps(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, lastLogicalTop, lastLogicalLeft, lastLogicalRight, cache, paintInfo);
    35113514    else
    3512         result = blockSelectionGaps(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, lastLogicalTop, lastLogicalLeft, lastLogicalRight, paintInfo);
     3515        result = blockSelectionGaps(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, lastLogicalTop, lastLogicalLeft, lastLogicalRight, cache, paintInfo);
    35133516
    35143517    // Go ahead and fill the vertical gap all the way to the bottom of our block if the selection extends past our block.
    3515     if (rootBlock == this && (selectionState() != SelectionBoth && selectionState() != SelectionEnd))
    3516         result.uniteCenter(blockSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, lastLogicalTop, lastLogicalLeft, lastLogicalRight,
    3517                                              logicalHeight(), paintInfo));
     3518    if (rootBlock == this && (selectionState() != SelectionBoth && selectionState() != SelectionEnd)) {
     3519        result.uniteCenter(blockSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock,
     3520            lastLogicalTop, lastLogicalLeft, lastLogicalRight, logicalHeight(), cache, paintInfo));
     3521    }
     3522
    35183523    return result;
    35193524}
    35203525
    35213526GapRects RenderBlock::inlineSelectionGaps(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
    3522                                           LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const PaintInfo* paintInfo)
     3527    LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const LogicalSelectionOffsetCaches& cache, const PaintInfo* paintInfo)
    35233528{
    35243529    GapRects result;
     
    35313536            // case.
    35323537            lastLogicalTop = blockDirectionOffset(rootBlock, offsetFromRootBlock) + logicalHeight();
    3533             lastLogicalLeft = logicalLeftSelectionOffset(rootBlock, logicalHeight());
    3534             lastLogicalRight = logicalRightSelectionOffset(rootBlock, logicalHeight());
     3538            lastLogicalLeft = logicalLeftSelectionOffset(rootBlock, logicalHeight(), cache);
     3539            lastLogicalRight = logicalRightSelectionOffset(rootBlock, logicalHeight(), cache);
    35353540        }
    35363541        return result;
     
    35483553        if (!containsStart && !lastSelectedLine &&
    35493554            selectionState() != SelectionStart && selectionState() != SelectionBoth)
    3550             result.uniteCenter(blockSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, lastLogicalTop, lastLogicalLeft, lastLogicalRight,
    3551                                                  selTop, paintInfo));
     3555            result.uniteCenter(blockSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, lastLogicalTop, lastLogicalLeft, lastLogicalRight, selTop, cache, paintInfo));
    35523556       
    35533557        LayoutRect logicalRect(curr->logicalLeft(), selTop, curr->logicalWidth(), selTop + selHeight);
     
    35563560        if (!paintInfo || (isHorizontalWritingMode() && physicalRect.y() < paintInfo->rect.maxY() && physicalRect.maxY() > paintInfo->rect.y())
    35573561            || (!isHorizontalWritingMode() && physicalRect.x() < paintInfo->rect.maxX() && physicalRect.maxX() > paintInfo->rect.x()))
    3558             result.unite(curr->lineSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, selTop, selHeight, paintInfo));
     3562            result.unite(curr->lineSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, selTop, selHeight, cache, paintInfo));
    35593563
    35603564        lastSelectedLine = curr;
     
    35683572        // Go ahead and update our lastY to be the bottom of the last selected line.
    35693573        lastLogicalTop = blockDirectionOffset(rootBlock, offsetFromRootBlock) + lastSelectedLine->selectionBottom();
    3570         lastLogicalLeft = logicalLeftSelectionOffset(rootBlock, lastSelectedLine->selectionBottom());
    3571         lastLogicalRight = logicalRightSelectionOffset(rootBlock, lastSelectedLine->selectionBottom());
     3574        lastLogicalLeft = logicalLeftSelectionOffset(rootBlock, lastSelectedLine->selectionBottom(), cache);
     3575        lastLogicalRight = logicalRightSelectionOffset(rootBlock, lastSelectedLine->selectionBottom(), cache);
    35723576    }
    35733577    return result;
     
    35753579
    35763580GapRects RenderBlock::blockSelectionGaps(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
    3577                                          LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const PaintInfo* paintInfo)
     3581    LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const LogicalSelectionOffsetCaches& cache, const PaintInfo* paintInfo)
    35783582{
    35793583    GapRects result;
     
    35823586    RenderBox* curr;
    35833587    for (curr = firstChildBox(); curr && curr->selectionState() == SelectionNone; curr = curr->nextSiblingBox()) { }
     3588   
     3589    if (!curr)
     3590        return result;
     3591
     3592    LogicalSelectionOffsetCaches childCache(this, cache);
    35843593
    35853594    for (bool sawSelectionEnd = false; curr && !sawSelectionEnd; curr = curr->nextSiblingBox()) {
     
    36033612        if (fillBlockGaps) {
    36043613            // We need to fill the vertical gap above this object.
    3605             if (childState == SelectionEnd || childState == SelectionInside)
     3614            if (childState == SelectionEnd || childState == SelectionInside) {
    36063615                // Fill the gap above the object.
    3607                 result.uniteCenter(blockSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, lastLogicalTop, lastLogicalLeft, lastLogicalRight,
    3608                                                      curr->logicalTop(), paintInfo));
     3616                result.uniteCenter(blockSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock,
     3617                    lastLogicalTop, lastLogicalLeft, lastLogicalRight, curr->logicalTop(), cache, paintInfo));
     3618            }
    36093619
    36103620            // Only fill side gaps for objects that paint their own selection if we know for sure the selection is going to extend all the way *past*
     
    36183628
    36193629            if (leftGap)
    3620                 result.uniteLeft(logicalLeftSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, this, curr->logicalLeft(), curr->logicalTop(), curr->logicalHeight(), paintInfo));
     3630                result.uniteLeft(logicalLeftSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, this, curr->logicalLeft(), curr->logicalTop(), curr->logicalHeight(), cache, paintInfo));
    36213631            if (rightGap)
    3622                 result.uniteRight(logicalRightSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, this, curr->logicalRight(), curr->logicalTop(), curr->logicalHeight(), paintInfo));
     3632                result.uniteRight(logicalRightSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, this, curr->logicalRight(), curr->logicalTop(), curr->logicalHeight(), cache, paintInfo));
    36233633
    36243634            // Update lastLogicalTop to be just underneath the object.  lastLogicalLeft and lastLogicalRight extend as far as
     
    36263636            // to the border of the root selection block.
    36273637            lastLogicalTop = blockDirectionOffset(rootBlock, offsetFromRootBlock) + curr->logicalBottom();
    3628             lastLogicalLeft = logicalLeftSelectionOffset(rootBlock, curr->logicalBottom());
    3629             lastLogicalRight = logicalRightSelectionOffset(rootBlock, curr->logicalBottom());
    3630         } else if (childState != SelectionNone)
     3638            lastLogicalLeft = logicalLeftSelectionOffset(rootBlock, curr->logicalBottom(), cache);
     3639            lastLogicalRight = logicalRightSelectionOffset(rootBlock, curr->logicalBottom(), cache);
     3640        } else if (childState != SelectionNone) {
    36313641            // We must be a block that has some selected object inside it.  Go ahead and recur.
    36323642            result.unite(toRenderBlock(curr)->selectionGaps(rootBlock, rootBlockPhysicalPosition, LayoutSize(offsetFromRootBlock.width() + curr->x(), offsetFromRootBlock.height() + curr->y()),
    3633                                                             lastLogicalTop, lastLogicalLeft, lastLogicalRight, paintInfo));
     3643                lastLogicalTop, lastLogicalLeft, lastLogicalRight, childCache, paintInfo));
     3644        }
    36343645    }
    36353646    return result;
     
    36373648
    36383649LayoutRect RenderBlock::blockSelectionGap(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
    3639                                           LayoutUnit lastLogicalTop, LayoutUnit lastLogicalLeft, LayoutUnit lastLogicalRight, LayoutUnit logicalBottom, const PaintInfo* paintInfo)
     3650    LayoutUnit lastLogicalTop, LayoutUnit lastLogicalLeft, LayoutUnit lastLogicalRight, LayoutUnit logicalBottom, const LogicalSelectionOffsetCaches& cache, const PaintInfo* paintInfo)
    36403651{
    36413652    LayoutUnit logicalTop = lastLogicalTop;
     
    36453656
    36463657    // Get the selection offsets for the bottom of the gap
    3647     LayoutUnit logicalLeft = max(lastLogicalLeft, logicalLeftSelectionOffset(rootBlock, logicalBottom));
    3648     LayoutUnit logicalRight = min(lastLogicalRight, logicalRightSelectionOffset(rootBlock, logicalBottom));
     3658    LayoutUnit logicalLeft = max(lastLogicalLeft, logicalLeftSelectionOffset(rootBlock, logicalBottom, cache));
     3659    LayoutUnit logicalRight = min(lastLogicalRight, logicalRightSelectionOffset(rootBlock, logicalBottom, cache));
    36493660    LayoutUnit logicalWidth = logicalRight - logicalLeft;
    36503661    if (logicalWidth <= 0)
     
    36583669
    36593670LayoutRect RenderBlock::logicalLeftSelectionGap(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
    3660                                                 RenderObject* selObj, LayoutUnit logicalLeft, LayoutUnit logicalTop, LayoutUnit logicalHeight, const PaintInfo* paintInfo)
     3671    RenderObject* selObj, LayoutUnit logicalLeft, LayoutUnit logicalTop, LayoutUnit logicalHeight, const LogicalSelectionOffsetCaches& cache, const PaintInfo* paintInfo)
    36613672{
    36623673    LayoutUnit rootBlockLogicalTop = blockDirectionOffset(rootBlock, offsetFromRootBlock) + logicalTop;
    3663     LayoutUnit rootBlockLogicalLeft = max(logicalLeftSelectionOffset(rootBlock, logicalTop), logicalLeftSelectionOffset(rootBlock, logicalTop + logicalHeight));
    3664     LayoutUnit rootBlockLogicalRight = min(inlineDirectionOffset(rootBlock, offsetFromRootBlock) + floorToInt(logicalLeft), min(logicalRightSelectionOffset(rootBlock, logicalTop), logicalRightSelectionOffset(rootBlock, logicalTop + logicalHeight)));
     3674    LayoutUnit rootBlockLogicalLeft = max(logicalLeftSelectionOffset(rootBlock, logicalTop, cache), logicalLeftSelectionOffset(rootBlock, logicalTop + logicalHeight, cache));
     3675    LayoutUnit rootBlockLogicalRight = min(inlineDirectionOffset(rootBlock, offsetFromRootBlock) + floorToInt(logicalLeft),
     3676        min(logicalRightSelectionOffset(rootBlock, logicalTop, cache), logicalRightSelectionOffset(rootBlock, logicalTop + logicalHeight, cache)));
    36653677    LayoutUnit rootBlockLogicalWidth = rootBlockLogicalRight - rootBlockLogicalLeft;
    36663678    if (rootBlockLogicalWidth <= 0)
     
    36743686
    36753687LayoutRect RenderBlock::logicalRightSelectionGap(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
    3676                                                  RenderObject* selObj, LayoutUnit logicalRight, LayoutUnit logicalTop, LayoutUnit logicalHeight, const PaintInfo* paintInfo)
     3688    RenderObject* selObj, LayoutUnit logicalRight, LayoutUnit logicalTop, LayoutUnit logicalHeight, const LogicalSelectionOffsetCaches& cache, const PaintInfo* paintInfo)
    36773689{
    36783690    LayoutUnit rootBlockLogicalTop = blockDirectionOffset(rootBlock, offsetFromRootBlock) + logicalTop;
    3679     LayoutUnit rootBlockLogicalLeft = max(inlineDirectionOffset(rootBlock, offsetFromRootBlock) + floorToInt(logicalRight), max(logicalLeftSelectionOffset(rootBlock, logicalTop), logicalLeftSelectionOffset(rootBlock, logicalTop + logicalHeight)));
    3680     LayoutUnit rootBlockLogicalRight = min(logicalRightSelectionOffset(rootBlock, logicalTop), logicalRightSelectionOffset(rootBlock, logicalTop + logicalHeight));
     3691    LayoutUnit rootBlockLogicalLeft = max(inlineDirectionOffset(rootBlock, offsetFromRootBlock) + floorToInt(logicalRight),
     3692        max(logicalLeftSelectionOffset(rootBlock, logicalTop, cache), logicalLeftSelectionOffset(rootBlock, logicalTop + logicalHeight, cache)));
     3693    LayoutUnit rootBlockLogicalRight = min(logicalRightSelectionOffset(rootBlock, logicalTop, cache), logicalRightSelectionOffset(rootBlock, logicalTop + logicalHeight, cache));
    36813694    LayoutUnit rootBlockLogicalWidth = rootBlockLogicalRight - rootBlockLogicalLeft;
    36823695    if (rootBlockLogicalWidth <= 0)
     
    37003713}
    37013714
    3702 LayoutUnit RenderBlock::logicalLeftSelectionOffset(RenderBlock* rootBlock, LayoutUnit position)
     3715LayoutUnit RenderBlock::logicalLeftSelectionOffset(RenderBlock* rootBlock, LayoutUnit position, const LogicalSelectionOffsetCaches& cache)
    37033716{
    37043717    LayoutUnit logicalLeft = logicalLeftOffsetForLine(position, false);
    37053718    if (logicalLeft == logicalLeftOffsetForContent()) {
    3706         if (rootBlock != this)
    3707             // The border can potentially be further extended by our containingBlock().
    3708             return containingBlock()->logicalLeftSelectionOffset(rootBlock, position + logicalTop());
     3719        if (rootBlock != this) // The border can potentially be further extended by our containingBlock().
     3720            return cache.containingBlockInfo(this).logicalLeftSelectionOffset(rootBlock, position + logicalTop());
    37093721        return logicalLeft;
    37103722    } else {
    37113723        RenderBlock* cb = this;
     3724        const LogicalSelectionOffsetCaches* currentCache = &cache;
    37123725        while (cb != rootBlock) {
    37133726            logicalLeft += cb->logicalLeft();
    3714             cb = cb->containingBlock();
     3727
     3728            ASSERT(currentCache);
     3729            const LogicalSelectionOffsetCaches::ContainingBlockInfo& info = currentCache->containingBlockInfo(cb);
     3730            cb = info.block();
     3731            currentCache = info.cache();
    37153732        }
    37163733    }
     
    37183735}
    37193736
    3720 LayoutUnit RenderBlock::logicalRightSelectionOffset(RenderBlock* rootBlock, LayoutUnit position)
     3737LayoutUnit RenderBlock::logicalRightSelectionOffset(RenderBlock* rootBlock, LayoutUnit position, const LogicalSelectionOffsetCaches& cache)
    37213738{
    37223739    LayoutUnit logicalRight = logicalRightOffsetForLine(position, false);
    37233740    if (logicalRight == logicalRightOffsetForContent()) {
    3724         if (rootBlock != this)
    3725             // The border can potentially be further extended by our containingBlock().
    3726             return containingBlock()->logicalRightSelectionOffset(rootBlock, position + logicalTop());
     3741        if (rootBlock != this) // The border can potentially be further extended by our containingBlock().
     3742            return cache.containingBlockInfo(this).logicalRightSelectionOffset(rootBlock, position + logicalTop());
    37273743        return logicalRight;
    37283744    } else {
    37293745        RenderBlock* cb = this;
     3746        const LogicalSelectionOffsetCaches* currentCache = &cache;
    37303747        while (cb != rootBlock) {
    37313748            logicalRight += cb->logicalLeft();
    3732             cb = cb->containingBlock();
     3749
     3750            ASSERT(currentCache);
     3751            const LogicalSelectionOffsetCaches::ContainingBlockInfo& info = currentCache->containingBlockInfo(cb);
     3752            cb = info.block();
     3753            currentCache = info.cache();
    37333754        }
    37343755    }
  • trunk/Source/WebCore/rendering/RenderBlock.h

    r148921 r149007  
    4747class LineLayoutState;
    4848class LineWidth;
     49class LogicalSelectionOffsetCaches;
    4950class RenderInline;
    5051class RenderText;
     
    244245    GapRects selectionGapRectsForRepaint(const RenderLayerModelObject* repaintContainer);
    245246    LayoutRect logicalLeftSelectionGap(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
    246                                        RenderObject* selObj, LayoutUnit logicalLeft, LayoutUnit logicalTop, LayoutUnit logicalHeight, const PaintInfo*);
     247        RenderObject* selObj, LayoutUnit logicalLeft, LayoutUnit logicalTop, LayoutUnit logicalHeight, const LogicalSelectionOffsetCaches&, const PaintInfo*);
    247248    LayoutRect logicalRightSelectionGap(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
    248                                         RenderObject* selObj, LayoutUnit logicalRight, LayoutUnit logicalTop, LayoutUnit logicalHeight, const PaintInfo*);
     249        RenderObject* selObj, LayoutUnit logicalRight, LayoutUnit logicalTop, LayoutUnit logicalHeight, const LogicalSelectionOffsetCaches&, const PaintInfo*);
    249250    void getSelectionGapInfo(SelectionState, bool& leftGap, bool& rightGap);
    250251    RenderBlock* blockBeforeWithinSelectionRoot(LayoutSize& offset) const;
     
    926927    bool isSelectionRoot() const;
    927928    GapRects selectionGaps(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
    928                            LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const PaintInfo* = 0);
     929        LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const LogicalSelectionOffsetCaches&, const PaintInfo* = 0);
    929930    GapRects inlineSelectionGaps(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
    930                                  LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const PaintInfo*);
     931        LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const LogicalSelectionOffsetCaches&, const PaintInfo*);
    931932    GapRects blockSelectionGaps(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
    932                                 LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const PaintInfo*);
     933        LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const LogicalSelectionOffsetCaches&, const PaintInfo*);
    933934    LayoutRect blockSelectionGap(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
    934                                  LayoutUnit lastLogicalTop, LayoutUnit lastLogicalLeft, LayoutUnit lastLogicalRight, LayoutUnit logicalBottom, const PaintInfo*);
    935     LayoutUnit logicalLeftSelectionOffset(RenderBlock* rootBlock, LayoutUnit position);
    936     LayoutUnit logicalRightSelectionOffset(RenderBlock* rootBlock, LayoutUnit position);
     935        LayoutUnit lastLogicalTop, LayoutUnit lastLogicalLeft, LayoutUnit lastLogicalRight, LayoutUnit logicalBottom, const LogicalSelectionOffsetCaches&, const PaintInfo*);
     936    LayoutUnit logicalLeftSelectionOffset(RenderBlock* rootBlock, LayoutUnit position, const LogicalSelectionOffsetCaches&);
     937    LayoutUnit logicalRightSelectionOffset(RenderBlock* rootBlock, LayoutUnit position, const LogicalSelectionOffsetCaches&);
     938   
     939    friend class LogicalSelectionOffsetCaches;
    937940
    938941    virtual void absoluteRects(Vector<IntRect>&, const LayoutPoint& accumulatedOffset) const;
  • trunk/Source/WebCore/rendering/RenderObject.cpp

    r148921 r149007  
    4545#include "HTMLNames.h"
    4646#include "HitTestResult.h"
     47#include "LogicalSelectionOffsetCaches.h"
    4748#include "Page.h"
    4849#include "RenderArena.h"
     
    768769}
    769770
    770 static inline bool isContainingBlockCandidateForAbsolutelyPositionedObject(RenderObject* object)
    771 {
    772     return object->style()->position() != StaticPosition
    773         || (object->hasTransform() && object->isRenderBlock())
    774 #if ENABLE(SVG)
    775         || object->isSVGForeignObject()
    776 #endif
    777         || object->isRenderView();
    778 }
    779 
    780 static inline bool isNonRenderBlockInline(RenderObject* object)
    781 {
    782     return (object->isInline() && !object->isReplaced()) || !object->isRenderBlock();
    783 }
    784 
    785771RenderBlock* RenderObject::containingBlock() const
    786772{
     
    789775        o = toRenderScrollbarPart(this)->rendererOwningScrollbar();
    790776
    791     if (!isText() && m_style->position() == FixedPosition) {
    792         while (o && !o->canContainFixedPositionObjects())
    793             o = o->parent();
    794         ASSERT(!o || !o->isAnonymousBlock());
    795     } else if (!isText() && m_style->position() == AbsolutePosition) {
    796         while (o && !isContainingBlockCandidateForAbsolutelyPositionedObject(o))
    797             o = o->parent();
    798 
    799         // For a relatively positioned inline, return its nearest non-anonymous containing block,
    800         // not the inline itself, to avoid having a positioned objects list in all RenderInlines
    801         // and use RenderBlock* as this function's return type.
    802         // Use RenderBlock::container() to obtain the inline.
    803         if (o && o->isRenderInline())
    804             o = o->containingBlock();
    805 
    806         while (o && o->isAnonymousBlock())
    807             o = o->containingBlock();
    808     } else {
    809         while (o && isNonRenderBlockInline(o))
    810             o = o->parent();
    811     }
     777    if (!isText() && m_style->position() == FixedPosition)
     778        o = containingBlockForFixedPosition(o);
     779    else if (!isText() && m_style->position() == AbsolutePosition)
     780        o = containingBlockForAbsolutePosition(o);
     781    else
     782        o = containingBlockForObjectInFlow(o);
    812783
    813784    if (!o || !o->isRenderBlock())
  • trunk/Source/WebCore/rendering/RootInlineBox.cpp

    r146104 r149007  
    3030#include "HitTestResult.h"
    3131#include "InlineTextBox.h"
     32#include "LogicalSelectionOffsetCaches.h"
    3233#include "Page.h"
    3334#include "PaintInfo.h"
     
    467468}
    468469
    469 GapRects RootInlineBox::lineSelectionGap(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock, 
    470                                          LayoutUnit selTop, LayoutUnit selHeight, const PaintInfo* paintInfo)
     470GapRects RootInlineBox::lineSelectionGap(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
     471    LayoutUnit selTop, LayoutUnit selHeight, const LogicalSelectionOffsetCaches& cache, const PaintInfo* paintInfo)
    471472{
    472473    RenderObject::SelectionState lineState = selectionState();
     
    479480    InlineBox* firstBox = firstSelectedBox();
    480481    InlineBox* lastBox = lastSelectedBox();
    481     if (leftGap)
    482         result.uniteLeft(block()->logicalLeftSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock,
    483                                                           firstBox->parent()->renderer(), firstBox->logicalLeft(), selTop, selHeight, paintInfo));
    484     if (rightGap)
    485         result.uniteRight(block()->logicalRightSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock,
    486                                                             lastBox->parent()->renderer(), lastBox->logicalRight(), selTop, selHeight, paintInfo));
     482    if (leftGap) {
     483        result.uniteLeft(block()->logicalLeftSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, firstBox->parent()->renderer(), firstBox->logicalLeft(),
     484            selTop, selHeight, cache, paintInfo));
     485    }
     486    if (rightGap) {
     487        result.uniteRight(block()->logicalRightSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, lastBox->parent()->renderer(), lastBox->logicalRight(),
     488            selTop, selHeight, cache, paintInfo));
     489    }
    487490
    488491    // When dealing with bidi text, a non-contiguous selection region is possible.
  • trunk/Source/WebCore/rendering/RootInlineBox.h

    r146104 r149007  
    2929class EllipsisBox;
    3030class HitTestResult;
     31class LogicalSelectionOffsetCaches;
    3132class RenderRegion;
    3233
     
    132133    InlineBox* lastSelectedBox();
    133134
    134     GapRects lineSelectionGap(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock, LayoutUnit selTop, LayoutUnit selHeight, const PaintInfo*);
     135    GapRects lineSelectionGap(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
     136        LayoutUnit selTop, LayoutUnit selHeight, const LogicalSelectionOffsetCaches&, const PaintInfo*);
    135137
    136138    RenderBlock* block() const;
Note: See TracChangeset for help on using the changeset viewer.