Source/WebCore/ChangeLog

 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 NOBODY (OOPS!).
 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-22 Jessie Berlin <jberlin@apple.com>
276
377 Debug build fix.
148940

Source/WebCore/GNUmakefile.list.am

@@webcore_sources += \
44474447 Source/WebCore/rendering/InlineTextBox.h \
44484448 Source/WebCore/rendering/LayoutState.cpp \
44494449 Source/WebCore/rendering/LayoutState.h \
 4450 Source/WebCore/rendering/LogicalSelectionOffsetCaches.h \
44504451 Source/WebCore/rendering/LayoutRepainter.h \
44514452 Source/WebCore/rendering/LayoutRepainter.cpp \
44524453 Source/WebCore/rendering/OverlapTestRequestClient.h \
148912

Source/WebCore/Target.pri

@@HEADERS += \
24572457 rendering/InlineBox.h \
24582458 rendering/InlineFlowBox.h \
24592459 rendering/InlineTextBox.h \
2460  rendering/LayoutState.h \
24612460 rendering/LayoutRepainter.h \
 2461 rendering/LayoutState.h \
 2462 rendering/LogicalSelectionOffsetCaches.h \
24622463 rendering/mathml/RenderMathMLBlock.h \
24632464 rendering/mathml/RenderMathMLFenced.h \
24642465 rendering/mathml/RenderMathMLFraction.h \
148912

Source/WebCore/WebCore.xcodeproj/project.pbxproj

33133313 9B6C41531344949000085B62 /* StringWithDirection.h in Headers */ = {isa = PBXBuildFile; fileRef = 9B6C41521344949000085B62 /* StringWithDirection.h */; settings = {ATTRIBUTES = (Private, ); }; };
33143314 9B7E78BD16F16CC600126914 /* HTMLTreeBuilderSimulator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B7E78BA16F16CAE00126914 /* HTMLTreeBuilderSimulator.cpp */; };
33153315 9B7E78BE16F16CC800126914 /* HTMLTreeBuilderSimulator.h in Headers */ = {isa = PBXBuildFile; fileRef = 9B7E78BB16F16CAE00126914 /* HTMLTreeBuilderSimulator.h */; };
 3316 9BA273F4172206BB0097CE47 /* LogicalSelectionOffsetCaches.h in Headers */ = {isa = PBXBuildFile; fileRef = 9BA273F3172206BB0097CE47 /* LogicalSelectionOffsetCaches.h */; };
33163317 9BAB6C6C12550631001626D4 /* EditingStyle.h in Headers */ = {isa = PBXBuildFile; fileRef = 9BAB6C6A12550631001626D4 /* EditingStyle.h */; settings = {ATTRIBUTES = (Private, ); }; };
33173318 9BAB6C6D12550631001626D4 /* EditingStyle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9BAB6C6B12550631001626D4 /* EditingStyle.cpp */; };
33183319 9BAF3B2412C1A39800014BF1 /* WritingDirection.h in Headers */ = {isa = PBXBuildFile; fileRef = 9BAF3B2312C1A39800014BF1 /* WritingDirection.h */; settings = {ATTRIBUTES = (Private, ); }; };

97989799 9B6C41521344949000085B62 /* StringWithDirection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StringWithDirection.h; sourceTree = "<group>"; };
97999800 9B7E78BA16F16CAE00126914 /* HTMLTreeBuilderSimulator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = HTMLTreeBuilderSimulator.cpp; path = parser/HTMLTreeBuilderSimulator.cpp; sourceTree = "<group>"; };
98009801 9B7E78BB16F16CAE00126914 /* HTMLTreeBuilderSimulator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HTMLTreeBuilderSimulator.h; path = parser/HTMLTreeBuilderSimulator.h; sourceTree = "<group>"; };
 9802 9BA273F3172206BB0097CE47 /* LogicalSelectionOffsetCaches.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LogicalSelectionOffsetCaches.h; sourceTree = "<group>"; };
98019803 9BAB6C6A12550631001626D4 /* EditingStyle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EditingStyle.h; sourceTree = "<group>"; };
98029804 9BAB6C6B12550631001626D4 /* EditingStyle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EditingStyle.cpp; sourceTree = "<group>"; };
98039805 9BAF3B2312C1A39800014BF1 /* WritingDirection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WritingDirection.h; sourceTree = "<group>"; };

1261912621 FABE72F31059C1EB00D999DD /* mathtags.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = mathtags.in; sourceTree = "<group>"; };
1262012622 FABE72FB1059C21100D999DD /* MathMLElementFactory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MathMLElementFactory.cpp; sourceTree = "<group>"; };
1262112623 FABE72FC1059C21100D999DD /* MathMLNames.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MathMLNames.cpp; sourceTree = "<group>"; };
12622  FB1A66D917225A6600BAA7AF /* CustomFilterColorParameter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CustomFilterColorParameter.h; path = filters/CustomFilterColorParameter.h; sourceTree = "<group>"; };
1262312624 FB0B75EE1723428500F05D2A /* WebKitCSSMatFunctionValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebKitCSSMatFunctionValue.cpp; sourceTree = "<group>"; };
1262412625 FB0B75EF1723428500F05D2A /* WebKitCSSMatFunctionValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebKitCSSMatFunctionValue.h; sourceTree = "<group>"; };
 12626 FB1A66D917225A6600BAA7AF /* CustomFilterColorParameter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CustomFilterColorParameter.h; path = filters/CustomFilterColorParameter.h; sourceTree = "<group>"; };
1262512627 FB2C15C2165D64900039C9F8 /* CachedSVGDocumentReference.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CachedSVGDocumentReference.h; sourceTree = "<group>"; };
1262612628 FB3056C1169E5DAC0096A232 /* CSSGroupingRule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSGroupingRule.h; sourceTree = "<group>"; };
1262712629 FB484F4A171F821E00040755 /* TransformFunctions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TransformFunctions.cpp; sourceTree = "<group>"; };

2004720049 A120ACA013F9983700FE4AC7 /* LayoutRepainter.h */,
2004820050 2D9066040BE141D400956998 /* LayoutState.cpp */,
2004920051 2D9066050BE141D400956998 /* LayoutState.h */,
 20052 9BA273F3172206BB0097CE47 /* LogicalSelectionOffsetCaches.h */,
