diff options
Diffstat (limited to 'Source/WebCore/rendering/RenderBlock.cpp')
| -rwxr-xr-x | Source/WebCore/rendering/RenderBlock.cpp | 349 | 
1 files changed, 237 insertions, 112 deletions
diff --git a/Source/WebCore/rendering/RenderBlock.cpp b/Source/WebCore/rendering/RenderBlock.cpp index 9b2bca5a9..413c60ece 100755 --- a/Source/WebCore/rendering/RenderBlock.cpp +++ b/Source/WebCore/rendering/RenderBlock.cpp @@ -114,8 +114,8 @@ RenderBlock::MarginInfo::MarginInfo(RenderBlock* block, LayoutUnit beforeBorderP      m_quirkContainer = block->isTableCell() || block->isBody() || blockStyle->marginBeforeCollapse() == MDISCARD          || blockStyle->marginAfterCollapse() == MDISCARD; -    m_positiveMargin = m_canCollapseMarginBeforeWithChildren ? block->maxPositiveMarginBefore() : 0; -    m_negativeMargin = m_canCollapseMarginBeforeWithChildren ? block->maxNegativeMarginBefore() : 0; +    m_positiveMargin = m_canCollapseMarginBeforeWithChildren ? block->maxPositiveMarginBefore() : zeroLayoutUnit; +    m_negativeMargin = m_canCollapseMarginBeforeWithChildren ? block->maxNegativeMarginBefore() : zeroLayoutUnit;  }  // ------------------------------------------------------------------------------------------------------- @@ -429,14 +429,24 @@ void RenderBlock::addChildToAnonymousColumnBlocks(RenderObject* newChild, Render  RenderBlock* RenderBlock::containingColumnsBlock(bool allowAnonymousColumnBlock)  { +    RenderBlock* firstChildIgnoringAnonymousWrappers = 0;      for (RenderObject* curr = this; curr; curr = curr->parent()) {          if (!curr->isRenderBlock() || curr->isFloatingOrPositioned() || curr->isTableCell() || curr->isRoot() || curr->isRenderView() || curr->hasOverflowClip()              || curr->isInlineBlockOrInlineTable())              return 0; + +        // FIXME: Table manages its own table parts, most of which are RenderBoxes. +        // Multi-column code cannot handle splitting the flow in table. Disabling it +        // to prevent crashes. +        if (curr->isTable()) +            return 0;          RenderBlock* currBlock = toRenderBlock(curr); +        if (!currBlock->createsAnonymousWrapper()) +            firstChildIgnoringAnonymousWrappers = currBlock; +          if (currBlock->style()->specifiesColumns() && (allowAnonymousColumnBlock || !currBlock->isAnonymousColumnsBlock())) -            return currBlock; +            return firstChildIgnoringAnonymousWrappers;          if (currBlock->isAnonymousColumnSpanBlock())              return 0; @@ -447,15 +457,20 @@ RenderBlock* RenderBlock::containingColumnsBlock(bool allowAnonymousColumnBlock)  RenderBlock* RenderBlock::clone() const  {      RenderBlock* cloneBlock; -    if (isAnonymousBlock()) +    if (isAnonymousBlock()) {          cloneBlock = createAnonymousBlock(); +        cloneBlock->setChildrenInline(childrenInline()); +    }      else { -        cloneBlock = new (renderArena()) RenderBlock(node()); +        RenderObject* cloneRenderer = node()->createRenderer(renderArena(), style()); +        cloneBlock = toRenderBlock(cloneRenderer);          cloneBlock->setStyle(style()); -        if (!childrenInline() && cloneBlock->firstChild() && cloneBlock->firstChild()->isInline()) -            cloneBlock->makeChildrenNonInline(); + +        // This takes care of setting the right value of childrenInline in case +        // generated content is added to cloneBlock and 'this' does not have +        // generated content added yet. +        cloneBlock->setChildrenInline(cloneBlock->firstChild() ? cloneBlock->firstChild()->isInline() : childrenInline());      } -    cloneBlock->setChildrenInline(childrenInline());      return cloneBlock;  } @@ -468,10 +483,16 @@ void RenderBlock::splitBlocks(RenderBlock* fromBlock, RenderBlock* toBlock,      if (!isAnonymousBlock())          cloneBlock->setContinuation(oldCont); -    // Now take all of the children from beforeChild to the end and remove -    // them from |this| and place them in the clone.      if (!beforeChild && isAfterContent(lastChild()))          beforeChild = lastChild(); + +    // If we are moving inline children from |this| to cloneBlock, then we need +    // to clear our line box tree. +    if (beforeChild && childrenInline()) +        deleteLineBoxTree(); + +    // Now take all of the children from beforeChild to the end and remove +    // them from |this| and place them in the clone.      moveChildrenTo(cloneBlock, beforeChild, 0, true);      // Hook |clone| up as the continuation of the middle block. @@ -494,7 +515,7 @@ void RenderBlock::splitBlocks(RenderBlock* fromBlock, RenderBlock* toBlock,          cloneBlock = blockCurr->clone();          // Insert our child clone as the first child. -        cloneBlock->children()->appendChildNode(cloneBlock, cloneChild); +        cloneBlock->addChildIgnoringContinuation(cloneChild, 0);          // Hook the clone up as a continuation of |curr|.  Note we do encounter          // anonymous blocks possibly as we walk up the block chain.  When we split an @@ -585,6 +606,9 @@ void RenderBlock::splitFlow(RenderObject* beforeChild, RenderBlock* newBlockBox,  RenderObject* RenderBlock::splitAnonymousBlocksAroundChild(RenderObject* beforeChild)  { +    if (beforeChild->isTablePart()) +        beforeChild = splitTablePartsAroundChild(beforeChild); +      while (beforeChild->parent() != this) {          RenderBlock* blockToSplit = toRenderBlock(beforeChild->parent());          if (blockToSplit->firstChild() != beforeChild) { @@ -603,6 +627,71 @@ RenderObject* RenderBlock::splitAnonymousBlocksAroundChild(RenderObject* beforeC      return beforeChild;  } +static void markTableForSectionAndCellRecalculation(RenderObject* child) +{ +    RenderObject* curr = child; +    while (!curr->isTable()) { +        if (curr->isTableSection()) +            toRenderTableSection(curr)->setNeedsCellRecalc(); +        curr = curr->parent(); +    } + +    RenderTable* table = toRenderTable(curr); +    table->setNeedsSectionRecalc(); +    table->setNeedsLayoutAndPrefWidthsRecalc(); +} + +static void moveAllTableChildrenTo(RenderObject* fromTablePart, RenderTable* toTable, RenderObject* startChild) +{ +    for (RenderObject* curr = startChild; curr;) { +        // Need to store next sibling as we won't have access to it +        // after we are removed from table. +        RenderObject* next = curr->nextSibling(); +        fromTablePart->removeChild(curr); +        toTable->addChild(curr); +        if (curr->isTableSection()) +            toRenderTableSection(curr)->setNeedsCellRecalc(); +        curr->setNeedsLayoutAndPrefWidthsRecalc(); +        curr = next;  +    } + +    // This marks fromTable for section and cell recalculation. +    markTableForSectionAndCellRecalculation(fromTablePart); + +    // startChild is now part of toTable. This marks toTable for section and cell recalculation. +    markTableForSectionAndCellRecalculation(startChild); +} + +RenderObject* RenderBlock::splitTablePartsAroundChild(RenderObject* beforeChild) +{ +    ASSERT(beforeChild->isTablePart()); + +    while (beforeChild->parent() != this) { +        RenderObject* tablePartToSplit = beforeChild->parent(); +        if (!tablePartToSplit->isTablePart() && !tablePartToSplit->isTable()) +            break; +        if (tablePartToSplit->firstChild() != beforeChild) { +            // Get our table container. +            RenderObject* curr = tablePartToSplit; +            while (!curr->isTable()) +                curr = curr->parent(); +            RenderTable* table = toRenderTable(curr); + +            // Create an anonymous table container next to our table container. +            RenderBlock* parentBlock = toRenderBlock(table->parent()); +            RenderTable* postTable = parentBlock->createAnonymousTable(); +            parentBlock->children()->insertChildNode(parentBlock, postTable, table->nextSibling()); +             +            // Move all the children from beforeChild to the newly created anonymous table container. +            moveAllTableChildrenTo(tablePartToSplit, postTable, beforeChild); + +            beforeChild = postTable; +        } else +            beforeChild = tablePartToSplit; +    } +    return beforeChild; +} +  void RenderBlock::makeChildrenAnonymousColumnBlocks(RenderObject* beforeChild, RenderBlock* newBlockBox, RenderObject* newChild)  {      RenderBlock* pre = 0; @@ -669,22 +758,17 @@ RenderBlock* RenderBlock::columnsBlockForSpanningElement(RenderObject* newChild)      RenderBlock* columnsBlockAncestor = 0;      if (!newChild->isText() && newChild->style()->columnSpan() && !newChild->isBeforeOrAfterContent()          && !newChild->isFloatingOrPositioned() && !newChild->isInline() && !isAnonymousColumnSpanBlock()) { -        if (style()->specifiesColumns()) -            columnsBlockAncestor = this; -        else if (!isInline() && parent() && parent()->isRenderBlock()) { -            columnsBlockAncestor = toRenderBlock(parent())->containingColumnsBlock(false); -             -            if (columnsBlockAncestor) { -                // Make sure that none of the parent ancestors have a continuation. -                // If yes, we do not want split the block into continuations. -                RenderObject* curr = this; -                while (curr && curr != columnsBlockAncestor) { -                    if (curr->isRenderBlock() && toRenderBlock(curr)->continuation()) { -                        columnsBlockAncestor = 0; -                        break; -                    } -                    curr = curr->parent(); +        columnsBlockAncestor = containingColumnsBlock(false); +        if (columnsBlockAncestor) { +            // Make sure that none of the parent ancestors have a continuation. +            // If yes, we do not want split the block into continuations. +            RenderObject* curr = this; +            while (curr && curr != columnsBlockAncestor) { +                if (curr->isRenderBlock() && toRenderBlock(curr)->continuation()) { +                    columnsBlockAncestor = 0; +                    break;                  } +                curr = curr->parent();              }          }      } @@ -697,35 +781,48 @@ void RenderBlock::addChildIgnoringAnonymousColumnBlocks(RenderObject* newChild,      if (!beforeChild)          beforeChild = afterPseudoElementRenderer(); -    // If the requested beforeChild is not one of our children, then this is because -    // there is an anonymous container within this object that contains the beforeChild.      if (beforeChild && beforeChild->parent() != this) { -        RenderObject* beforeChildAnonymousContainer = anonymousContainer(beforeChild); -        ASSERT(beforeChildAnonymousContainer); -        ASSERT(beforeChildAnonymousContainer->isAnonymous()); - -        if (beforeChildAnonymousContainer->isAnonymousBlock()) { -            // Insert the child into the anonymous block box instead of here. -            if (newChild->isInline() || beforeChild->parent()->firstChild() != beforeChild) -                beforeChild->parent()->addChild(newChild, beforeChild); -            else -                addChild(newChild, beforeChild->parent()); -            return; -        } +        RenderObject* beforeChildContainer = beforeChild->parent(); +        while (beforeChildContainer->parent() != this) +            beforeChildContainer = beforeChildContainer->parent(); +        ASSERT(beforeChildContainer); + +        if (beforeChildContainer->isAnonymous()) { +            // If the requested beforeChild is not one of our children, then this is because +            // there is an anonymous container within this object that contains the beforeChild. +            RenderObject* beforeChildAnonymousContainer = beforeChildContainer; +            if (beforeChildAnonymousContainer->isAnonymousBlock()) { +                // Insert the child into the anonymous block box instead of here. +                if (newChild->isInline() || beforeChild->parent()->firstChild() != beforeChild) +                    beforeChild->parent()->addChild(newChild, beforeChild); +                else +                    addChild(newChild, beforeChild->parent()); +                return; +            } -        ASSERT(beforeChildAnonymousContainer->isTable()); -        if ((newChild->isTableCol() && newChild->style()->display() == TABLE_COLUMN_GROUP) -                || (newChild->isTableCaption()) -                || newChild->isTableSection() -                || newChild->isTableRow() -                || newChild->isTableCell()) { -            // Insert into the anonymous table. -            beforeChildAnonymousContainer->addChild(newChild, beforeChild); -            return; -        } +            ASSERT(beforeChildAnonymousContainer->isTable()); +            if (newChild->isTablePart()) { +                // Insert into the anonymous table. +                beforeChildAnonymousContainer->addChild(newChild, beforeChild); +                return; +            } + +            beforeChild = splitTablePartsAroundChild(beforeChild); -        // Go on to insert before the anonymous table. -        beforeChild = beforeChildAnonymousContainer; +            ASSERT(beforeChild->parent() == this); +            if (beforeChild->parent() != this) { +                // We should never reach here. If we do, we need to use the +                // safe fallback to use the topmost beforeChild container. +                beforeChild = beforeChildContainer; +            } +        } else { +            // We will reach here when beforeChild is a run-in element. +            // If run-in element precedes a block-level element, it becomes the +            // the first inline child of that block level element. The insertion +            // point will be before that block-level element. +            ASSERT(beforeChild->isRunIn()); +            beforeChild = beforeChildContainer; +        }      }      // Check for a spanning element in columns. @@ -885,23 +982,27 @@ RootInlineBox* RenderBlock::createAndAppendRootInlineBox()      return rootBox;  } -void RenderBlock::moveChildTo(RenderBlock* to, RenderObject* child, RenderObject* beforeChild, bool fullRemoveInsert) +void RenderBlock::moveChildTo(RenderBlock* toBlock, RenderObject* child, RenderObject* beforeChild, bool fullRemoveInsert)  {      ASSERT(this == child->parent()); -    ASSERT(!beforeChild || to == beforeChild->parent()); -    to->children()->insertChildNode(to, children()->removeChildNode(this, child, fullRemoveInsert), beforeChild, fullRemoveInsert); +    ASSERT(!beforeChild || toBlock == beforeChild->parent()); +    if (fullRemoveInsert) { +        // Takes care of adding the new child correctly if toBlock and fromBlock +        // have different kind of children (block vs inline). +        toBlock->addChildIgnoringContinuation(children()->removeChildNode(this, child), beforeChild); +    } else +        toBlock->children()->insertChildNode(toBlock, children()->removeChildNode(this, child, false), beforeChild, false);  } -void RenderBlock::moveChildrenTo(RenderBlock* to, RenderObject* startChild, RenderObject* endChild, RenderObject* beforeChild, bool fullRemoveInsert) +void RenderBlock::moveChildrenTo(RenderBlock* toBlock, RenderObject* startChild, RenderObject* endChild, RenderObject* beforeChild, bool fullRemoveInsert)  { -    ASSERT(!beforeChild || to == beforeChild->parent()); -    RenderObject* nextChild = startChild; -    while (nextChild && nextChild != endChild) { -        RenderObject* child = nextChild; -        nextChild = child->nextSibling(); -        to->children()->insertChildNode(to, children()->removeChildNode(this, child, fullRemoveInsert), beforeChild, fullRemoveInsert); -        if (child == endChild) -            return; +    ASSERT(!beforeChild || toBlock == beforeChild->parent()); + +    for (RenderObject* child = startChild; child && child != endChild; ) { +        // Save our next sibling as moveChildTo will clear it. +        RenderObject* nextSibling = child->nextSibling(); +        moveChildTo(toBlock, child, beforeChild, fullRemoveInsert); +        child = nextSibling;      }  } @@ -1025,11 +1126,15 @@ void RenderBlock::collapseAnonymousBoxChild(RenderBlock* parent, RenderObject* c      parent->setNeedsLayoutAndPrefWidthsRecalc();      parent->setChildrenInline(child->childrenInline());      RenderObject* nextSibling = child->nextSibling(); + +    RenderFlowThread* childFlowThread = child->enclosingRenderFlowThread();      RenderBlock* anonBlock = toRenderBlock(parent->children()->removeChildNode(parent, child, child->hasLayer()));      anonBlock->moveAllChildrenTo(parent, nextSibling, child->hasLayer());      // Delete the now-empty block's lines and nuke it.      if (!parent->documentBeingDestroyed())          anonBlock->deleteLineBoxTree(); +    if (childFlowThread && !parent->documentBeingDestroyed()) +        childFlowThread->removeFlowChildInfo(anonBlock);      anonBlock->destroy();  } @@ -1419,7 +1524,7 @@ void RenderBlock::layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeigh          if (hasOverflowClip()) {              // Adjust repaint rect for scroll offset -            repaintRect.move(-layer()->scrolledContentOffset()); +            repaintRect.move(-scrolledContentOffset());              // Don't allow this rect to spill out of our overflow box.              repaintRect.intersect(LayoutRect(LayoutPoint(), size())); @@ -1427,7 +1532,6 @@ void RenderBlock::layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeigh          // Make sure the rect is still non-empty after intersecting for overflow above          if (!repaintRect.isEmpty()) { -            // FIXME: Might need rounding once we switch to float, see https://bugs.webkit.org/show_bug.cgi?id=64021              repaintRectangle(repaintRect); // We need to do a partial repaint of our content.              if (hasReflection())                  repaintRectangle(reflectedRect(repaintRect)); @@ -1488,6 +1592,9 @@ void RenderBlock::computeOverflow(LayoutUnit oldClientAfterEdge, bool recomputeF      // Add visual overflow from theme.      addVisualOverflowFromTheme(); + +    if (isRenderFlowThread()) +        enclosingRenderFlowThread()->computeOverflowStateForRegions(oldClientAfterEdge);  }  void RenderBlock::addOverflowFromBlockChildren() @@ -1591,7 +1698,7 @@ void RenderBlock::adjustFloatingBlock(const MarginInfo& marginInfo)      // for by simply calling canCollapseWithMarginBefore.  See      // http://www.hixie.ch/tests/adhoc/css/box/block/margin-collapse/046.html for      // an example of this scenario. -    LayoutUnit marginOffset = marginInfo.canCollapseWithMarginBefore() ? 0 : marginInfo.margin(); +    LayoutUnit marginOffset = marginInfo.canCollapseWithMarginBefore() ? zeroLayoutUnit : marginInfo.margin();      setLogicalHeight(logicalHeight() + marginOffset);      positionNewFloats();      setLogicalHeight(logicalHeight() - marginOffset); @@ -1893,7 +2000,6 @@ LayoutUnit RenderBlock::computeStartPositionDeltaForChildAvoidingFloats(const Re          if (childMarginStart < 0)              startOff += childMarginStart;          newPosition = max(newPosition, startOff); // Let the float sit in the child's margin if it can fit. -        // FIXME: Needs to use epsilon once we switch to float, see https://bugs.webkit.org/show_bug.cgi?id=64021      } else if (startOff != startPosition) {          // The object is shifting to the "end" side of the block. The object might be centered, so we need to          // recalculate our inline direction margins. Note that the containing block content @@ -2440,7 +2546,7 @@ void RenderBlock::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)      // z-index.  We paint after we painted the background/border, so that the scrollbars will      // sit above the background/border.      if (hasOverflowClip() && style()->visibility() == VISIBLE && (phase == PaintPhaseBlockBackground || phase == PaintPhaseChildBlockBackground) && paintInfo.shouldPaintWithinRoot(this)) -        layer()->paintOverflowControls(paintInfo.context, adjustedPaintOffset, paintInfo.rect); +        layer()->paintOverflowControls(paintInfo.context, roundedIntPoint(adjustedPaintOffset), paintInfo.rect);  }  void RenderBlock::paintColumnRules(PaintInfo& paintInfo, const LayoutPoint& paintOffset) @@ -2463,9 +2569,9 @@ void RenderBlock::paintColumnRules(PaintInfo& paintInfo, const LayoutPoint& pain      bool antialias = shouldAntialiasLines(paintInfo.context);      if (colInfo->progressionAxis() == ColumnInfo::InlineAxis) { -        LayoutUnit currLogicalLeftOffset = style()->isLeftToRightDirection() ? 0 : contentLogicalWidth(); +        LayoutUnit currLogicalLeftOffset = style()->isLeftToRightDirection() ? zeroLayoutUnit : contentLogicalWidth();          LayoutUnit ruleAdd = logicalLeftOffsetForContent(); -        LayoutUnit ruleLogicalLeft = style()->isLeftToRightDirection() ? 0 : contentLogicalWidth(); +        LayoutUnit ruleLogicalLeft = style()->isLeftToRightDirection() ? zeroLayoutUnit : contentLogicalWidth();          LayoutUnit inlineDirectionSize = colInfo->desiredColumnWidth();          BoxSide boxSide = isHorizontalWritingMode()              ? style()->isLeftToRightDirection() ? BSLeft : BSRight @@ -2487,7 +2593,8 @@ void RenderBlock::paintColumnRules(PaintInfo& paintInfo, const LayoutPoint& pain                  LayoutUnit ruleRight = isHorizontalWritingMode() ? ruleLeft + ruleThickness : ruleLeft + contentWidth();                  LayoutUnit ruleTop = isHorizontalWritingMode() ? paintOffset.y() + borderTop() + paddingTop() : paintOffset.y() + ruleLogicalLeft - ruleThickness / 2 + ruleAdd;                  LayoutUnit ruleBottom = isHorizontalWritingMode() ? ruleTop + contentHeight() : ruleTop + ruleThickness; -                drawLineForBoxSide(paintInfo.context, ruleLeft, ruleTop, ruleRight, ruleBottom, boxSide, ruleColor, ruleStyle, 0, 0, antialias); +                IntRect pixelSnappedRuleRect = pixelSnappedIntRectFromEdges(ruleLeft, ruleTop, ruleRight, ruleBottom); +                drawLineForBoxSide(paintInfo.context, pixelSnappedRuleRect.x(), pixelSnappedRuleRect.y(), pixelSnappedRuleRect.maxX(), pixelSnappedRuleRect.maxY(), boxSide, ruleColor, ruleStyle, 0, 0, antialias);              }              ruleLogicalLeft = currLogicalLeftOffset; @@ -2512,7 +2619,8 @@ void RenderBlock::paintColumnRules(PaintInfo& paintInfo, const LayoutPoint& pain          for (unsigned i = 1; i < colCount; i++) {              ruleRect.move(step); -            drawLineForBoxSide(paintInfo.context, ruleRect.x(), ruleRect.y(), ruleRect.maxX(), ruleRect.maxY(), boxSide, ruleColor, ruleStyle, 0, 0, antialias); +            IntRect pixelSnappedRuleRect = pixelSnappedIntRect(ruleRect); +            drawLineForBoxSide(paintInfo.context, pixelSnappedRuleRect.x(), pixelSnappedRuleRect.y(), pixelSnappedRuleRect.maxX(), pixelSnappedRuleRect.maxY(), boxSide, ruleColor, ruleStyle, 0, 0, antialias);          }      }  } @@ -2540,7 +2648,7 @@ void RenderBlock::paintColumnContents(PaintInfo& paintInfo, const LayoutPoint& p          }          colRect.moveBy(paintOffset);          PaintInfo info(paintInfo); -        info.rect.intersect(colRect); +        info.rect.intersect(pixelSnappedIntRect(colRect));          if (!info.rect.isEmpty()) {              GraphicsContextStateSaver stateSaver(*context); @@ -2680,7 +2788,7 @@ void RenderBlock::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffs      // Adjust our painting position if we're inside a scrolled layer (e.g., an overflow:auto div).      LayoutPoint scrolledOffset = paintOffset;      if (hasOverflowClip()) -        scrolledOffset.move(-layer()->scrolledContentOffset()); +        scrolledOffset.move(-scrolledContentOffset());      // 2. paint contents      if (paintPhase != PaintPhaseSelfOutline) { @@ -2928,7 +3036,7 @@ GapRects RenderBlock::selectionGapRectsForRepaint(RenderBoxModelObject* repaintC      LayoutPoint offsetFromRepaintContainer = roundedLayoutPoint(transformState.mappedPoint());      if (hasOverflowClip()) -        offsetFromRepaintContainer -= layer()->scrolledContentOffset(); +        offsetFromRepaintContainer -= scrolledContentOffset();      LayoutUnit lastTop = 0;      LayoutUnit lastLeft = logicalLeftSelectionOffset(this, lastTop); @@ -2953,7 +3061,8 @@ void RenderBlock::paintSelection(PaintInfo& paintInfo, const LayoutPoint& paintO                      LayoutRect localBounds(gapRectsBounds);                      flipForWritingMode(localBounds);                      gapRectsBounds = localToContainerQuad(FloatRect(localBounds), layer->renderer()).enclosingBoundingBox(); -                    gapRectsBounds.move(layer->scrolledContentOffset()); +                    if (layer->renderer()->hasOverflowClip()) +                        gapRectsBounds.move(layer->renderBox()->scrolledContentOffset());                  }                  layer->addBlockSelectionGapsBounds(gapRectsBounds);              } @@ -3019,7 +3128,7 @@ GapRects RenderBlock::selectionGaps(RenderBlock* rootBlock, const LayoutPoint& r                                      r->m_renderer->width(), r->m_renderer->height());                  rootBlock->flipForWritingMode(floatBox);                  floatBox.move(rootBlockPhysicalPosition.x(), rootBlockPhysicalPosition.y()); -                paintInfo->context->clipOut(floatBox); +                paintInfo->context->clipOut(pixelSnappedIntRect(floatBox));              }          }      } @@ -3769,7 +3878,7 @@ LayoutUnit RenderBlock::nextFloatLogicalBottomBelow(LayoutUnit logicalHeight) co              bottom = min(floatBottom, bottom);      } -    return bottom == numeric_limits<LayoutUnit>::max() ? 0 : bottom; +    return bottom == numeric_limits<LayoutUnit>::max() ? zeroLayoutUnit : bottom;  }  LayoutUnit RenderBlock::lowestFloatLogicalBottom(FloatingObject::Type floatType) const @@ -4087,7 +4196,7 @@ bool RenderBlock::avoidsFloats() const      return RenderBox::avoidsFloats() || !style()->hasAutoColumnCount() || !style()->hasAutoColumnWidth();  } -bool RenderBlock::containsFloat(RenderBox* renderer) +bool RenderBlock::containsFloat(RenderBox* renderer) const  {      return m_floatingObjects && m_floatingObjects->set().contains<RenderBox*, FloatingObjectHashTranslator>(renderer);  } @@ -4166,13 +4275,11 @@ LayoutUnit RenderBlock::getClearDelta(RenderBox* child, LayoutUnit logicalTop)      }      // We also clear floats if we are too big to sit on the same line as a float (and wish to avoid floats by default). -    LayoutUnit result = clearSet ? max<LayoutUnit>(0, logicalBottom - logicalTop) : 0; +    LayoutUnit result = clearSet ? max<LayoutUnit>(0, logicalBottom - logicalTop) : zeroLayoutUnit;      if (!result && child->avoidsFloats()) {          LayoutUnit newLogicalTop = logicalTop;          while (true) {              LayoutUnit availableLogicalWidthAtNewLogicalTopOffset = availableLogicalWidthForLine(newLogicalTop, false); -            // FIXME: Change to use roughlyEquals when we move to float. -            // See https://bugs.webkit.org/show_bug.cgi?id=66148              if (availableLogicalWidthAtNewLogicalTopOffset == availableLogicalWidthForContent(newLogicalTop))                  return newLogicalTop - logicalTop; @@ -4193,8 +4300,6 @@ LayoutUnit RenderBlock::getClearDelta(RenderBox* child, LayoutUnit logicalTop)              child->setMarginLeft(childOldMarginLeft);              child->setMarginRight(childOldMarginRight); -            // FIXME: Change to use roughlyEquals when we move to float. -            // See https://bugs.webkit.org/show_bug.cgi?id=66148              if (childLogicalWidthAtNewLogicalTopOffset <= availableLogicalWidthAtNewLogicalTopOffset)                  return newLogicalTop - logicalTop; @@ -4245,9 +4350,8 @@ bool RenderBlock::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu      if (checkChildren) {          // Hit test descendants first.          LayoutSize scrolledOffset(localOffset); -        if (hasOverflowClip()) { -            scrolledOffset -= layer()->scrolledContentOffset(); -        } +        if (hasOverflowClip()) +            scrolledOffset -= scrolledContentOffset();          // Hit test contents if we don't have columns.          if (!hasColumns()) { @@ -4594,7 +4698,7 @@ VisiblePosition RenderBlock::positionForPoint(const LayoutPoint& point)  void RenderBlock::offsetForContents(LayoutPoint& offset) const  {      if (hasOverflowClip()) -        offset += layer()->scrolledContentOffset(); +        offset += scrolledContentOffset();      if (hasColumns())          adjustPointToColumnContents(offset); @@ -5005,6 +5109,8 @@ void RenderBlock::computePreferredLogicalWidths()          }          int scrollbarWidth = 0; +        // FIXME: This should only be done for horizontal writing mode. +        // For vertical writing mode, this should check overflowX and use the horizontalScrollbarHeight.          if (hasOverflowClip() && styleToUse->overflowY() == OSCROLL) {              layer()->setHasVerticalScrollbar(true);              scrollbarWidth = verticalScrollbarWidth(); @@ -5150,7 +5256,7 @@ void RenderBlock::computeInlinePreferredLogicalWidths()      RenderStyle* styleToUse = style();      RenderBlock* containingBlock = this->containingBlock(); -    LayoutUnit cw = containingBlock ? containingBlock->contentLogicalWidth() : 0; +    LayoutUnit cw = containingBlock ? containingBlock->contentLogicalWidth() : zeroLayoutUnit;      // If we are at the start of a line, we want to ignore all white-space.      // Also strip spaces if we previously had text that ended in a trailing space. @@ -5704,6 +5810,36 @@ static inline bool shouldSkipForFirstLetter(UChar c)      return isSpaceOrNewline(c) || c == noBreakSpace || isPunctuationForFirstLetter(c);  } +// We only honor first-letter if  +// - the firstLetterBlock can have children in the DOM and +// - the block doesn't have any special assumption on its text children. +// This correctly prevents form controls from honoring first-letter. +static inline bool isSafeToCreateFirstLetterRendererOn(RenderObject* renderer) +{ +    return (renderer->canHaveChildren() +            && !(renderer->isDeprecatedFlexibleBox() +                 && static_cast<RenderDeprecatedFlexibleBox*>(renderer)->buttonText())); +} + +static inline RenderObject* findFirstLetterBlock(RenderBlock* start) +{ +    RenderObject* firstLetterBlock = start; +    while (true) { +        bool canHaveFirstLetterRenderer = firstLetterBlock->style()->hasPseudoStyle(FIRST_LETTER) +            && isSafeToCreateFirstLetterRendererOn(firstLetterBlock); +        if (canHaveFirstLetterRenderer) +            return firstLetterBlock; + +        RenderObject* parentBlock = firstLetterBlock->parent(); +        if (firstLetterBlock->isReplaced() || !parentBlock || parentBlock->firstChild() != firstLetterBlock ||  +            !parentBlock->isBlockFlow()) +            return 0; +        firstLetterBlock = parentBlock; +    }  + +    return 0; +} +     void RenderBlock::updateFirstLetter()  {      if (!document()->usesFirstLetterRules()) @@ -5714,23 +5850,8 @@ void RenderBlock::updateFirstLetter()      // FIXME: We need to destroy the first-letter object if it is no longer the first child.  Need to find      // an efficient way to check for that situation though before implementing anything. -    RenderObject* firstLetterBlock = this; -    bool hasPseudoStyle = false; -    while (true) { -        // We only honor first-letter if the firstLetterBlock can have children in the DOM. This correctly  -        // prevents form controls from honoring first-letter. -        hasPseudoStyle = firstLetterBlock->style()->hasPseudoStyle(FIRST_LETTER)  -            && firstLetterBlock->canHaveChildren(); -        if (hasPseudoStyle) -            break; -        RenderObject* parentBlock = firstLetterBlock->parent(); -        if (firstLetterBlock->isReplaced() || !parentBlock || parentBlock->firstChild() != firstLetterBlock ||  -            !parentBlock->isBlockFlow()) -            break; -        firstLetterBlock = parentBlock; -    }  - -    if (!hasPseudoStyle)  +    RenderObject* firstLetterBlock = findFirstLetterBlock(this); +    if (!firstLetterBlock)          return;      // Drill into inlines looking for our first text child. @@ -5922,7 +6043,7 @@ static int getHeightForLineCount(RenderBlock* block, int l, bool includeBottom,          if (block->childrenInline()) {              for (RootInlineBox* box = block->firstRootBox(); box; box = box->nextRootBox()) {                  if (++count == l) -                    return box->lineBottom() + (includeBottom ? (block->borderBottom() + block->paddingBottom()) : 0); +                    return box->lineBottom() + (includeBottom ? (block->borderBottom() + block->paddingBottom()) : zeroLayoutUnit);              }          }          else { @@ -5931,7 +6052,7 @@ static int getHeightForLineCount(RenderBlock* block, int l, bool includeBottom,                  if (shouldCheckLines(obj)) {                      int result = getHeightForLineCount(toRenderBlock(obj), l, false, count);                      if (result != -1) -                        return result + obj->y() + (includeBottom ? (block->borderBottom() + block->paddingBottom()) : 0); +                        return result + obj->y() + (includeBottom ? (block->borderBottom() + block->paddingBottom()) : zeroLayoutUnit);                  }                  else if (!obj->isFloatingOrPositioned() && !obj->isRunIn())                      normalFlowChildWithoutLines = obj; @@ -6495,11 +6616,15 @@ LayoutUnit RenderBlock::pageRemainingLogicalHeightForOffset(LayoutUnit offset, P  LayoutUnit RenderBlock::adjustForUnsplittableChild(RenderBox* child, LayoutUnit logicalOffset, bool includeMargins)  { -    bool isUnsplittable = child->isUnsplittableForPagination() || child->style()->columnBreakInside() == PBAVOID -        || child->style()->regionBreakInside() == PBAVOID; +    bool checkColumnBreaks = view()->layoutState()->isPaginatingColumns(); +    bool checkPageBreaks = !checkColumnBreaks && view()->layoutState()->m_pageLogicalHeight; +    bool checkRegionBreaks = inRenderFlowThread(); +    bool isUnsplittable = child->isUnsplittableForPagination() || (checkColumnBreaks && child->style()->columnBreakInside() == PBAVOID) +        || (checkPageBreaks && child->style()->pageBreakInside() == PBAVOID) +        || (checkRegionBreaks && child->style()->regionBreakInside() == PBAVOID);      if (!isUnsplittable)          return logicalOffset; -    LayoutUnit childLogicalHeight = logicalHeightForChild(child) + (includeMargins ? marginBeforeForChild(child) + marginAfterForChild(child) : 0); +    LayoutUnit childLogicalHeight = logicalHeightForChild(child) + (includeMargins ? marginBeforeForChild(child) + marginAfterForChild(child) : zeroLayoutUnit);      LayoutState* layoutState = view()->layoutState();      if (layoutState->m_columnInfo)          layoutState->m_columnInfo->updateMinimumColumnHeight(childLogicalHeight);  | 
