Source/WebCore/rendering/RenderObject.cpp

3131#include "AnimationController.h"
3232#include "Chrome.h"
3333#include "ContentData.h"
 34#include "ContainingBlockCache.h"
3435#include "CursorList.h"
3536#include "DashArray.h"
3637#include "EditingBoundary.h"

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();
 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);
799784
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->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  }
813 
814785 if (!o || !o->isRenderBlock())
815786 return 0; // This can still happen in case of an orphaned tree
816787
148767

Source/WebCore/rendering/RootInlineBox.h

2626
2727namespace WebCore {
2828
 29class ContainingBlockCache;
2930class EllipsisBox;
3031class HitTestResult;
3132class RenderRegion;

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 ContainingBlockCache&, const PaintInfo*);
135137
136138 RenderBlock* block() const;
137139
148767

Source/WebCore/rendering/RootInlineBox.cpp

2323#include "BidiResolver.h"
2424#include "Chrome.h"
2525#include "ChromeClient.h"
 26#include "ContainingBlockCache.h"
2627#include "Document.h"
2728#include "EllipsisBox.h"
2829#include "Frame.h"

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 ContainingBlockCache& cache, const PaintInfo* paintInfo)
471472{
472473 RenderObject::SelectionState lineState = selectionState();
473474

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
148767

Source/WebCore/rendering/ContainingBlockCache.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 ContainingBlockCache_h
 22#define ContainingBlockCache_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 ContainingBlockCache
 80{
 81public:
 82 // FIXME: We shouldn't have this constructor
 83 ContainingBlockCache(RenderBlock* rootBlock)
 84 : m_parentCache(0)
 85 {
 86 RenderObject* parent = rootBlock->parent();
 87
 88 // ContainingBlockCache should not be used on an orphaned tree.
 89 m_containingBlockForFixedPosition.block = toRenderBlock(containingBlockForFixedPosition(parent));
 90 m_containingBlockForAbsolutePosition.block = toRenderBlock(containingBlockForAbsolutePosition(parent));
 91 m_containingBlockForInflowPosition.block = toRenderBlock(containingBlockForObjectInFlow(parent));
 92 }
 93
 94 ContainingBlockCache(RenderBlock* block, const ContainingBlockCache& cache)
 95 : m_containingBlockForFixedPosition(cache.m_containingBlockForFixedPosition)
 96 , m_containingBlockForAbsolutePosition(cache.m_containingBlockForAbsolutePosition)
 97 , m_parentCache(&cache)
 98 {
 99 if (block->canContainFixedPositionObjects())
 100 m_containingBlockForFixedPosition.block = block;
 101
 102 if (isContainingBlockCandidateForAbsolutelyPositionedObject(block) && !block->isRenderInline() && !block->isAnonymousBlock())
 103 m_containingBlockForFixedPosition.block = block;
 104
 105 m_containingBlockForInflowPosition.block = block;
 106 }
 107
 108 RenderBlock* containingBlock(RenderBlock* block) const
 109 {
 110 EPosition position = block->style()->position();
 111 if (position == FixedPosition)
 112 return m_containingBlockForFixedPosition.block;
 113 if (position == AbsolutePosition)
 114 return m_containingBlockForAbsolutePosition.block;
 115 return m_containingBlockForInflowPosition.block;
 116 }
 117
 118 const ContainingBlockCache* parentCache() const { return m_parentCache; }
 119
 120private:
 121 struct ContainingBlockInfo {
 122 ContainingBlockInfo()
 123 : block(0)
 124 , cachedLeftOffset(false)
 125 , cachedRightOffset(false)
 126 { }
 127
 128 RenderBlock* block;
 129 LayoutUnit leftOffset;
 130 LayoutUnit rightOffset;
 131 bool cachedLeftOffset : 1;
 132 bool cachedRightOffset : 1;
 133 };
 134
 135 ContainingBlockInfo m_containingBlockForFixedPosition;
 136 ContainingBlockInfo m_containingBlockForAbsolutePosition;
 137 ContainingBlockInfo m_containingBlockForInflowPosition;
 138 const ContainingBlockCache* m_parentCache;
 139};
 140
 141} // namespace WebCore
 142
 143#endif // ContainingBlockCache_h