2005020053 3774ABA30FA21EB400AD7DE9 /* OverlapTestRequestClient.h */,
2005120054 9377AB9F15DEFEEF0031FD04 /* Pagination.h */,
2005220055 0885067D11DA045B00182B98 /* PaintInfo.h */,

2291122914 935207BE09BD410A00F2038D /* LocalizedStrings.h in Headers */,
2291222915 BCE1C41B0D982980003B02F2 /* Location.h in Headers */,
2291322916 A8239E0109B3CF8A00B60641 /* Logging.h in Headers */,
 22917 9BA273F4172206BB0097CE47 /* LogicalSelectionOffsetCaches.h in Headers */,
2291422918 E187056316E54A0D00585E97 /* MainThreadTask.h in Headers */,
2291522919 1A8F6BC60DB55CDC001DB794 /* ManifestParser.h in Headers */,
2291622920 93309DF8099E64920056E581 /* markup.h in Headers */,
148912

Source/WebCore/rendering/LogicalSelectionOffsetCaches.h

 1/*
 2 * Copyright (C) 2013 Apple Inc. All rights reserved.
 3 *
 4 * This library is free software; you can redistribute it and/or
 5 * modify it under the terms of the GNU Library General Public
 6 * License as published by the Free Software Foundation; either
 7 * version 2 of the License, or (at your option) any later version.
 8 *
 9 * This library is distributed in the hope that it will be useful,
 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 12 * Library General Public License for more details.
 13 *
 14 * You should have received a copy of the GNU Library General Public License
 15 * along with this library; see the file COPYING.LIB. If not, write to
 16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 17 * Boston, MA 02110-1301, USA.
 18 *
 19 */
 20
 21#ifndef LogicalSelectionOffsetCaches_h
 22#define LogicalSelectionOffsetCaches_h
 23
 24#include "RenderBlock.h"
 25
 26namespace WebCore {
 27
 28static inline bool isContainingBlockCandidateForAbsolutelyPositionedObject(RenderObject* object)
 29{
 30 return object->style()->position() != StaticPosition
 31 || (object->hasTransform() && object->isRenderBlock())
 32#if ENABLE(SVG)
 33 || object->isSVGForeignObject()
 34#endif
 35 || object->isRenderView();
 36}
 37
 38static inline bool isNonRenderBlockInline(RenderObject* object)
 39{
 40 return (object->isInline() && !object->isReplaced()) || !object->isRenderBlock();
 41}
 42
 43static inline RenderObject* containingBlockForFixedPosition(RenderObject* parent)
 44{
 45 RenderObject* object = parent;
 46 while (object && !object->canContainFixedPositionObjects())
 47 object = object->parent();
 48 ASSERT(!object || !object->isAnonymousBlock());
 49 return object;
 50}
 51
 52static inline RenderObject* containingBlockForAbsolutePosition(RenderObject* parent)
 53{
 54 RenderObject* object = parent;
 55 while (object && !isContainingBlockCandidateForAbsolutelyPositionedObject(object))
 56 object = object->parent();
 57
 58 // For a relatively positioned inline, return its nearest non-anonymous containing block,
 59 // not the inline itself, to avoid having a positioned objects list in all RenderInlines
 60 // and use RenderBlock* as RenderObject::containingBlock's return type.
 61 // Use RenderBlock::container() to obtain the inline.
 62 if (object->isRenderInline())
 63 object = object->containingBlock();
 64
 65 while (object && object->isAnonymousBlock())
 66 object = object->containingBlock();
 67
 68 return object;
 69}
 70
 71static inline RenderObject* containingBlockForObjectInFlow(RenderObject* parent)
 72{
 73 RenderObject* object = parent;
 74 while (object && isNonRenderBlockInline(object))
 75 object = object->parent();
 76 return object;
 77}
 78
 79class LogicalSelectionOffsetCaches {
 80public:
 81 class ContainingBlockInfo {
 82 public:
 83 ContainingBlockInfo()
 84 : m_block(0)
 85 , m_cache(0)
 86 , m_hasFloatsOrFlowThreads(false)
 87 , m_cachedLogicalLeftSelectionOffset(false)
 88 , m_cachedLogicalRightSelectionOffset(false)
 89 { }
 90
 91 void setBlock(RenderBlock* block, const LogicalSelectionOffsetCaches* cache)
 92 {
 93 m_block = block;
 94 m_hasFloatsOrFlowThreads = m_hasFloatsOrFlowThreads || m_block->containsFloats() || m_block->flowThreadContainingBlock();
 95 m_cache = cache;
 96 m_cachedLogicalLeftSelectionOffset = false;
 97 m_cachedLogicalRightSelectionOffset = false;
 98 }
 99
 100 RenderBlock* block() const { return m_block; }
 101 const LogicalSelectionOffsetCaches* cache() const { return m_cache; }
 102
 103 LayoutUnit logicalLeftSelectionOffset(RenderBlock* rootBlock, LayoutUnit position) const
 104 {
 105 ASSERT(m_cache);
 106 if (m_hasFloatsOrFlowThreads || !m_cachedLogicalLeftSelectionOffset) {
 107 m_cachedLogicalLeftSelectionOffset = true;
 108 m_logicalLeftSelectionOffset = m_block->logicalLeftSelectionOffset(rootBlock, position, *m_cache);
 109 } else
 110 ASSERT(m_logicalLeftSelectionOffset == m_block->logicalLeftSelectionOffset(rootBlock, position, *m_cache));
 111 return m_logicalLeftSelectionOffset;
 112 }
 113
 114 LayoutUnit logicalRightSelectionOffset(RenderBlock* rootBlock, LayoutUnit position) const
 115 {
 116 ASSERT(m_cache);
 117 if (m_hasFloatsOrFlowThreads || !m_cachedLogicalRightSelectionOffset) {
 118 m_cachedLogicalRightSelectionOffset = true;
 119 m_logicalRightSelectionOffset = m_block->logicalRightSelectionOffset(rootBlock, position, *m_cache);
 120 } else
 121 ASSERT(m_logicalRightSelectionOffset == m_block->logicalRightSelectionOffset(rootBlock, position, *m_cache));
 122 return m_logicalRightSelectionOffset;
 123 }
 124
 125 private:
 126 RenderBlock* m_block;
 127 const LogicalSelectionOffsetCaches* m_cache;
 128 bool m_hasFloatsOrFlowThreads : 1;
 129 mutable bool m_cachedLogicalLeftSelectionOffset : 1;
 130 mutable bool m_cachedLogicalRightSelectionOffset : 1;
 131 mutable LayoutUnit m_logicalLeftSelectionOffset;
 132 mutable LayoutUnit m_logicalRightSelectionOffset;
 133
 134 };
 135
 136 LogicalSelectionOffsetCaches(RenderBlock* rootBlock)
 137 {
 138 ASSERT(rootBlock->isSelectionRoot());
 139 RenderObject* parent = rootBlock->parent();
 140
 141 // LogicalSelectionOffsetCaches should not be used on an orphaned tree.
 142 m_containingBlockForFixedPosition.setBlock(toRenderBlock(containingBlockForFixedPosition(parent)), 0);
 143 m_containingBlockForAbsolutePosition.setBlock(toRenderBlock(containingBlockForAbsolutePosition(parent)), 0);
 144 m_containingBlockForInflowPosition.setBlock(toRenderBlock(containingBlockForObjectInFlow(parent)), 0);
 145 }
 146
 147 LogicalSelectionOffsetCaches(RenderBlock* block, const LogicalSelectionOffsetCaches& cache)
 148 : m_containingBlockForFixedPosition(cache.m_containingBlockForFixedPosition)
 149 , m_containingBlockForAbsolutePosition(cache.m_containingBlockForAbsolutePosition)
 150 , m_parentCache(&cache)
 151 {
 152 if (block->canContainFixedPositionObjects())
 153 m_containingBlockForFixedPosition.setBlock(block, &cache);
 154
 155 if (isContainingBlockCandidateForAbsolutelyPositionedObject(block) && !block->isRenderInline() && !block->isAnonymousBlock())
 156 m_containingBlockForFixedPosition.setBlock(block, &cache);
 157
 158 m_containingBlockForInflowPosition.setBlock(block, &cache);
 159 }
 160
 161 const ContainingBlockInfo& containingBlockInfo(RenderBlock* block) const
 162 {
 163 EPosition position = block->style()->position();
 164 if (position == FixedPosition) {
 165 ASSERT(block->containingBlock() == m_containingBlockForFixedPosition.block());
 166 return m_containingBlockForFixedPosition;
 167 }
 168 if (position == AbsolutePosition) {
 169 ASSERT(block->containingBlock() == m_containingBlockForAbsolutePosition.block());
 170 return m_containingBlockForAbsolutePosition;
 171 }
 172 ASSERT(block->containingBlock() == m_containingBlockForInflowPosition.block());
 173 return m_containingBlockForInflowPosition;
 174 }
 175
 176private:
 177 ContainingBlockInfo m_containingBlockForFixedPosition;
 178 ContainingBlockInfo m_containingBlockForAbsolutePosition;
 179 ContainingBlockInfo m_containingBlockForInflowPosition;
 180 const LogicalSelectionOffsetCaches* m_parentCache;
 181};
 182
 183} // namespace WebCore
 184
 185#endif // LogicalSelectionOffsetCaches_h
0

Source/WebCore/rendering/RenderBlock.cpp

4141#include "InlineIterator.h"
4242#include "InlineTextBox.h"
4343#include "LayoutRepainter.h"
 44#include "LogicalSelectionOffsetCaches.h"
4445#include "OverflowEvent.h"
4546#include "PODFreeListArena.h"
4647#include "Page.h"

@@GapRects RenderBlock::selectionGapRectsF
34013402 if (hasOverflowClip())
34023403 offsetFromRepaintContainer -= scrolledContentOffset();
34033404
 3405 LogicalSelectionOffsetCaches cache(this);
34043406 LayoutUnit lastTop = 0;
3405  LayoutUnit lastLeft = logicalLeftSelectionOffset(this, lastTop);
3406  LayoutUnit lastRight = logicalRightSelectionOffset(this, lastTop);
 3407 LayoutUnit lastLeft = logicalLeftSelectionOffset(this, lastTop, cache);
 3408 LayoutUnit lastRight = logicalRightSelectionOffset(this, lastTop, cache);
34073409
3408  return selectionGaps(this, offsetFromRepaintContainer, IntSize(), lastTop, lastLeft, lastRight);
 3410 return selectionGaps(this, offsetFromRepaintContainer, IntSize(), lastTop, lastLeft, lastRight, cache);