0

Source/WebCore/rendering/RenderBlock.cpp

2626
2727#include "AXObjectCache.h"
2828#include "ColumnInfo.h"
 29#include "ContainingBlockCache.h"
2930#include "Document.h"
3031#include "Editor.h"
3132#include "Element.h"

34013402 if (hasOverflowClip())
34023403 offsetFromRepaintContainer -= scrolledContentOffset();
34033404
 3405 ContainingBlockCache 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 ContainingBlockCache 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);

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 ContainingBlockCache& 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.

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 ContainingBlockCache& cache, const PaintInfo* paintInfo)
35273532{
35283533 GapRects result;
35293534

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 }

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 }

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 ContainingBlockCache& 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;
35883595
 3596 ContainingBlockCache childCache(this, cache);
 3597
35893598 for (bool sawSelectionEnd = false; curr && !sawSelectionEnd; curr = curr->nextSiblingBox()) {
35903599 SelectionState childState = curr->selectionState();
35913600 if (childState == SelectionBoth || childState == SelectionEnd)

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.

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 ContainingBlockCache& cache, const PaintInfo* paintInfo)
36443655{
36453656 LayoutUnit logicalTop = lastLogicalTop;
36463657 LayoutUnit logicalHeight = blockDirectionOffset(rootBlock, offsetFromRootBlock) + logicalBottom - logicalTop;

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();

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 ContainingBlockCache& 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();

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 ContainingBlockCache& 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();

37033716 (state == RenderObject::SelectionEnd && !ltr);
37043717}
37053718
3706 LayoutUnit RenderBlock::logicalLeftSelectionOffset(RenderBlock* rootBlock, LayoutUnit position)
 3719LayoutUnit RenderBlock::logicalLeftSelectionOffset(RenderBlock* rootBlock, LayoutUnit position, const ContainingBlockCache& cache)
37073720{
37083721 LayoutUnit logicalLeft = logicalLeftOffsetForLine(position, false);
37093722 if (logicalLeft == logicalLeftOffsetForContent()) {
3710  if (rootBlock != this)
 3723 if (rootBlock != this) {
37113724 // The border can potentially be further extended by our containingBlock().
3712  return containingBlock()->logicalLeftSelectionOffset(rootBlock, position + logicalTop());
 3725 ASSERT(containingBlock() == cache.containingBlock(this));
 3726 ASSERT(cache.parentCache());
 3727 return cache.containingBlock(this)->logicalLeftSelectionOffset(rootBlock, position + logicalTop(), *cache.parentCache());
 3728 }
37133729 return logicalLeft;
37143730 } else {
37153731 RenderBlock* cb = this;
 3732 const ContainingBlockCache* currentCache = &cache;
37163733 while (cb != rootBlock) {
37173734 logicalLeft += cb->logicalLeft();
3718  cb = cb->containingBlock();
 3735
 3736 ASSERT(currentCache);
 3737 ASSERT(cb->containingBlock() == currentCache->containingBlock(cb));
 3738 cb = currentCache->containingBlock(cb);
 3739 currentCache = currentCache->parentCache();
37193740 }
37203741 }
37213742 return logicalLeft;
37223743}
37233744
3724 LayoutUnit RenderBlock::logicalRightSelectionOffset(RenderBlock* rootBlock, LayoutUnit position)
 3745LayoutUnit RenderBlock::logicalRightSelectionOffset(RenderBlock* rootBlock, LayoutUnit position, const ContainingBlockCache& cache)