34093411}
34103412
34113413void RenderBlock::paintSelection(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
34123414{
34133415 if (shouldPaintSelectionGaps() && paintInfo.phase == PaintPhaseForeground) {
 3416 LogicalSelectionOffsetCaches cache(this);
34143417 LayoutUnit lastTop = 0;
3415  LayoutUnit lastLeft = logicalLeftSelectionOffset(this, lastTop);
3416  LayoutUnit lastRight = logicalRightSelectionOffset(this, lastTop);
 3418 LayoutUnit lastLeft = logicalLeftSelectionOffset(this, lastTop, cache);
 3419 LayoutUnit lastRight = logicalRightSelectionOffset(this, lastTop, cache);
34173420 GraphicsContextStateSaver stateSaver(*paintInfo.context);
34183421
3419  LayoutRect gapRectsBounds = selectionGaps(this, paintOffset, LayoutSize(), lastTop, lastLeft, lastRight, &paintInfo);
 3422 LayoutRect gapRectsBounds = selectionGaps(this, paintOffset, LayoutSize(), lastTop, lastLeft, lastRight, cache, &paintInfo);
34203423 if (!gapRectsBounds.isEmpty()) {
34213424 if (RenderLayer* layer = enclosingLayer()) {
34223425 gapRectsBounds.moveBy(-paintOffset);

@@LayoutRect RenderBlock::logicalRectToPhy
34683471}
34693472
34703473GapRects RenderBlock::selectionGaps(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
3471  LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const PaintInfo* paintInfo)
 3474 LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const LogicalSelectionOffsetCaches& cache, const PaintInfo* paintInfo)
34723475{
34733476 // IMPORTANT: Callers of this method that intend for painting to happen need to do a save/restore.
34743477 // Clip out floating and positioned objects when painting selection gaps.

@@GapRects RenderBlock::selectionGaps(Rend
35053508 if (hasColumns() || hasTransform() || style()->columnSpan()) {
35063509 // FIXME: We should learn how to gap fill multiple columns and transforms eventually.
35073510 lastLogicalTop = blockDirectionOffset(rootBlock, offsetFromRootBlock) + logicalHeight();
3508  lastLogicalLeft = logicalLeftSelectionOffset(rootBlock, logicalHeight());
3509  lastLogicalRight = logicalRightSelectionOffset(rootBlock, logicalHeight());
 3511 lastLogicalLeft = logicalLeftSelectionOffset(rootBlock, logicalHeight(), cache);
 3512 lastLogicalRight = logicalRightSelectionOffset(rootBlock, logicalHeight(), cache);
35103513 return result;
35113514 }
35123515
35133516 if (childrenInline())
3514  result = inlineSelectionGaps(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, lastLogicalTop, lastLogicalLeft, lastLogicalRight, paintInfo);
 3517 result = inlineSelectionGaps(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, lastLogicalTop, lastLogicalLeft, lastLogicalRight, cache, paintInfo);
35153518 else
3516  result = blockSelectionGaps(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, lastLogicalTop, lastLogicalLeft, lastLogicalRight, paintInfo);
 3519 result = blockSelectionGaps(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, lastLogicalTop, lastLogicalLeft, lastLogicalRight, cache, paintInfo);
35173520
35183521 // Go ahead and fill the vertical gap all the way to the bottom of our block if the selection extends past our block.
3519  if (rootBlock == this && (selectionState() != SelectionBoth && selectionState() != SelectionEnd))
3520  result.uniteCenter(blockSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, lastLogicalTop, lastLogicalLeft, lastLogicalRight,
3521  logicalHeight(), paintInfo));
 3522 if (rootBlock == this && (selectionState() != SelectionBoth && selectionState() != SelectionEnd)) {
 3523 result.uniteCenter(blockSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock,
 3524 lastLogicalTop, lastLogicalLeft, lastLogicalRight, logicalHeight(), cache, paintInfo));
 3525 }
 3526
35223527 return result;
35233528}
35243529
35253530GapRects RenderBlock::inlineSelectionGaps(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
3526  LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const PaintInfo* paintInfo)
 3531 LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const LogicalSelectionOffsetCaches& cache, const PaintInfo* paintInfo)
35273532{
35283533 GapRects result;
35293534

@@GapRects RenderBlock::inlineSelectionGap
35343539 // Go ahead and update our lastLogicalTop to be the bottom of the block. <hr>s or empty blocks with height can trip this
35353540 // case.
35363541 lastLogicalTop = blockDirectionOffset(rootBlock, offsetFromRootBlock) + logicalHeight();
3537  lastLogicalLeft = logicalLeftSelectionOffset(rootBlock, logicalHeight());
3538  lastLogicalRight = logicalRightSelectionOffset(rootBlock, logicalHeight());
 3542 lastLogicalLeft = logicalLeftSelectionOffset(rootBlock, logicalHeight(), cache);
 3543 lastLogicalRight = logicalRightSelectionOffset(rootBlock, logicalHeight(), cache);
35393544 }
35403545 return result;
35413546 }

@@GapRects RenderBlock::inlineSelectionGap
35513556
35523557 if (!containsStart && !lastSelectedLine &&
35533558 selectionState() != SelectionStart && selectionState() != SelectionBoth)
3554  result.uniteCenter(blockSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, lastLogicalTop, lastLogicalLeft, lastLogicalRight,
3555  selTop, paintInfo));
 3559 result.uniteCenter(blockSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, lastLogicalTop, lastLogicalLeft, lastLogicalRight, selTop, cache, paintInfo));
35563560
35573561 LayoutRect logicalRect(curr->logicalLeft(), selTop, curr->logicalWidth(), selTop + selHeight);
35583562 logicalRect.move(isHorizontalWritingMode() ? offsetFromRootBlock : offsetFromRootBlock.transposedSize());
35593563 LayoutRect physicalRect = rootBlock->logicalRectToPhysicalRect(rootBlockPhysicalPosition, logicalRect);
35603564 if (!paintInfo || (isHorizontalWritingMode() && physicalRect.y() < paintInfo->rect.maxY() && physicalRect.maxY() > paintInfo->rect.y())
35613565 || (!isHorizontalWritingMode() && physicalRect.x() < paintInfo->rect.maxX() && physicalRect.maxX() > paintInfo->rect.x()))
3562  result.unite(curr->lineSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, selTop, selHeight, paintInfo));
 3566 result.unite(curr->lineSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, selTop, selHeight, cache, paintInfo));
35633567
35643568 lastSelectedLine = curr;
35653569 }

@@GapRects RenderBlock::inlineSelectionGap
35713575 if (lastSelectedLine && selectionState() != SelectionEnd && selectionState() != SelectionBoth) {
35723576 // Go ahead and update our lastY to be the bottom of the last selected line.
35733577 lastLogicalTop = blockDirectionOffset(rootBlock, offsetFromRootBlock) + lastSelectedLine->selectionBottom();
3574  lastLogicalLeft = logicalLeftSelectionOffset(rootBlock, lastSelectedLine->selectionBottom());
3575  lastLogicalRight = logicalRightSelectionOffset(rootBlock, lastSelectedLine->selectionBottom());
 3578 lastLogicalLeft = logicalLeftSelectionOffset(rootBlock, lastSelectedLine->selectionBottom(), cache);
 3579 lastLogicalRight = logicalRightSelectionOffset(rootBlock, lastSelectedLine->selectionBottom(), cache);
35763580 }
35773581 return result;
35783582}
35793583
35803584GapRects RenderBlock::blockSelectionGaps(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
3581  LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const PaintInfo* paintInfo)
 3585 LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const LogicalSelectionOffsetCaches& cache, const PaintInfo* paintInfo)
35823586{
35833587 GapRects result;
35843588
35853589 // Go ahead and jump right to the first block child that contains some selected objects.
35863590 RenderBox* curr;
35873591 for (curr = firstChildBox(); curr && curr->selectionState() == SelectionNone; curr = curr->nextSiblingBox()) { }
 3592
 3593 if (!curr)
 3594 return result;
 3595
 3596 LogicalSelectionOffsetCaches childCache(this, cache);
35883597
35893598 for (bool sawSelectionEnd = false; curr && !sawSelectionEnd; curr = curr->nextSiblingBox()) {
35903599 SelectionState childState = curr->selectionState();

@@GapRects RenderBlock::blockSelectionGaps
36063615 bool fillBlockGaps = paintsOwnSelection || (curr->canBeSelectionLeaf() && childState != SelectionNone);
36073616 if (fillBlockGaps) {
36083617 // We need to fill the vertical gap above this object.
3609  if (childState == SelectionEnd || childState == SelectionInside)
 3618 if (childState == SelectionEnd || childState == SelectionInside) {
36103619 // Fill the gap above the object.
3611  result.uniteCenter(blockSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, lastLogicalTop, lastLogicalLeft, lastLogicalRight,
3612  curr->logicalTop(), paintInfo));
 3620 result.uniteCenter(blockSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock,
 3621 lastLogicalTop, lastLogicalLeft, lastLogicalRight, curr->logicalTop(), cache, paintInfo));
 3622 }
36133623
36143624 // 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*
36153625 // our object. We know this if the selection did not end inside our object.

@@GapRects RenderBlock::blockSelectionGaps
36213631 getSelectionGapInfo(childState, leftGap, rightGap);
36223632
36233633 if (leftGap)
3624  result.uniteLeft(logicalLeftSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, this, curr->logicalLeft(), curr->logicalTop(), curr->logicalHeight(), paintInfo));
 3634 result.uniteLeft(logicalLeftSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, this, curr->logicalLeft(), curr->logicalTop(), curr->logicalHeight(), cache, paintInfo));
36253635 if (rightGap)
3626  result.uniteRight(logicalRightSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, this, curr->logicalRight(), curr->logicalTop(), curr->logicalHeight(), paintInfo));
 3636 result.uniteRight(logicalRightSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, this, curr->logicalRight(), curr->logicalTop(), curr->logicalHeight(), cache, paintInfo));