37253746{
37263747 LayoutUnit logicalRight = logicalRightOffsetForLine(position, false);
37273748 if (logicalRight == logicalRightOffsetForContent()) {
3728  if (rootBlock != this)
 3749 if (rootBlock != this) {
37293750 // The border can potentially be further extended by our containingBlock().
3730  return containingBlock()->logicalRightSelectionOffset(rootBlock, position + logicalTop());
 3751 ASSERT(containingBlock() == cache.containingBlock(this));
 3752 ASSERT(cache.parentCache());
 3753 return cache.containingBlock(this)->logicalRightSelectionOffset(rootBlock, position + logicalTop(), *cache.parentCache());
 3754 }
37313755 return logicalRight;
37323756 } else {
37333757 RenderBlock* cb = this;
 3758 const ContainingBlockCache* currentCache = &cache;
37343759 while (cb != rootBlock) {
37353760 logicalRight += cb->logicalLeft();
3736  cb = cb->containingBlock();
 3761
 3762 ASSERT(currentCache);
 3763 ASSERT(cb->containingBlock() == currentCache->containingBlock(cb));
 3764 cb = currentCache->containingBlock(cb);
 3765 currentCache = currentCache->parentCache();
37373766 }
37383767 }
37393768 return logicalRight;
148767

Source/WebCore/rendering/RenderBlock.h

4242namespace WebCore {
4343
4444class BidiContext;
 45class ContainingBlockCache;
4546class InlineIterator;
4647class LayoutStateMaintainer;
4748class LineLayoutState;

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 ContainingBlockCache& cache, 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 ContainingBlockCache& cache, const PaintInfo*);
249250 void getSelectionGapInfo(SelectionState, bool& leftGap, bool& rightGap);
250251 RenderBlock* blockBeforeWithinSelectionRoot(LayoutSize& offset) const;
251252

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 ContainingBlockCache&, 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 ContainingBlockCache&, 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 ContainingBlockCache&, 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 ContainingBlockCache&, const PaintInfo*);
 939 LayoutUnit logicalLeftSelectionOffset(RenderBlock* rootBlock, LayoutUnit position, const ContainingBlockCache&);
 940 LayoutUnit logicalRightSelectionOffset(RenderBlock* rootBlock, LayoutUnit position, const ContainingBlockCache&);
940941
941942 virtual void absoluteRects(Vector<IntRect>&, const LayoutPoint& accumulatedOffset) const;
942943 virtual void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const;
148767

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 /* ContainingBlockCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 9BA273F3172206BB0097CE47 /* ContainingBlockCache.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, ); }; };

97759776 9B6C41521344949000085B62 /* StringWithDirection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StringWithDirection.h; sourceTree = "<group>"; };
97769777 9B7E78BA16F16CAE00126914 /* HTMLTreeBuilderSimulator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = HTMLTreeBuilderSimulator.cpp; path = parser/HTMLTreeBuilderSimulator.cpp; sourceTree = "<group>"; };
97779778 9B7E78BB16F16CAE00126914 /* HTMLTreeBuilderSimulator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HTMLTreeBuilderSimulator.h; path = parser/HTMLTreeBuilderSimulator.h; sourceTree = "<group>"; };
 9779 9BA273F3172206BB0097CE47 /* ContainingBlockCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContainingBlockCache.h; sourceTree = "<group>"; };
97789780 9BAB6C6A12550631001626D4 /* EditingStyle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EditingStyle.h; sourceTree = "<group>"; };
97799781 9BAB6C6B12550631001626D4 /* EditingStyle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EditingStyle.cpp; sourceTree = "<group>"; };
97809782 9BAF3B2312C1A39800014BF1 /* WritingDirection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WritingDirection.h; sourceTree = "<group>"; };

2010720109 458FE4071589DF0B005609E6 /* RenderSearchField.cpp */,
2010820110 458FE4081589DF0B005609E6 /* RenderSearchField.h */,
2010920111 0F11A54E0F39233100C37884 /* RenderSelectionInfo.h */,
 20112 9BA273F3172206BB0097CE47 /* ContainingBlockCache.h */,
2011020113 AB247A6A0AFD6383003FA5FD /* RenderSlider.cpp */,
2011120114 AB247A6B0AFD6383003FA5FD /* RenderSlider.h */,
2011220115 31E8D8BA160BC94B004CE8F5 /* RenderSnapshottedPlugIn.cpp */,

2404924052 E1B533491717DEE300F205F9 /* CachedRawResourceClient.h in Headers */,
2405024053 BE88E0C21715CE2600658D98 /* TrackListBase.h in Headers */,
2405124054 FB484F4D171F821E00040755 /* TransformFunctions.h in Headers */,
 24055 9BA273F4172206BB0097CE47 /* ContainingBlockCache.h in Headers */,
2405224056 );
2405324057 runOnlyForDeploymentPostprocessing = 0;
2405424058 };
148767