36273637
36283638 // Update lastLogicalTop to be just underneath the object. lastLogicalLeft and lastLogicalRight extend as far as
36293639 // they can without bumping into floating or positioned objects. Ideally they will go right up
36303640 // to the border of the root selection block.
36313641 lastLogicalTop = blockDirectionOffset(rootBlock, offsetFromRootBlock) + curr->logicalBottom();
3632  lastLogicalLeft = logicalLeftSelectionOffset(rootBlock, curr->logicalBottom());
3633  lastLogicalRight = logicalRightSelectionOffset(rootBlock, curr->logicalBottom());
3634  } else if (childState != SelectionNone)
 3642 lastLogicalLeft = logicalLeftSelectionOffset(rootBlock, curr->logicalBottom(), cache);
 3643 lastLogicalRight = logicalRightSelectionOffset(rootBlock, curr->logicalBottom(), cache);
 3644 } else if (childState != SelectionNone) {
36353645 // We must be a block that has some selected object inside it. Go ahead and recur.
36363646 result.unite(toRenderBlock(curr)->selectionGaps(rootBlock, rootBlockPhysicalPosition, LayoutSize(offsetFromRootBlock.width() + curr->x(), offsetFromRootBlock.height() + curr->y()),
3637  lastLogicalTop, lastLogicalLeft, lastLogicalRight, paintInfo));
 3647 lastLogicalTop, lastLogicalLeft, lastLogicalRight, childCache, paintInfo));
 3648 }
36383649 }
36393650 return result;
36403651}
36413652
36423653LayoutRect RenderBlock::blockSelectionGap(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
3643  LayoutUnit lastLogicalTop, LayoutUnit lastLogicalLeft, LayoutUnit lastLogicalRight, LayoutUnit logicalBottom, const PaintInfo* paintInfo)
 3654 LayoutUnit lastLogicalTop, LayoutUnit lastLogicalLeft, LayoutUnit lastLogicalRight, LayoutUnit logicalBottom, const LogicalSelectionOffsetCaches& cache, const PaintInfo* paintInfo)
36443655{
36453656 LayoutUnit logicalTop = lastLogicalTop;
36463657 LayoutUnit logicalHeight = blockDirectionOffset(rootBlock, offsetFromRootBlock) + logicalBottom - logicalTop;

@@LayoutRect RenderBlock::blockSelectionGa
36483659 return LayoutRect();
36493660
36503661 // Get the selection offsets for the bottom of the gap
3651  LayoutUnit logicalLeft = max(lastLogicalLeft, logicalLeftSelectionOffset(rootBlock, logicalBottom));
3652  LayoutUnit logicalRight = min(lastLogicalRight, logicalRightSelectionOffset(rootBlock, logicalBottom));
 3662 LayoutUnit logicalLeft = max(lastLogicalLeft, logicalLeftSelectionOffset(rootBlock, logicalBottom, cache));
 3663 LayoutUnit logicalRight = min(lastLogicalRight, logicalRightSelectionOffset(rootBlock, logicalBottom, cache));
36533664 LayoutUnit logicalWidth = logicalRight - logicalLeft;
36543665 if (logicalWidth <= 0)
36553666 return LayoutRect();

@@LayoutRect RenderBlock::blockSelectionGa
36613672}
36623673
36633674LayoutRect RenderBlock::logicalLeftSelectionGap(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
3664  RenderObject* selObj, LayoutUnit logicalLeft, LayoutUnit logicalTop, LayoutUnit logicalHeight, const PaintInfo* paintInfo)
 3675 RenderObject* selObj, LayoutUnit logicalLeft, LayoutUnit logicalTop, LayoutUnit logicalHeight, const LogicalSelectionOffsetCaches& cache, const PaintInfo* paintInfo)
36653676{
36663677 LayoutUnit rootBlockLogicalTop = blockDirectionOffset(rootBlock, offsetFromRootBlock) + logicalTop;
3667  LayoutUnit rootBlockLogicalLeft = max(logicalLeftSelectionOffset(rootBlock, logicalTop), logicalLeftSelectionOffset(rootBlock, logicalTop + logicalHeight));
3668  LayoutUnit rootBlockLogicalRight = min(inlineDirectionOffset(rootBlock, offsetFromRootBlock) + floorToInt(logicalLeft), min(logicalRightSelectionOffset(rootBlock, logicalTop), logicalRightSelectionOffset(rootBlock, logicalTop + logicalHeight)));
 3678 LayoutUnit rootBlockLogicalLeft = max(logicalLeftSelectionOffset(rootBlock, logicalTop, cache), logicalLeftSelectionOffset(rootBlock, logicalTop + logicalHeight, cache));
 3679 LayoutUnit rootBlockLogicalRight = min(inlineDirectionOffset(rootBlock, offsetFromRootBlock) + floorToInt(logicalLeft),
 3680 min(logicalRightSelectionOffset(rootBlock, logicalTop, cache), logicalRightSelectionOffset(rootBlock, logicalTop + logicalHeight, cache)));
36693681 LayoutUnit rootBlockLogicalWidth = rootBlockLogicalRight - rootBlockLogicalLeft;
36703682 if (rootBlockLogicalWidth <= 0)
36713683 return LayoutRect();

@@LayoutRect RenderBlock::logicalLeftSelec
36773689}
36783690
36793691LayoutRect RenderBlock::logicalRightSelectionGap(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
3680  RenderObject* selObj, LayoutUnit logicalRight, LayoutUnit logicalTop, LayoutUnit logicalHeight, const PaintInfo* paintInfo)
 3692 RenderObject* selObj, LayoutUnit logicalRight, LayoutUnit logicalTop, LayoutUnit logicalHeight, const LogicalSelectionOffsetCaches& cache, const PaintInfo* paintInfo)
36813693{
36823694 LayoutUnit rootBlockLogicalTop = blockDirectionOffset(rootBlock, offsetFromRootBlock) + logicalTop;
3683  LayoutUnit rootBlockLogicalLeft = max(inlineDirectionOffset(rootBlock, offsetFromRootBlock) + floorToInt(logicalRight), max(logicalLeftSelectionOffset(rootBlock, logicalTop), logicalLeftSelectionOffset(rootBlock, logicalTop + logicalHeight)));
3684  LayoutUnit rootBlockLogicalRight = min(logicalRightSelectionOffset(rootBlock, logicalTop), logicalRightSelectionOffset(rootBlock, logicalTop + logicalHeight));
 3695 LayoutUnit rootBlockLogicalLeft = max(inlineDirectionOffset(rootBlock, offsetFromRootBlock) + floorToInt(logicalRight),
 3696 max(logicalLeftSelectionOffset(rootBlock, logicalTop, cache), logicalLeftSelectionOffset(rootBlock, logicalTop + logicalHeight, cache)));
 3697 LayoutUnit rootBlockLogicalRight = min(logicalRightSelectionOffset(rootBlock, logicalTop, cache), logicalRightSelectionOffset(rootBlock, logicalTop + logicalHeight, cache));
36853698 LayoutUnit rootBlockLogicalWidth = rootBlockLogicalRight - rootBlockLogicalLeft;
36863699 if (rootBlockLogicalWidth <= 0)
36873700 return LayoutRect();

@@void RenderBlock::getSelectionGapInfo(Se
37033716 (state == RenderObject::SelectionEnd && !ltr);
37043717}
37053718
3706 LayoutUnit RenderBlock::logicalLeftSelectionOffset(RenderBlock* rootBlock, LayoutUnit position)
 3719LayoutUnit RenderBlock::logicalLeftSelectionOffset(RenderBlock* rootBlock, LayoutUnit position, const LogicalSelectionOffsetCaches& cache)
37073720{
37083721 LayoutUnit logicalLeft = logicalLeftOffsetForLine(position, false);
37093722 if (logicalLeft == logicalLeftOffsetForContent()) {
3710  if (rootBlock != this)
3711  // The border can potentially be further extended by our containingBlock().
3712  return containingBlock()->logicalLeftSelectionOffset(rootBlock, position + logicalTop());
 3723 if (rootBlock != this) // The border can potentially be further extended by our containingBlock().
 3724 return cache.containingBlockInfo(this).logicalLeftSelectionOffset(rootBlock, position + logicalTop());
37133725 return logicalLeft;
37143726 } else {
37153727 RenderBlock* cb = this;
 3728 const LogicalSelectionOffsetCaches* currentCache = &cache;
37163729 while (cb != rootBlock) {
37173730 logicalLeft += cb->logicalLeft();
3718  cb = cb->containingBlock();
 3731
 3732 ASSERT(currentCache);
 3733 const LogicalSelectionOffsetCaches::ContainingBlockInfo& info = currentCache->containingBlockInfo(cb);
 3734 cb = info.block();
 3735 currentCache = info.cache();
37193736 }
37203737 }
37213738 return logicalLeft;
37223739}
37233740
3724 LayoutUnit RenderBlock::logicalRightSelectionOffset(RenderBlock* rootBlock, LayoutUnit position)
 3741LayoutUnit RenderBlock::logicalRightSelectionOffset(RenderBlock* rootBlock, LayoutUnit position, const LogicalSelectionOffsetCaches& cache)
37253742{
37263743 LayoutUnit logicalRight = logicalRightOffsetForLine(position, false);
37273744 if (logicalRight == logicalRightOffsetForContent()) {
3728  if (rootBlock != this)
3729  // The border can potentially be further extended by our containingBlock().
3730  return containingBlock()->logicalRightSelectionOffset(rootBlock, position + logicalTop());
 3745 if (rootBlock != this) // The border can potentially be further extended by our containingBlock().
 3746 return cache.containingBlockInfo(this).logicalRightSelectionOffset(rootBlock, position + logicalTop());
37313747 return logicalRight;
37323748 } else {
37333749 RenderBlock* cb = this;
 3750 const LogicalSelectionOffsetCaches* currentCache = &cache;
37343751 while (cb != rootBlock) {
37353752 logicalRight += cb->logicalLeft();
3736  cb = cb->containingBlock();
 3753
 3754 ASSERT(currentCache);
 3755 const LogicalSelectionOffsetCaches::ContainingBlockInfo& info = currentCache->containingBlockInfo(cb);
 3756 cb = info.block();
 3757 currentCache = info.cache();
37373758 }
37383759 }
37393760 return logicalRight;
148912

Source/WebCore/rendering/RenderBlock.h

@@class InlineIterator;
4646class LayoutStateMaintainer;
4747class LineLayoutState;
4848class LineWidth;
 49class LogicalSelectionOffsetCaches;
4950class RenderInline;
5051class RenderText;
5152

@@public:
243244
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;
251252

@@private:
928929 virtual bool shouldPaintSelectionGaps() const;
929930 bool isSelectionRoot() const;
930931 GapRects selectionGaps(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
931  LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const PaintInfo* = 0);
 932 LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const LogicalSelectionOffsetCaches&, const PaintInfo* = 0);
932933 GapRects inlineSelectionGaps(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
933  LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const PaintInfo*);
 934 LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const LogicalSelectionOffsetCaches&, const PaintInfo*);
934935 GapRects blockSelectionGaps(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
935  LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const PaintInfo*);
 936 LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const LogicalSelectionOffsetCaches&, const PaintInfo*);
936937 LayoutRect blockSelectionGap(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
937  LayoutUnit lastLogicalTop, LayoutUnit lastLogicalLeft, LayoutUnit lastLogicalRight, LayoutUnit logicalBottom, const PaintInfo*);
938  LayoutUnit logicalLeftSelectionOffset(RenderBlock* rootBlock, LayoutUnit position);
939  LayoutUnit logicalRightSelectionOffset(RenderBlock* rootBlock, LayoutUnit position);
 938 LayoutUnit lastLogicalTop, LayoutUnit lastLogicalLeft, LayoutUnit lastLogicalRight, LayoutUnit logicalBottom, const LogicalSelectionOffsetCaches&, const PaintInfo*);
 939 LayoutUnit logicalLeftSelectionOffset(RenderBlock* rootBlock, LayoutUnit position, const LogicalSelectionOffsetCaches&);
 940 LayoutUnit logicalRightSelectionOffset(RenderBlock* rootBlock, LayoutUnit position, const LogicalSelectionOffsetCaches&);
 941
 942 friend class LogicalSelectionOffsetCaches;
940943
941944 virtual void absoluteRects(Vector<IntRect>&, const LayoutPoint& accumulatedOffset) const;
942945 virtual void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const;
148912

Source/WebCore/rendering/RenderObject.cpp

4444#include "HTMLElement.h"
4545#include "HTMLNames.h"
4646#include "HitTestResult.h"
 47#include "LogicalSelectionOffsetCaches.h"
4748#include "Page.h"
4849#include "RenderArena.h"
4950#include "RenderCounter.h"

@@void RenderObject::setLayerNeedsFullRepa
768769 toRenderLayerModelObject(this)->layer()->setRepaintStatus(NeedsFullRepaintForPositionedMovementLayout);
769770}
770771
771 static inline bool isContainingBlockCandidateForAbsolutelyPositionedObject(RenderObject* object)
772 {
773  return object->style()->position() != StaticPosition
774  || (object->hasTransform() && object->isRenderBlock())
775 #if ENABLE(SVG)
776  || object->isSVGForeignObject()
777 #endif
778  || object->isRenderView();
779 }
780 
781 static inline bool isNonRenderBlockInline(RenderObject* object)
782 {
783  return (object->isInline() && !object->isReplaced()) || !object->isRenderBlock();
784 }
785 
786772RenderBlock* RenderObject::containingBlock() const
787773{
788774 RenderObject* o = parent();
789775 if (!o && isRenderScrollbarPart())
790776 o = toRenderScrollbarPart(this)->rendererOwningScrollbar();
791777
792  if (!isText() && m_style->position() == FixedPosition) {
793  while (o && !o->canContainFixedPositionObjects())
794  o = o->parent();
795  ASSERT(!o || !o->isAnonymousBlock());
796  } else if (!isText() && m_style->position() == AbsolutePosition) {
797  while (o && !isContainingBlockCandidateForAbsolutelyPositionedObject(o))
798  o = o->parent();
799 
800  // For a relatively positioned inline, return its nearest non-anonymous containing block,
801  // not the inline itself, to avoid having a positioned objects list in all RenderInlines
802  // and use RenderBlock* as this function's return type.
803  // Use RenderBlock::container() to obtain the inline.
804  if (o && o->isRenderInline())
805  o = o->containingBlock();
806 
807  while (o && o->isAnonymousBlock())
808  o = o->containingBlock();
809  } else {
810  while (o && isNonRenderBlockInline(o))
811  o = o->parent();
812  }
 778 if (!isText() && m_style->position() == FixedPosition)
 779 o = containingBlockForFixedPosition(o);
 780 else if (!isText() && m_style->position() == AbsolutePosition)
 781 o = containingBlockForAbsolutePosition(o);
 782 else
 783 o = containingBlockForObjectInFlow(o);
813784
814785 if (!o || !o->isRenderBlock())
815786 return 0; // This can still happen in case of an orphaned tree
148912

Source/WebCore/rendering/RootInlineBox.cpp

2929#include "GraphicsContext.h"
3030#include "HitTestResult.h"
3131#include "InlineTextBox.h"
 32#include "LogicalSelectionOffsetCaches.h"
3233#include "Page.h"
3334#include "PaintInfo.h"
3435#include "RenderArena.h"

@@LayoutUnit RootInlineBox::lineSnapAdjust
466467 return lineSnapAdjustment(newPageLogicalTop - (blockOffset + lineTopWithLeading()));
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();
473474

@@GapRects RootInlineBox::lineSelectionGap
478479
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.
489492 // e.g. The logical text aaaAAAbbb (capitals denote RTL text and non-capitals LTR) is layed out
148912

Source/WebCore/rendering/RootInlineBox.h

@@namespace WebCore {
2828
2929class EllipsisBox;
3030class HitTestResult;
 31class LogicalSelectionOffsetCaches;
3132class RenderRegion;
3233
3334struct BidiStatus;

@@public:
131132 InlineBox* firstSelectedBox();
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;
137139
148912