diff options
| author | Simon Hausmann <simon.hausmann@nokia.com> | 2012-02-24 16:36:50 +0100 |
|---|---|---|
| committer | Simon Hausmann <simon.hausmann@nokia.com> | 2012-02-24 16:36:50 +0100 |
| commit | ad0d549d4cc13433f77c1ac8f0ab379c83d93f28 (patch) | |
| tree | b34b0daceb7c8e7fdde4b4ec43650ab7caadb0a9 /Source/WebCore/rendering | |
| parent | 03e12282df9aa1e1fb05a8b90f1cfc2e08764cec (diff) | |
| download | qtwebkit-ad0d549d4cc13433f77c1ac8f0ab379c83d93f28.tar.gz | |
Imported WebKit commit bb52bf3c0119e8a128cd93afe5572413a8617de9 (http://svn.webkit.org/repository/webkit/trunk@108790)
Diffstat (limited to 'Source/WebCore/rendering')
109 files changed, 1854 insertions, 1068 deletions
diff --git a/Source/WebCore/rendering/FilterEffectRenderer.cpp b/Source/WebCore/rendering/FilterEffectRenderer.cpp index cb20bc4bd..7d9873151 100644 --- a/Source/WebCore/rendering/FilterEffectRenderer.cpp +++ b/Source/WebCore/rendering/FilterEffectRenderer.cpp @@ -326,7 +326,8 @@ void FilterEffectRenderer::prepare() m_graphicsBufferAttached = true; } m_sourceGraphic->clearResult(); - lastEffect()->clearResult(); + for (size_t i = 0; i < m_effects.size(); ++i) + m_effects[i]->clearResult(); } void FilterEffectRenderer::apply() diff --git a/Source/WebCore/rendering/InlineFlowBox.cpp b/Source/WebCore/rendering/InlineFlowBox.cpp index fb93b62c2..f799a1ae1 100644 --- a/Source/WebCore/rendering/InlineFlowBox.cpp +++ b/Source/WebCore/rendering/InlineFlowBox.cpp @@ -657,8 +657,8 @@ void InlineFlowBox::placeBoxesInBlockDirection(LayoutUnit top, LayoutUnit maxHei RenderRubyRun* rubyRun = toRenderRubyRun(curr->renderer()); if (RenderRubyBase* rubyBase = rubyRun->rubyBase()) { - LayoutUnit bottomRubyBaseLeading = (curr->logicalHeight() - rubyBase->logicalBottom()) + rubyBase->logicalHeight() - (rubyBase->lastRootBox() ? rubyBase->lastRootBox()->lineBottom() : 0); - LayoutUnit topRubyBaseLeading = rubyBase->logicalTop() + (rubyBase->firstRootBox() ? rubyBase->firstRootBox()->lineTop() : 0); + LayoutUnit bottomRubyBaseLeading = (curr->logicalHeight() - rubyBase->logicalBottom()) + rubyBase->logicalHeight() - (rubyBase->lastRootBox() ? rubyBase->lastRootBox()->lineBottom() : zeroLayoutUnit); + LayoutUnit topRubyBaseLeading = rubyBase->logicalTop() + (rubyBase->firstRootBox() ? rubyBase->firstRootBox()->lineTop() : zeroLayoutUnit); newLogicalTop += !renderer()->style()->isFlippedLinesWritingMode() ? topRubyBaseLeading : bottomRubyBaseLeading; boxHeight -= (topRubyBaseLeading + bottomRubyBaseLeading); } @@ -787,8 +787,8 @@ inline void InlineFlowBox::addBorderOutsetVisualOverflow(LayoutRect& logicalVisu LayoutUnit borderOutsetLogicalRight; style->getBorderImageInlineDirectionOutsets(borderOutsetLogicalLeft, borderOutsetLogicalRight); - LayoutUnit outsetLogicalLeft = includeLogicalLeftEdge() ? borderOutsetLogicalLeft : 0; - LayoutUnit outsetLogicalRight = includeLogicalRightEdge() ? borderOutsetLogicalRight : 0; + LayoutUnit outsetLogicalLeft = includeLogicalLeftEdge() ? borderOutsetLogicalLeft : zeroLayoutUnit; + LayoutUnit outsetLogicalRight = includeLogicalRightEdge() ? borderOutsetLogicalRight : zeroLayoutUnit; LayoutUnit logicalLeftVisualOverflow = min(pixelSnappedLogicalLeft() - outsetLogicalLeft, logicalVisualOverflow.x()); LayoutUnit logicalRightVisualOverflow = max(pixelSnappedLogicalRight() + outsetLogicalRight, logicalVisualOverflow.maxX()); @@ -1008,7 +1008,7 @@ void InlineFlowBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, flipForWritingMode(overflowRect); overflowRect.moveBy(paintOffset); - if (!paintInfo.rect.intersects(overflowRect)) + if (!paintInfo.rect.intersects(pixelSnappedIntRect(overflowRect))) return; if (paintInfo.phase != PaintPhaseChildOutlines) { @@ -1079,6 +1079,15 @@ void InlineFlowBox::paintFillLayers(const PaintInfo& paintInfo, const Color& c, paintFillLayer(paintInfo, c, fillLayer, rect, op); } +bool InlineFlowBox::boxShadowCanBeAppliedToBackground(const FillLayer& lastBackgroundLayer) const +{ + // The checks here match how paintFillLayer() decides whether to clip (if it does, the shadow + // would be clipped out, so it has to be drawn separately). + StyleImage* image = lastBackgroundLayer.image(); + bool hasFillImage = image && image->canRender(renderer(), renderer()->style()->effectiveZoom()); + return (!hasFillImage && !renderer()->style()->hasBorderRadius()) || (!prevLineBox() && !nextLineBox()) || !parent(); +} + void InlineFlowBox::paintFillLayer(const PaintInfo& paintInfo, const Color& c, const FillLayer* fillLayer, const LayoutRect& rect, CompositeOperator op) { StyleImage* img = fillLayer->image(); @@ -1107,8 +1116,8 @@ void InlineFlowBox::paintFillLayer(const PaintInfo& paintInfo, const Color& c, c for (InlineFlowBox* curr = this; curr; curr = curr->prevLineBox()) totalLogicalWidth += curr->logicalWidth(); } - LayoutUnit stripX = rect.x() - (isHorizontal() ? logicalOffsetOnLine : 0); - LayoutUnit stripY = rect.y() - (isHorizontal() ? 0 : logicalOffsetOnLine); + LayoutUnit stripX = rect.x() - (isHorizontal() ? logicalOffsetOnLine : zeroLayoutUnit); + LayoutUnit stripY = rect.y() - (isHorizontal() ? zeroLayoutUnit : logicalOffsetOnLine); LayoutUnit stripWidth = isHorizontal() ? totalLogicalWidth : width(); LayoutUnit stripHeight = isHorizontal() ? height() : totalLogicalWidth; @@ -1203,7 +1212,8 @@ void InlineFlowBox::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint& if ((!parent() && m_firstLine && styleToUse != renderer()->style()) || (parent() && renderer()->hasBoxDecorations())) { LayoutRect paintRect = LayoutRect(adjustedPaintoffset, frameRect.size()); // Shadow comes first and is behind the background and border. - paintBoxShadow(paintInfo, styleToUse, Normal, paintRect); + if (!boxModelObject()->boxShadowShouldBeAppliedToBackground(BackgroundBleedNone, this)) + paintBoxShadow(paintInfo, styleToUse, Normal, paintRect); Color c = styleToUse->visitedDependentColor(CSSPropertyBackgroundColor); paintFillLayers(paintInfo, c, styleToUse->backgroundLayers(), paintRect); @@ -1237,8 +1247,8 @@ void InlineFlowBox::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint& LayoutUnit totalLogicalWidth = logicalOffsetOnLine; for (InlineFlowBox* curr = this; curr; curr = curr->nextLineBox()) totalLogicalWidth += curr->logicalWidth(); - LayoutUnit stripX = adjustedPaintoffset.x() - (isHorizontal() ? logicalOffsetOnLine : 0); - LayoutUnit stripY = adjustedPaintoffset.y() - (isHorizontal() ? 0 : logicalOffsetOnLine); + LayoutUnit stripX = adjustedPaintoffset.x() - (isHorizontal() ? logicalOffsetOnLine : zeroLayoutUnit); + LayoutUnit stripY = adjustedPaintoffset.y() - (isHorizontal() ? zeroLayoutUnit : logicalOffsetOnLine); LayoutUnit stripWidth = isHorizontal() ? totalLogicalWidth : frameRect.width(); LayoutUnit stripHeight = isHorizontal() ? frameRect.height() : totalLogicalWidth; @@ -1308,8 +1318,8 @@ void InlineFlowBox::paintMask(PaintInfo& paintInfo, const LayoutPoint& paintOffs LayoutUnit totalLogicalWidth = logicalOffsetOnLine; for (InlineFlowBox* curr = this; curr; curr = curr->nextLineBox()) totalLogicalWidth += curr->logicalWidth(); - LayoutUnit stripX = adjustedPaintOffset.x() - (isHorizontal() ? logicalOffsetOnLine : 0); - LayoutUnit stripY = adjustedPaintOffset.y() - (isHorizontal() ? 0 : logicalOffsetOnLine); + LayoutUnit stripX = adjustedPaintOffset.x() - (isHorizontal() ? logicalOffsetOnLine : zeroLayoutUnit); + LayoutUnit stripY = adjustedPaintOffset.y() - (isHorizontal() ? zeroLayoutUnit : logicalOffsetOnLine); LayoutUnit stripWidth = isHorizontal() ? totalLogicalWidth : frameRect.width(); LayoutUnit stripHeight = isHorizontal() ? frameRect.height() : totalLogicalWidth; @@ -1406,7 +1416,7 @@ LayoutUnit InlineFlowBox::computeOverAnnotationAdjustment(LayoutUnit allowedPosi continue; if (!rubyRun->style()->isFlippedLinesWritingMode()) { - LayoutUnit topOfFirstRubyTextLine = rubyText->logicalTop() + (rubyText->firstRootBox() ? rubyText->firstRootBox()->lineTop() : 0); + LayoutUnit topOfFirstRubyTextLine = rubyText->logicalTop() + (rubyText->firstRootBox() ? rubyText->firstRootBox()->lineTop() : zeroLayoutUnit); if (topOfFirstRubyTextLine >= 0) continue; topOfFirstRubyTextLine += curr->logicalTop(); diff --git a/Source/WebCore/rendering/InlineFlowBox.h b/Source/WebCore/rendering/InlineFlowBox.h index 2ea5c47ba..500de7ed9 100644 --- a/Source/WebCore/rendering/InlineFlowBox.h +++ b/Source/WebCore/rendering/InlineFlowBox.h @@ -114,6 +114,8 @@ public: virtual void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom); virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const LayoutPoint& pointInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom); + bool boxShadowCanBeAppliedToBackground(const FillLayer&) const; + virtual RenderLineBoxList* rendererLineBoxes() const; // logicalLeft = left in a horizontal line and top in a vertical line. diff --git a/Source/WebCore/rendering/LayoutState.cpp b/Source/WebCore/rendering/LayoutState.cpp index c9018c599..e89dcc5db 100644 --- a/Source/WebCore/rendering/LayoutState.cpp +++ b/Source/WebCore/rendering/LayoutState.cpp @@ -79,7 +79,7 @@ LayoutState::LayoutState(LayoutState* prev, RenderBox* renderer, const LayoutSiz m_clipped = true; } - m_paintOffset -= layer->scrolledContentOffset(); + m_paintOffset -= renderer->scrolledContentOffset(); } // If we establish a new page height, then cache the offset to the top of the first page. @@ -156,10 +156,11 @@ LayoutState::LayoutState(RenderObject* root) m_paintOffset = LayoutSize(absContentPoint.x(), absContentPoint.y()); if (container->hasOverflowClip()) { - RenderLayer* layer = toRenderBoxModelObject(container)->layer(); + RenderBox* containerBox = toRenderBox(container); + RenderLayer* layer = containerBox->layer(); m_clipped = true; m_clipRect = LayoutRect(toPoint(m_paintOffset), layer->size()); - m_paintOffset -= layer->scrolledContentOffset(); + m_paintOffset -= containerBox->scrolledContentOffset(); } } diff --git a/Source/WebCore/rendering/LayoutTypes.h b/Source/WebCore/rendering/LayoutTypes.h index fc765d11f..72cbf2fd9 100644 --- a/Source/WebCore/rendering/LayoutTypes.h +++ b/Source/WebCore/rendering/LayoutTypes.h @@ -46,16 +46,38 @@ typedef IntPoint LayoutPoint; typedef IntSize LayoutSize; typedef IntRect LayoutRect; +const LayoutUnit zeroLayoutUnit = 0; + inline LayoutRect enclosingLayoutRect(const FloatRect& rect) { return enclosingIntRect(rect); } +inline IntRect pixelSnappedIntRect(const LayoutRect& rect) +{ + return rect; +} + +inline IntRect pixelSnappedIntRectFromEdges(LayoutUnit left, LayoutUnit top, LayoutUnit right, LayoutUnit bottom) +{ + return IntRect(left, top, right - left, bottom - top); +} + +inline IntSize roundedIntSize(const LayoutSize& s) +{ + return s; +} + inline LayoutSize roundedLayoutSize(const FloatSize& s) { return roundedIntSize(s); } +inline IntPoint roundedIntPoint(const LayoutPoint& p) +{ + return p; +} + inline LayoutPoint roundedLayoutPoint(const FloatPoint& p) { return roundedIntPoint(p); 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); diff --git a/Source/WebCore/rendering/RenderBlock.h b/Source/WebCore/rendering/RenderBlock.h index 2ccf0aa25..8996da5ef 100644 --- a/Source/WebCore/rendering/RenderBlock.h +++ b/Source/WebCore/rendering/RenderBlock.h @@ -122,8 +122,8 @@ public: void markPositionedObjectsForLayout(); virtual void markForPaginationRelayoutIfNeeded(); - bool containsFloats() { return m_floatingObjects && !m_floatingObjects->set().isEmpty(); } - bool containsFloat(RenderBox*); + bool containsFloats() const { return m_floatingObjects && !m_floatingObjects->set().isEmpty(); } + bool containsFloat(RenderBox*) const; // Versions that can compute line offsets with the region and page offset passed in. Used for speed to avoid having to // compute the region all over again when you already know it. @@ -145,6 +145,11 @@ public: return style()->isLeftToRightDirection() ? logicalLeftOffsetForLine(position, firstLine, region, offsetFromLogicalTopOfFirstPage) : logicalWidth() - logicalRightOffsetForLine(position, firstLine, region, offsetFromLogicalTopOfFirstPage); } + LayoutUnit endOffsetForLine(LayoutUnit position, bool firstLine, RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage) const + { + return !style()->isLeftToRightDirection() ? logicalLeftOffsetForLine(position, firstLine, region, offsetFromLogicalTopOfFirstPage) + : logicalWidth() - logicalRightOffsetForLine(position, firstLine, region, offsetFromLogicalTopOfFirstPage); + } LayoutUnit availableLogicalWidthForLine(LayoutUnit position, bool firstLine) const { @@ -163,6 +168,11 @@ public: return style()->isLeftToRightDirection() ? logicalLeftOffsetForLine(position, firstLine) : logicalWidth() - logicalRightOffsetForLine(position, firstLine); } + LayoutUnit endOffsetForLine(LayoutUnit position, bool firstLine) const + { + return !style()->isLeftToRightDirection() ? logicalLeftOffsetForLine(position, firstLine) + : logicalWidth() - logicalRightOffsetForLine(position, firstLine); + } // FIXME: The implementation for these functions will change once we move to subpixel layout. See bug 60318. int pixelSnappedLogicalRightOffsetForLine(LayoutUnit position, bool firstLine) const @@ -242,12 +252,12 @@ public: unsigned columnCount(ColumnInfo*) const; LayoutRect columnRectAt(ColumnInfo*, unsigned) const; - LayoutUnit paginationStrut() const { return m_rareData ? m_rareData->m_paginationStrut : 0; } + LayoutUnit paginationStrut() const { return m_rareData ? m_rareData->m_paginationStrut : zeroLayoutUnit; } void setPaginationStrut(LayoutUnit); // The page logical offset is the object's offset from the top of the page in the page progression // direction (so an x-offset in vertical text and a y-offset for horizontal text). - int pageLogicalOffset() const { return m_rareData ? m_rareData->m_pageLogicalOffset : 0; } + LayoutUnit pageLogicalOffset() const { return m_rareData ? m_rareData->m_pageLogicalOffset : zeroLayoutUnit; } void setPageLogicalOffset(int); RootInlineBox* lineGridBox() const { return m_rareData ? m_rareData->m_lineGridBox : 0; } @@ -326,6 +336,11 @@ public: return style()->isLeftToRightDirection() ? logicalLeftOffsetForContent(region, offsetFromLogicalTopOfFirstPage) : logicalWidth() - logicalRightOffsetForContent(region, offsetFromLogicalTopOfFirstPage); } + LayoutUnit endOffsetForContent(RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage) const + { + return !style()->isLeftToRightDirection() ? logicalLeftOffsetForContent(region, offsetFromLogicalTopOfFirstPage) + : logicalWidth() - logicalRightOffsetForContent(region, offsetFromLogicalTopOfFirstPage); + } LayoutUnit logicalLeftOffsetForContent(LayoutUnit blockOffset) const { return logicalLeftOffsetForContent(regionAtBlockOffset(blockOffset), offsetFromLogicalTopOfFirstPage()); @@ -342,9 +357,14 @@ public: { return startOffsetForContent(regionAtBlockOffset(blockOffset), offsetFromLogicalTopOfFirstPage()); } + LayoutUnit endOffsetForContent(LayoutUnit blockOffset) const + { + return endOffsetForContent(regionAtBlockOffset(blockOffset), offsetFromLogicalTopOfFirstPage()); + } LayoutUnit logicalLeftOffsetForContent() const { return isHorizontalWritingMode() ? borderLeft() + paddingLeft() : borderTop() + paddingTop(); } LayoutUnit logicalRightOffsetForContent() const { return logicalLeftOffsetForContent() + availableLogicalWidth(); } LayoutUnit startOffsetForContent() const { return style()->isLeftToRightDirection() ? logicalLeftOffsetForContent() : logicalWidth() - logicalRightOffsetForContent(); } + LayoutUnit endOffsetForContent() const { return !style()->isLeftToRightDirection() ? logicalLeftOffsetForContent() : logicalWidth() - logicalRightOffsetForContent(); } void setStaticInlinePositionForChild(RenderBox*, LayoutUnit blockOffset, LayoutUnit inlinePosition); @@ -365,23 +385,23 @@ protected: { return moveChildTo(to, child, 0, fullRemoveInsert); } - void moveChildTo(RenderBlock* to, RenderObject* child, RenderObject* beforeChild, bool fullRemoveInsert = false); - void moveAllChildrenTo(RenderBlock* to, bool fullRemoveInsert = false) + void moveChildTo(RenderBlock* toBlock, RenderObject* child, RenderObject* beforeChild, bool fullRemoveInsert = false); + void moveAllChildrenTo(RenderBlock* toBlock, bool fullRemoveInsert = false) { - return moveAllChildrenTo(to, 0, fullRemoveInsert); + return moveAllChildrenTo(toBlock, 0, fullRemoveInsert); } - void moveAllChildrenTo(RenderBlock* to, RenderObject* beforeChild, bool fullRemoveInsert = false) + void moveAllChildrenTo(RenderBlock* toBlock, RenderObject* beforeChild, bool fullRemoveInsert = false) { - return moveChildrenTo(to, firstChild(), 0, beforeChild, fullRemoveInsert); + return moveChildrenTo(toBlock, firstChild(), 0, beforeChild, fullRemoveInsert); } // Move all of the kids from |startChild| up to but excluding |endChild|. 0 can be passed as the endChild to denote // that all the kids from |startChild| onwards should be added. - void moveChildrenTo(RenderBlock* to, RenderObject* startChild, RenderObject* endChild, bool fullRemoveInsert = false) + void moveChildrenTo(RenderBlock* toBlock, RenderObject* startChild, RenderObject* endChild, bool fullRemoveInsert = false) { - return moveChildrenTo(to, startChild, endChild, 0, fullRemoveInsert); + return moveChildrenTo(toBlock, startChild, endChild, 0, fullRemoveInsert); } - void moveChildrenTo(RenderBlock* to, RenderObject* startChild, RenderObject* endChild, RenderObject* beforeChild, bool fullRemoveInsert = false); - + void moveChildrenTo(RenderBlock* toBlock, RenderObject* startChild, RenderObject* endChild, RenderObject* beforeChild, bool fullRemoveInsert = false); + LayoutUnit maxPositiveMarginBefore() const { return m_rareData ? m_rareData->m_margins.positiveMarginBefore() : RenderBlockRareData::positiveMarginBeforeDefault(this); } LayoutUnit maxNegativeMarginBefore() const { return m_rareData ? m_rareData->m_margins.negativeMarginBefore() : RenderBlockRareData::negativeMarginBeforeDefault(this); } LayoutUnit maxPositiveMarginAfter() const { return m_rareData ? m_rareData->m_margins.positiveMarginAfter() : RenderBlockRareData::positiveMarginAfterDefault(this); } @@ -822,6 +842,7 @@ private: void updateScrollInfoAfterLayout(); RenderObject* splitAnonymousBlocksAroundChild(RenderObject* beforeChild); + RenderObject* splitTablePartsAroundChild(RenderObject* beforeChild); void splitBlocks(RenderBlock* fromBlock, RenderBlock* toBlock, RenderBlock* middleBlock, RenderObject* beforeChild, RenderBoxModelObject* oldCont); void splitFlow(RenderObject* beforeChild, RenderBlock* newBlockBox, diff --git a/Source/WebCore/rendering/RenderBlockLineLayout.cpp b/Source/WebCore/rendering/RenderBlockLineLayout.cpp index 406930fc1..47b632464 100755 --- a/Source/WebCore/rendering/RenderBlockLineLayout.cpp +++ b/Source/WebCore/rendering/RenderBlockLineLayout.cpp @@ -491,6 +491,9 @@ RootInlineBox* RenderBlock::constructLine(BidiRunList<BidiRun>& bidiRuns, const if (runCount == 2 && !r->m_object->isListMarker()) isOnlyRun = (!style()->isLeftToRightDirection() ? bidiRuns.lastRun() : bidiRuns.firstRun())->m_object->isListMarker(); + if (lineInfo.isEmpty()) + continue; + InlineBox* box = createInlineBoxForRenderer(r->m_object, false, isOnlyRun); r->m_box = box; @@ -1093,8 +1096,8 @@ public: void updateRepaintRangeFromBox(RootInlineBox* box, LayoutUnit paginationDelta = 0) { m_usesRepaintBounds = true; - m_repaintLogicalTop = min(m_repaintLogicalTop, box->logicalTopVisualOverflow() + min(paginationDelta, 0)); - m_repaintLogicalBottom = max(m_repaintLogicalBottom, box->logicalBottomVisualOverflow() + max(paginationDelta, 0)); + m_repaintLogicalTop = min(m_repaintLogicalTop, box->logicalTopVisualOverflow() + min(paginationDelta, zeroLayoutUnit)); + m_repaintLogicalBottom = max(m_repaintLogicalBottom, box->logicalBottomVisualOverflow() + max(paginationDelta, zeroLayoutUnit)); } bool endLineMatched() const { return m_endLineMatched; } @@ -1459,7 +1462,7 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, LayoutUnit& repain LineLayoutState layoutState(isFullLayout, repaintLogicalTop, repaintLogicalBottom); if (isFullLayout) - lineBoxes()->deleteLineBoxes(renderArena()); + deleteLineBoxTree(); // Text truncation only kicks in if your overflow isn't visible and your text-overflow-mode isn't // clip. @@ -1831,14 +1834,22 @@ static inline bool shouldCollapseWhiteSpace(const RenderStyle* style, const Line || (whitespacePosition == TrailingWhitespace && style->whiteSpace() == PRE_WRAP && (!lineInfo.isEmpty() || !lineInfo.previousLineBrokeCleanly())); } -static bool inlineFlowRequiresLineBox(RenderInline* flow, const LineInfo& lineInfo) +static bool requiresLineBoxForContent(RenderInline* flow, const LineInfo& lineInfo) +{ + RenderObject* parent = flow->parent(); + if (flow->document()->inNoQuirksMode() + && (flow->style(lineInfo.isFirstLine())->lineHeight() != parent->style(lineInfo.isFirstLine())->lineHeight() + || flow->style()->verticalAlign() != parent->style()->verticalAlign() + || !parent->style()->font().fontMetrics().hasIdenticalAscentDescentAndLineGap(flow->style()->font().fontMetrics()))) + return true; + return false; +} + +static bool alwaysRequiresLineBox(RenderInline* flow) { // FIXME: Right now, we only allow line boxes for inlines that are truly empty. // We need to fix this, though, because at the very least, inlines containing only // ignorable whitespace should should also have line boxes. - if (!flow->document()->inQuirksMode() && flow->style(lineInfo.isFirstLine())->lineHeight() != flow->parent()->style(lineInfo.isFirstLine())->lineHeight()) - return true; - return !flow->firstChild() && flow->hasInlineDirectionBordersPaddingOrMargin(); } @@ -1847,7 +1858,7 @@ static bool requiresLineBox(const InlineIterator& it, const LineInfo& lineInfo = if (it.m_obj->isFloatingOrPositioned()) return false; - if (it.m_obj->isRenderInline() && !inlineFlowRequiresLineBox(toRenderInline(it.m_obj), lineInfo)) + if (it.m_obj->isRenderInline() && !alwaysRequiresLineBox(toRenderInline(it.m_obj)) && !requiresLineBoxForContent(toRenderInline(it.m_obj), lineInfo)) return false; if (!shouldCollapseWhiteSpace(it.m_obj->style(), lineInfo, whitespacePosition) || it.m_obj->isBR()) @@ -2235,8 +2246,12 @@ InlineIterator RenderBlock::LineBreaker::nextLineBreak(InlineBidiResolver& resol // to make sure that we stop to include this object and then start ignoring spaces again. // If this object is at the start of the line, we need to behave like list markers and // start ignoring spaces. - if (inlineFlowRequiresLineBox(flowBox, lineInfo)) { - lineInfo.setEmpty(false, m_block, &width); + bool requiresLineBox = alwaysRequiresLineBox(flowBox); + if (requiresLineBox || requiresLineBoxForContent(flowBox, lineInfo)) { + // An empty inline that only has line-height, vertical-align or font-metrics will only get a + // line box to affect the height of the line if the rest of the line is not empty. + if (requiresLineBox) + lineInfo.setEmpty(false, m_block, &width); if (ignoringSpaces) { trailingObjects.clear(); addMidpoint(lineMidpointState, InlineIterator(0, current.m_obj, 0)); // Stop ignoring spaces. @@ -2354,7 +2369,7 @@ InlineIterator RenderBlock::LineBreaker::nextLineBreak(InlineBidiResolver& resol midWordBreak = width.committedWidth() + wrapW + charWidth > width.availableWidth(); } - if (lineBreakIteratorInfo.first != t) { + if ((lineBreakIteratorInfo.first != t) || (lineBreakIteratorInfo.second.string() != t->characters())) { lineBreakIteratorInfo.first = t; lineBreakIteratorInfo.second.reset(t->characters(), t->textLength(), style->locale()); } @@ -2651,7 +2666,7 @@ InlineIterator RenderBlock::LineBreaker::nextLineBreak(InlineBidiResolver& resol void RenderBlock::addOverflowFromInlineChildren() { - LayoutUnit endPadding = hasOverflowClip() ? paddingEnd() : 0; + LayoutUnit endPadding = hasOverflowClip() ? paddingEnd() : zeroLayoutUnit; // FIXME: Need to find another way to do this, since scrollbars could show when we don't want them to. if (hasOverflowClip() && !endPadding && node() && node()->rendererIsEditable() && node() == node()->rootEditableElement() && style()->isLeftToRightDirection()) endPadding = 1; diff --git a/Source/WebCore/rendering/RenderBox.cpp b/Source/WebCore/rendering/RenderBox.cpp index f3ca0b1d1..d21c2405d 100644 --- a/Source/WebCore/rendering/RenderBox.cpp +++ b/Source/WebCore/rendering/RenderBox.cpp @@ -746,6 +746,13 @@ bool RenderBox::needsPreferredWidthsRecalculation() const return style()->paddingStart().isPercent() || style()->paddingEnd().isPercent(); } +IntSize RenderBox::scrolledContentOffset() const +{ + ASSERT(hasOverflowClip()); + ASSERT(hasLayer()); + return layer()->scrolledContentOffset(); +} + LayoutUnit RenderBox::minPreferredLogicalWidth() const { if (preferredLogicalWidthsDirty()) @@ -917,11 +924,12 @@ void RenderBox::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint& pai // balloon layout is an example of this). borderFitAdjust(paintRect); + BackgroundBleedAvoidance bleedAvoidance = determineBackgroundBleedAvoidance(paintInfo.context); + // FIXME: Should eventually give the theme control over whether the box shadow should paint, since controls could have // custom shadows of their own. - paintBoxShadow(paintInfo, paintRect, style(), Normal); - - BackgroundBleedAvoidance bleedAvoidance = determineBackgroundBleedAvoidance(paintInfo.context); + if (!boxShadowShouldBeAppliedToBackground(bleedAvoidance)) + paintBoxShadow(paintInfo, paintRect, style(), Normal); GraphicsContextStateSaver stateSaver(*paintInfo.context, false); if (bleedAvoidance == BackgroundBleedUseTransparencyLayer) { @@ -941,12 +949,12 @@ void RenderBox::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint& pai paintBackground(paintInfo, paintRect, bleedAvoidance); if (style()->hasAppearance()) - theme()->paintDecorations(this, paintInfo, paintRect); + theme()->paintDecorations(this, paintInfo, pixelSnappedIntRect(paintRect)); } paintBoxShadow(paintInfo, paintRect, style(), Inset); // The theme will tell us whether or not we should also paint the CSS border. - if ((!style()->hasAppearance() || (!themePainted && theme()->paintBorderOnly(this, paintInfo, paintRect))) && style()->hasBorder()) + if ((!style()->hasAppearance() || (!themePainted && theme()->paintBorderOnly(this, paintInfo, pixelSnappedIntRect(paintRect)))) && style()->hasBorder()) paintBorder(paintInfo, paintRect, style(), bleedAvoidance); if (bleedAvoidance == BackgroundBleedUseTransparencyLayer) @@ -1186,7 +1194,7 @@ bool RenderBox::pushContentsClip(PaintInfo& paintInfo, const LayoutPoint& accumu paintObject(paintInfo, accumulatedOffset); paintInfo.phase = PaintPhaseChildBlockBackgrounds; } - IntRect clipRect(isControlClip ? controlClipRect(accumulatedOffset) : overflowClipRect(accumulatedOffset, paintInfo.renderRegion)); + IntRect clipRect = pixelSnappedIntRect(isControlClip ? controlClipRect(accumulatedOffset) : overflowClipRect(accumulatedOffset, paintInfo.renderRegion)); paintInfo.context->save(); if (style()->hasBorderRadius()) paintInfo.context->addRoundedRectClip(style()->getRoundedInnerBorderFor(LayoutRect(accumulatedOffset, size()))); @@ -1251,11 +1259,50 @@ LayoutRect RenderBox::clipRect(const LayoutPoint& location, RenderRegion* region return clipRect; } +LayoutUnit RenderBox::shrinkLogicalWidthToAvoidFloats(LayoutUnit childMarginStart, LayoutUnit childMarginEnd, const RenderBlock* cb, RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage) +{ + RenderRegion* containingBlockRegion = 0; + LayoutUnit logicalTopPosition = logicalTop(); + LayoutUnit adjustedPageOffsetForContainingBlock = offsetFromLogicalTopOfFirstPage - logicalTop(); + if (region) { + LayoutUnit offsetFromLogicalTopOfRegion = region ? region->offsetFromLogicalTopOfFirstPage() - offsetFromLogicalTopOfFirstPage : 0; + logicalTopPosition = max(logicalTopPosition, logicalTopPosition + offsetFromLogicalTopOfRegion); + containingBlockRegion = cb->clampToStartAndEndRegions(region); + } + + LayoutUnit result = cb->availableLogicalWidthForLine(logicalTopPosition, false, containingBlockRegion, adjustedPageOffsetForContainingBlock) - childMarginStart - childMarginEnd; + + // We need to see if margins on either the start side or the end side can contain the floats in question. If they can, + // then just using the line width is inaccurate. In the case where a float completely fits, we don't need to use the line + // offset at all, but can instead push all the way to the content edge of the containing block. In the case where the float + // doesn't fit, we can use the line offset, but we need to grow it by the margin to reflect the fact that the margin was + // "consumed" by the float. Negative margins aren't consumed by the float, and so we ignore them. + if (childMarginStart > 0) { + LayoutUnit startContentSide = cb->startOffsetForContent(containingBlockRegion, adjustedPageOffsetForContainingBlock); + LayoutUnit startContentSideWithMargin = startContentSide + childMarginStart; + LayoutUnit startOffset = cb->startOffsetForLine(logicalTopPosition, false, containingBlockRegion, adjustedPageOffsetForContainingBlock); + if (startOffset > startContentSideWithMargin) + result += childMarginStart; + else + result += startOffset - startContentSide; + } + + if (childMarginEnd > 0) { + LayoutUnit endContentSide = cb->endOffsetForContent(containingBlockRegion, adjustedPageOffsetForContainingBlock); + LayoutUnit endContentSideWithMargin = endContentSide + childMarginEnd; + LayoutUnit endOffset = cb->endOffsetForLine(logicalTopPosition, false, containingBlockRegion, adjustedPageOffsetForContainingBlock); + if (endOffset > endContentSideWithMargin) + result += childMarginEnd; + else + result += endOffset - endContentSide; + } + + return result; +} + LayoutUnit RenderBox::containingBlockLogicalWidthForContent() const { RenderBlock* cb = containingBlock(); - if (shrinkToAvoidFloats() && !inRenderFlowThread()) - return cb->availableLogicalWidthForLine(logicalTop(), false); return cb->availableLogicalWidth(); } @@ -1266,10 +1313,6 @@ LayoutUnit RenderBox::containingBlockLogicalWidthForContentInRegion(RenderRegion RenderBlock* cb = containingBlock(); RenderRegion* containingBlockRegion = cb->clampToStartAndEndRegions(region); - if (shrinkToAvoidFloats()) { - LayoutUnit offsetFromLogicalTopOfRegion = region->offsetFromLogicalTopOfFirstPage() - offsetFromLogicalTopOfFirstPage; - return cb->availableLogicalWidthForLine(max(logicalTop(), logicalTop() + offsetFromLogicalTopOfRegion), false, containingBlockRegion, offsetFromLogicalTopOfFirstPage - logicalTop()); - } LayoutUnit result = cb->availableLogicalWidth(); RenderBoxRegionInfo* boxInfo = cb->renderBoxRegionInfo(containingBlockRegion, offsetFromLogicalTopOfFirstPage - logicalTop()); if (!boxInfo) @@ -1397,7 +1440,7 @@ LayoutSize RenderBox::offsetFromContainer(RenderObject* o, const LayoutPoint& po } if (o->hasOverflowClip()) - offset -= toRenderBox(o)->layer()->scrolledContentOffset(); + offset -= toRenderBox(o)->scrolledContentOffset(); if (style()->position() == AbsolutePosition && o->isRelPositioned() && o->isRenderInline()) offset += toRenderInline(o)->relativePositionedInlineOffset(this); @@ -1596,7 +1639,7 @@ void RenderBox::computeRectForRepaint(RenderBoxModelObject* repaintContainer, La // o->height() is inaccurate if we're in the middle of a layout of |o|, so use the // layer's size instead. Even if the layer's size is wrong, the layer itself will repaint // anyway if its size does change. - topLeft -= containerBox->layer()->scrolledContentOffset(); // For overflow:auto/scroll/hidden. + topLeft -= containerBox->scrolledContentOffset(); // For overflow:auto/scroll/hidden. LayoutRect repaintRect(topLeft, rect.size()); LayoutRect boxRect(LayoutPoint(), containerBox->layer()->size()); @@ -1691,11 +1734,11 @@ void RenderBox::computeLogicalWidthInRegion(RenderRegion* region, LayoutUnit off setLogicalWidth(logicalWidthLength.value() + borderAndPaddingLogicalWidth()); else { // Calculate LogicalWidth - setLogicalWidth(computeLogicalWidthUsing(LogicalWidth, containerWidthInInlineDirection)); + setLogicalWidth(computeLogicalWidthInRegionUsing(LogicalWidth, containerWidthInInlineDirection, cb, region, offsetFromLogicalTopOfFirstPage)); // Calculate MaxLogicalWidth if (!styleToUse->logicalMaxWidth().isUndefined()) { - LayoutUnit maxLogicalWidth = computeLogicalWidthUsing(MaxLogicalWidth, containerWidthInInlineDirection); + LayoutUnit maxLogicalWidth = computeLogicalWidthInRegionUsing(MaxLogicalWidth, containerWidthInInlineDirection, cb, region, offsetFromLogicalTopOfFirstPage); if (logicalWidth() > maxLogicalWidth) { setLogicalWidth(maxLogicalWidth); logicalWidthLength = styleToUse->logicalMaxWidth(); @@ -1703,7 +1746,7 @@ void RenderBox::computeLogicalWidthInRegion(RenderRegion* region, LayoutUnit off } // Calculate MinLogicalWidth - LayoutUnit minLogicalWidth = computeLogicalWidthUsing(MinLogicalWidth, containerWidthInInlineDirection); + LayoutUnit minLogicalWidth = computeLogicalWidthInRegionUsing(MinLogicalWidth, containerWidthInInlineDirection, cb, region, offsetFromLogicalTopOfFirstPage); if (logicalWidth() < minLogicalWidth) { setLogicalWidth(minLogicalWidth); logicalWidthLength = styleToUse->logicalMinWidth(); @@ -1728,7 +1771,8 @@ void RenderBox::computeLogicalWidthInRegion(RenderRegion* region, LayoutUnit off cb->setMarginEndForChild(this, containerLogicalWidth - logicalWidth() - cb->marginStartForChild(this)); } -LayoutUnit RenderBox::computeLogicalWidthUsing(LogicalWidthType widthType, LayoutUnit availableLogicalWidth) +LayoutUnit RenderBox::computeLogicalWidthInRegionUsing(LogicalWidthType widthType, LayoutUnit availableLogicalWidth, + const RenderBlock* cb, RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage) { LayoutUnit logicalWidthResult = logicalWidth(); RenderStyle* styleToUse = style(); @@ -1745,6 +1789,9 @@ LayoutUnit RenderBox::computeLogicalWidthUsing(LogicalWidthType widthType, Layou LayoutUnit marginEnd = styleToUse->marginEnd().calcMinValue(availableLogicalWidth); logicalWidthResult = availableLogicalWidth - marginStart - marginEnd; + if (shrinkToAvoidFloats() && cb->containsFloats()) + logicalWidthResult = shrinkLogicalWidthToAvoidFloats(marginStart, marginEnd, cb, region, offsetFromLogicalTopOfFirstPage); + if (sizesToIntrinsicLogicalWidth(widthType)) { logicalWidthResult = max(logicalWidthResult, minPreferredLogicalWidth()); logicalWidthResult = min(logicalWidthResult, maxPreferredLogicalWidth()); @@ -1997,7 +2044,6 @@ void RenderBox::computeLogicalHeight() LayoutUnit heightResult; if (checkMinMaxHeight) { heightResult = computeLogicalHeightUsing(styleToUse->logicalHeight()); - // FIXME: Use < 0 or roughlyEquals when we move to float, see https://bugs.webkit.org/show_bug.cgi?id=66148 if (heightResult == -1) heightResult = logicalHeight(); LayoutUnit minH = computeLogicalHeightUsing(styleToUse->logicalMinHeight()); // Leave as -1 if unset. @@ -2056,7 +2102,6 @@ LayoutUnit RenderBox::computeLogicalHeightUsing(const Length& h) logicalHeight = h.value(); else if (h.isPercent()) logicalHeight = computePercentageLogicalHeight(h); - // FIXME: Use < 0 or roughlyEquals when we move to float, see https://bugs.webkit.org/show_bug.cgi?id=66148 if (logicalHeight != -1) { logicalHeight = computeBorderBoxLogicalHeight(logicalHeight); return logicalHeight; @@ -2123,7 +2168,6 @@ LayoutUnit RenderBox::computePercentageLogicalHeight(const Length& height) else if (cbstyle->logicalHeight().isPercent() && !isPositionedWithSpecifiedHeight) { // We need to recur and compute the percentage height for our containing block. result = cb->computePercentageLogicalHeight(cbstyle->logicalHeight()); - // FIXME: Use < 0 or roughlyEquals when we move to float, see https://bugs.webkit.org/show_bug.cgi?id=66148 if (result != -1) result = cb->computeContentBoxLogicalHeight(result); } else if (cb->isRenderView() || (cb->isBody() && document()->inQuirksMode()) || isPositionedWithSpecifiedHeight) { @@ -2138,7 +2182,6 @@ LayoutUnit RenderBox::computePercentageLogicalHeight(const Length& height) // always. Note we could only hit this case by recurring into computePercentageLogicalHeight on a positioned containing block. result = cb->computeContentBoxLogicalHeight(cb->availableLogicalHeight()); - // FIXME: Use < 0 or roughlyEquals when we move to float, see https://bugs.webkit.org/show_bug.cgi?id=66148 if (result != -1) { result = height.calcValue(result); if (includeBorderPadding) { @@ -3444,9 +3487,9 @@ VisiblePosition RenderBox::positionForPoint(const LayoutPoint& point) RenderBox* renderer = toRenderBox(renderObject); - LayoutUnit top = renderer->borderTop() + renderer->paddingTop() + (isTableRow() ? 0 : renderer->y()); + LayoutUnit top = renderer->borderTop() + renderer->paddingTop() + (isTableRow() ? zeroLayoutUnit : renderer->y()); LayoutUnit bottom = top + renderer->contentHeight(); - LayoutUnit left = renderer->borderLeft() + renderer->paddingLeft() + (isTableRow() ? 0 : renderer->x()); + LayoutUnit left = renderer->borderLeft() + renderer->paddingLeft() + (isTableRow() ? zeroLayoutUnit : renderer->x()); LayoutUnit right = left + renderer->contentWidth(); if (point.x() <= right && point.x() >= left && point.y() <= top && point.y() >= bottom) { diff --git a/Source/WebCore/rendering/RenderBox.h b/Source/WebCore/rendering/RenderBox.h index f9b852c54..31ec39a20 100644 --- a/Source/WebCore/rendering/RenderBox.h +++ b/Source/WebCore/rendering/RenderBox.h @@ -151,6 +151,7 @@ public: // respectively are flipped when compared to their physical counterparts. For example minX is on the left in vertical-lr, // but it is on the right in vertical-rl. LayoutRect layoutOverflowRect() const { return m_overflow ? m_overflow->layoutOverflowRect() : clientBoxRect(); } + IntRect pixelSnappedLayoutOverflowRect() const { return pixelSnappedIntRect(layoutOverflowRect()); } LayoutUnit minYLayoutOverflow() const { return m_overflow? m_overflow->minYLayoutOverflow() : borderTop(); } LayoutUnit maxYLayoutOverflow() const { return m_overflow ? m_overflow->maxYLayoutOverflow() : borderTop() + clientHeight(); } LayoutUnit minXLayoutOverflow() const { return m_overflow ? m_overflow->minXLayoutOverflow() : borderLeft(); } @@ -160,9 +161,9 @@ public: LayoutUnit logicalRightLayoutOverflow() const { return style()->isHorizontalWritingMode() ? maxXLayoutOverflow() : maxYLayoutOverflow(); } virtual LayoutRect visualOverflowRect() const { return m_overflow ? m_overflow->visualOverflowRect() : borderBoxRect(); } - LayoutUnit minYVisualOverflow() const { return m_overflow? m_overflow->minYVisualOverflow() : 0; } + LayoutUnit minYVisualOverflow() const { return m_overflow? m_overflow->minYVisualOverflow() : zeroLayoutUnit; } LayoutUnit maxYVisualOverflow() const { return m_overflow ? m_overflow->maxYVisualOverflow() : height(); } - LayoutUnit minXVisualOverflow() const { return m_overflow ? m_overflow->minXVisualOverflow() : 0; } + LayoutUnit minXVisualOverflow() const { return m_overflow ? m_overflow->minXVisualOverflow() : zeroLayoutUnit; } LayoutUnit maxXVisualOverflow() const { return m_overflow ? m_overflow->maxXVisualOverflow() : width(); } LayoutUnit logicalLeftVisualOverflow() const { return style()->isHorizontalWritingMode() ? minXVisualOverflow() : minYVisualOverflow(); } LayoutUnit logicalRightVisualOverflow() const { return style()->isHorizontalWritingMode() ? maxXVisualOverflow() : maxYVisualOverflow(); } @@ -313,7 +314,7 @@ public: virtual void computeLogicalHeight(); RenderBoxRegionInfo* renderBoxRegionInfo(RenderRegion*, LayoutUnit offsetFromLogicalTopOfFirstPage, RenderBoxRegionInfoFlags = CacheRenderBoxRegionInfo) const; - void computeLogicalWidthInRegion(RenderRegion* = 0, LayoutUnit offsetFromLogicalTopOfFirstPage = 0); + void computeLogicalWidthInRegion(RenderRegion* = 0, LayoutUnit offsetFromLogicalTopOfFirstPage = zeroLayoutUnit); bool stretchesToViewport() const { @@ -329,7 +330,9 @@ public: bool sizesToIntrinsicLogicalWidth(LogicalWidthType) const; virtual bool stretchesToMinIntrinsicLogicalWidth() const { return false; } - LayoutUnit computeLogicalWidthUsing(LogicalWidthType, LayoutUnit availableLogicalWidth); + LayoutUnit shrinkLogicalWidthToAvoidFloats(LayoutUnit childMarginStart, LayoutUnit childMarginEnd, const RenderBlock* cb, RenderRegion*, LayoutUnit offsetFromLogicalTopOfFirstPage); + + LayoutUnit computeLogicalWidthInRegionUsing(LogicalWidthType, LayoutUnit availableLogicalWidth, const RenderBlock* containingBlock, RenderRegion*, LayoutUnit offsetFromLogicalTopOfFirstPage); LayoutUnit computeLogicalHeightUsing(const Length& height); LayoutUnit computeReplacedLogicalWidthUsing(Length width) const; LayoutUnit computeReplacedLogicalWidthRespectingMinMaxWidth(LayoutUnit logicalWidth, bool includeMaxWidth = true) const; @@ -444,6 +447,8 @@ public: virtual bool needsPreferredWidthsRecalculation() const; virtual void computeIntrinsicRatioInformation(FloatSize& /* intrinsicSize */, double& /* intrinsicRatio */, bool& /* isPercentageIntrinsicSize */) const { } + IntSize scrolledContentOffset() const; + protected: virtual void willBeDestroyed(); @@ -459,6 +464,8 @@ protected: void paintMaskImages(const PaintInfo&, const LayoutRect&); + BackgroundBleedAvoidance determineBackgroundBleedAvoidance(GraphicsContext*) const; + #if PLATFORM(MAC) void paintCustomHighlight(const LayoutPoint&, const AtomicString& type, bool behindText); #endif @@ -503,8 +510,6 @@ private: // These include tables, positioned objects, floats and flexible boxes. virtual void computePreferredLogicalWidths() { setPreferredLogicalWidthsDirty(false); } - BackgroundBleedAvoidance determineBackgroundBleedAvoidance(GraphicsContext*) const; - private: // The width/height of the contents + borders + padding. The x/y location is relative to our container (which is not always our parent). LayoutRect m_frameRect; diff --git a/Source/WebCore/rendering/RenderBoxModelObject.cpp b/Source/WebCore/rendering/RenderBoxModelObject.cpp index 3aadee902..e3ab32180 100644 --- a/Source/WebCore/rendering/RenderBoxModelObject.cpp +++ b/Source/WebCore/rendering/RenderBoxModelObject.cpp @@ -168,8 +168,6 @@ bool ImageQualityController::shouldPaintAtLowQuality(GraphicsContext* context, R const AffineTransform& currentTransform = context->getCTM(); bool contextIsScaled = !currentTransform.isIdentityOrTranslationOrFlipped(); - // FIXME: Change to use roughlyEquals when we move to float. - // See https://bugs.webkit.org/show_bug.cgi?id=66148 if (!contextIsScaled && size == imageSize) { // There is no scale in effect. If we had a scale in effect before, we can just remove this object from the list. removeLayer(object, innerMap, layer); @@ -192,8 +190,6 @@ bool ImageQualityController::shouldPaintAtLowQuality(GraphicsContext* context, R // If this is the first time resizing this image, or its size is the // same as the last resize, draw at high res, but record the paint // size and set the timer. - // FIXME: Change to use roughlyEquals when we move to float. - // See https://bugs.webkit.org/show_bug.cgi?id=66148 if (isFirstResize || oldSize == size) { restartTimer(); set(object, innerMap, layer, size); @@ -362,7 +358,7 @@ void RenderBoxModelObject::styleDidChange(StyleDifference diff, const RenderStyl updateBoxModelInfoFromStyle(); if (requiresLayer()) { - if (!layer()) { + if (!layer() && layerCreationAllowedForSubtree()) { if (s_wasFloating && isFloating()) setChildNeedsLayout(true); m_layer = new (renderArena()) RenderLayer(this); @@ -401,8 +397,26 @@ void RenderBoxModelObject::updateBoxModelInfoFromStyle() setHorizontalWritingMode(styleToUse->isHorizontalWritingMode()); } +enum RelPosAxis { RelPosX, RelPosY }; + +static LayoutUnit accumulateRelativePositionOffsets(const RenderObject* child, RelPosAxis axis) +{ + if (!child->isAnonymousBlock() || !child->isRelPositioned()) + return 0; + LayoutUnit offset = 0; + RenderObject* p = toRenderBlock(child)->inlineElementContinuation(); + while (p && p->isRenderInline()) { + if (p->isRelPositioned()) + offset += (axis == RelPosX) ? toRenderInline(p)->relativePositionOffsetX() : toRenderInline(p)->relativePositionOffsetY(); + p = p->parent(); + } + return offset; +} + LayoutUnit RenderBoxModelObject::relativePositionOffsetX() const { + LayoutUnit offset = accumulateRelativePositionOffsets(this, RelPosX); + // Objects that shrink to avoid floats normally use available line width when computing containing block width. However // in the case of relative positioning using percentages, we can't do this. The offset should always be resolved using the // available width of the containing block. Therefore we don't use containingBlockLogicalWidthForContent() here, but instead explicitly @@ -411,19 +425,20 @@ LayoutUnit RenderBoxModelObject::relativePositionOffsetX() const RenderBlock* cb = containingBlock(); if (!style()->right().isAuto() && !cb->style()->isLeftToRightDirection()) return -style()->right().calcValue(cb->availableWidth()); - return style()->left().calcValue(cb->availableWidth()); + return offset + style()->left().calcValue(cb->availableWidth()); } if (!style()->right().isAuto()) { RenderBlock* cb = containingBlock(); - return -style()->right().calcValue(cb->availableWidth()); + return offset + -style()->right().calcValue(cb->availableWidth()); } - return 0; + return offset; } LayoutUnit RenderBoxModelObject::relativePositionOffsetY() const { + LayoutUnit offset = accumulateRelativePositionOffsets(this, RelPosY); + RenderBlock* containingBlock = this->containingBlock(); - // If the containing block of a relatively positioned element does not // specify a height, a percentage top or bottom offset should be resolved as // auto. An exception to this is if the containing block has the WinIE quirk @@ -434,15 +449,15 @@ LayoutUnit RenderBoxModelObject::relativePositionOffsetY() const && (!containingBlock->style()->height().isAuto() || !style()->top().isPercent() || containingBlock->stretchesToViewport())) - return style()->top().calcValue(containingBlock->availableHeight()); + return offset + style()->top().calcValue(containingBlock->availableHeight()); if (!style()->bottom().isAuto() && (!containingBlock->style()->height().isAuto() || !style()->bottom().isPercent() || containingBlock->stretchesToViewport())) - return -style()->bottom().calcValue(containingBlock->availableHeight()); + return offset + -style()->bottom().calcValue(containingBlock->availableHeight()); - return 0; + return offset; } LayoutUnit RenderBoxModelObject::offsetLeft() const @@ -453,7 +468,7 @@ LayoutUnit RenderBoxModelObject::offsetLeft() const return 0; RenderBoxModelObject* offsetPar = offsetParent(); - LayoutUnit xPos = (isBox() ? toRenderBox(this)->left() : 0); + LayoutUnit xPos = (isBox() ? toRenderBox(this)->left() : zeroLayoutUnit); // If the offsetParent of the element is null, or is the HTML body element, // return the distance between the canvas origin and the left border edge @@ -487,7 +502,7 @@ LayoutUnit RenderBoxModelObject::offsetTop() const return 0; RenderBoxModelObject* offsetPar = offsetParent(); - LayoutUnit yPos = (isBox() ? toRenderBox(this)->top() : 0); + LayoutUnit yPos = (isBox() ? toRenderBox(this)->top() : zeroLayoutUnit); // If the offsetParent of the element is null, or is the HTML body element, // return the distance between the canvas origin and the top border edge @@ -619,6 +634,19 @@ static LayoutRect backgroundRectAdjustedForBleedAvoidance(GraphicsContext* conte return adjustedRect; } +static void applyBoxShadowForBackground(GraphicsContext* context, RenderStyle* style) +{ + const ShadowData* boxShadow = style->boxShadow(); + while (boxShadow->style() != Normal) + boxShadow = boxShadow->next(); + + FloatSize shadowOffset(boxShadow->x(), boxShadow->y()); + if (!boxShadow->isWebkitBoxShadow()) + context->setShadow(shadowOffset, boxShadow->blur(), boxShadow->color(), style->colorSpace()); + else + context->setLegacyShadow(shadowOffset, boxShadow->blur(), boxShadow->color(), style->colorSpace()); +} + void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, const Color& color, const FillLayer* bgLayer, const LayoutRect& rect, BackgroundBleedAvoidance bleedAvoidance, InlineFlowBox* box, const LayoutSize& boxSize, CompositeOperator op, RenderObject* backgroundObject) { @@ -669,11 +697,16 @@ void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, co if (!colorVisible) return; + bool boxShadowShouldBeAppliedToBackground = this->boxShadowShouldBeAppliedToBackground(bleedAvoidance, box); + GraphicsContextStateSaver shadowStateSaver(*context, boxShadowShouldBeAppliedToBackground); + if (boxShadowShouldBeAppliedToBackground) + applyBoxShadowForBackground(context, style()); + if (hasRoundedBorder && bleedAvoidance != BackgroundBleedUseTransparencyLayer) { RoundedRect border = getBackgroundRoundedRect(backgroundRectAdjustedForBleedAvoidance(context, rect, bleedAvoidance), box, boxSize.width(), boxSize.height(), includeLeftEdge, includeRightEdge); context->fillRoundedRect(border, bgColor, style()->colorSpace()); } else - context->fillRect(rect, bgColor, style()->colorSpace()); + context->fillRect(pixelSnappedIntRect(rect), bgColor, style()->colorSpace()); return; } @@ -685,49 +718,53 @@ void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, co context->addRoundedRectClip(border); } - LayoutUnit bLeft = includeLeftEdge ? borderLeft() : 0; - LayoutUnit bRight = includeRightEdge ? borderRight() : 0; - LayoutUnit pLeft = includeLeftEdge ? paddingLeft() : 0; - LayoutUnit pRight = includeRightEdge ? paddingRight() : 0; + LayoutUnit bLeft = includeLeftEdge ? borderLeft() : zeroLayoutUnit; + LayoutUnit bRight = includeRightEdge ? borderRight() : zeroLayoutUnit; + LayoutUnit pLeft = includeLeftEdge ? paddingLeft() : zeroLayoutUnit; + LayoutUnit pRight = includeRightEdge ? paddingRight() : zeroLayoutUnit; GraphicsContextStateSaver clipWithScrollingStateSaver(*context, clippedWithLocalScrolling); LayoutRect scrolledPaintRect = rect; if (clippedWithLocalScrolling) { // Clip to the overflow area. - context->clip(toRenderBox(this)->overflowClipRect(rect.location(), paintInfo.renderRegion)); + RenderBox* thisBox = toRenderBox(this); + context->clip(thisBox->overflowClipRect(rect.location(), paintInfo.renderRegion)); // Adjust the paint rect to reflect a scrolled content box with borders at the ends. - LayoutSize offset = layer()->scrolledContentOffset(); + IntSize offset = thisBox->scrolledContentOffset(); scrolledPaintRect.move(-offset); scrolledPaintRect.setWidth(bLeft + layer()->scrollWidth() + bRight); scrolledPaintRect.setHeight(borderTop() + layer()->scrollHeight() + borderBottom()); } GraphicsContextStateSaver backgroundClipStateSaver(*context, false); + OwnPtr<ImageBuffer> maskImage; + IntRect maskRect; + if (bgLayer->clip() == PaddingFillBox || bgLayer->clip() == ContentFillBox) { // Clip to the padding or content boxes as necessary. bool includePadding = bgLayer->clip() == ContentFillBox; - LayoutRect clipRect = LayoutRect(scrolledPaintRect.x() + bLeft + (includePadding ? pLeft : 0), - scrolledPaintRect.y() + borderTop() + (includePadding ? paddingTop() : 0), - scrolledPaintRect.width() - bLeft - bRight - (includePadding ? pLeft + pRight : 0), - scrolledPaintRect.height() - borderTop() - borderBottom() - (includePadding ? paddingTop() + paddingBottom() : 0)); + LayoutRect clipRect = LayoutRect(scrolledPaintRect.x() + bLeft + (includePadding ? pLeft : zeroLayoutUnit), + scrolledPaintRect.y() + borderTop() + (includePadding ? paddingTop() : zeroLayoutUnit), + scrolledPaintRect.width() - bLeft - bRight - (includePadding ? pLeft + pRight : zeroLayoutUnit), + scrolledPaintRect.height() - borderTop() - borderBottom() - (includePadding ? paddingTop() + paddingBottom() : zeroLayoutUnit)); backgroundClipStateSaver.save(); context->clip(clipRect); } else if (bgLayer->clip() == TextFillBox) { // We have to draw our text into a mask that can then be used to clip background drawing. // First figure out how big the mask has to be. It should be no bigger than what we need // to actually render, so we should intersect the dirty rect with the border box of the background. - LayoutRect maskRect = rect; + maskRect = pixelSnappedIntRect(rect); maskRect.intersect(paintInfo.rect); - + // Now create the mask. - OwnPtr<ImageBuffer> maskImage = context->createCompatibleBuffer(maskRect.size()); + maskImage = context->createCompatibleBuffer(maskRect.size()); if (!maskImage) return; - + GraphicsContext* maskImageContext = maskImage->context(); maskImageContext->translate(-maskRect.x(), -maskRect.y()); - + // Now add the text to the clip. We do this by painting using a special paint phase that signals to // InlineTextBoxes that they should just add their contents to the clip. PaintInfo info(maskImageContext, maskRect, PaintPhaseTextClip, true, 0, paintInfo.renderRegion, 0); @@ -738,12 +775,13 @@ void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, co LayoutSize localOffset = isBox() ? toRenderBox(this)->locationOffset() : LayoutSize(); paint(info, scrolledPaintRect.location() - localOffset); } - + // The mask has been created. Now we just need to clip to it. backgroundClipStateSaver.save(); - context->clipToImageBuffer(maskImage.get(), maskRect); + context->clip(maskRect); + context->beginTransparencyLayer(1); } - + // Only fill with a base color (e.g., white) if we're the root document, since iframes/frames with // no background in the child document should show the parent's background. bool isOpaqueRoot = false; @@ -777,8 +815,11 @@ void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, co // Paint the color first underneath all images. if (!bgLayer->next()) { - LayoutRect backgroundRect(scrolledPaintRect); - backgroundRect.intersect(paintInfo.rect); + IntRect backgroundRect(pixelSnappedIntRect(scrolledPaintRect)); + bool boxShadowShouldBeAppliedToBackground = this->boxShadowShouldBeAppliedToBackground(bleedAvoidance, box); + if (!boxShadowShouldBeAppliedToBackground) + backgroundRect.intersect(paintInfo.rect); + // If we have an alpha and we are painting the root element, go ahead and blend with the base background color. Color baseColor; bool shouldClearBackground = false; @@ -788,6 +829,10 @@ void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, co shouldClearBackground = true; } + GraphicsContextStateSaver shadowStateSaver(*context, boxShadowShouldBeAppliedToBackground); + if (boxShadowShouldBeAppliedToBackground) + applyBoxShadowForBackground(context, style()); + if (baseColor.alpha()) { if (bgColor.alpha()) baseColor = baseColor.blend(bgColor); @@ -814,6 +859,11 @@ void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, co compositeOp, useLowQualityScaling); } } + + if (bgLayer->clip() == TextFillBox) { + context->drawImageBuffer(maskImage.get(), ColorSpaceDeviceRGB, maskRect, CompositeDestinationIn); + context->endTransparencyLayer(); + } } static inline LayoutUnit resolveWidthForRatio(LayoutUnit height, const FloatSize& intrinsicRatio) @@ -1064,7 +1114,7 @@ void RenderBoxModelObject::calculateBackgroundImageGeometry(const FillLayer* fil } else positioningAreaSize = LayoutSize(paintRect.width() - left - right, paintRect.height() - top - bottom); } else { - geometry.setDestRect(viewRect()); + geometry.setDestRect(pixelSnappedIntRect(viewRect())); positioningAreaSize = geometry.destRect().size(); } @@ -1404,6 +1454,14 @@ static inline bool includesEdge(BorderEdgeFlags flags, BoxSide side) return flags & edgeFlagForSide(side); } +static inline bool includesAdjacentEdges(BorderEdgeFlags flags) +{ + return (flags & (TopBorderEdge | RightBorderEdge)) == (TopBorderEdge | RightBorderEdge) + || (flags & (RightBorderEdge | BottomBorderEdge)) == (RightBorderEdge | BottomBorderEdge) + || (flags & (BottomBorderEdge | LeftBorderEdge)) == (BottomBorderEdge | LeftBorderEdge) + || (flags & (LeftBorderEdge | TopBorderEdge)) == (LeftBorderEdge | TopBorderEdge); +} + inline bool edgesShareColor(const BorderEdge& firstEdge, const BorderEdge& secondEdge) { return firstEdge.color == secondEdge.color; @@ -1527,7 +1585,7 @@ static bool joinRequiresMitre(BoxSide side, BoxSide adjacentSide, const BorderEd } void RenderBoxModelObject::paintOneBorderSide(GraphicsContext* graphicsContext, const RenderStyle* style, const RoundedRect& outerBorder, const RoundedRect& innerBorder, - const LayoutRect& sideRect, BoxSide side, BoxSide adjacentSide1, BoxSide adjacentSide2, const BorderEdge edges[], const Path* path, + const IntRect& sideRect, BoxSide side, BoxSide adjacentSide1, BoxSide adjacentSide2, const BorderEdge edges[], const Path* path, BackgroundBleedAvoidance bleedAvoidance, bool includeLogicalLeftEdge, bool includeLogicalRightEdge, bool antialias, const Color* overrideColor) { const BorderEdge& edgeToRender = edges[side]; @@ -1572,9 +1630,9 @@ void RenderBoxModelObject::paintOneBorderSide(GraphicsContext* graphicsContext, } } -static LayoutRect calculateSideRect(const RoundedRect& outerBorder, const BorderEdge edges[], int side) +static IntRect calculateSideRect(const RoundedRect& outerBorder, const BorderEdge edges[], int side) { - LayoutRect sideRect = outerBorder.rect(); + IntRect sideRect = outerBorder.rect(); int width = edges[side].width; if (side == BSTop) @@ -1600,7 +1658,7 @@ void RenderBoxModelObject::paintBorderSides(GraphicsContext* graphicsContext, co roundedPath.addRoundedRect(outerBorder); if (edges[BSTop].shouldRender() && includesEdge(edgeSet, BSTop)) { - LayoutRect sideRect = outerBorder.rect(); + IntRect sideRect = outerBorder.rect(); sideRect.setHeight(edges[BSTop].width); bool usePath = renderRadii && (borderStyleHasInnerDetail(edges[BSTop].style) || borderWillArcInnerEdge(innerBorder.radii().topLeft(), innerBorder.radii().topRight())); @@ -1608,7 +1666,7 @@ void RenderBoxModelObject::paintBorderSides(GraphicsContext* graphicsContext, co } if (edges[BSBottom].shouldRender() && includesEdge(edgeSet, BSBottom)) { - LayoutRect sideRect = outerBorder.rect(); + IntRect sideRect = outerBorder.rect(); sideRect.shiftYEdgeTo(sideRect.maxY() - edges[BSBottom].width); bool usePath = renderRadii && (borderStyleHasInnerDetail(edges[BSBottom].style) || borderWillArcInnerEdge(innerBorder.radii().bottomLeft(), innerBorder.radii().bottomRight())); @@ -1616,7 +1674,7 @@ void RenderBoxModelObject::paintBorderSides(GraphicsContext* graphicsContext, co } if (edges[BSLeft].shouldRender() && includesEdge(edgeSet, BSLeft)) { - LayoutRect sideRect = outerBorder.rect(); + IntRect sideRect = outerBorder.rect(); sideRect.setWidth(edges[BSLeft].width); bool usePath = renderRadii && (borderStyleHasInnerDetail(edges[BSLeft].style) || borderWillArcInnerEdge(innerBorder.radii().bottomLeft(), innerBorder.radii().topLeft())); @@ -1624,7 +1682,7 @@ void RenderBoxModelObject::paintBorderSides(GraphicsContext* graphicsContext, co } if (edges[BSRight].shouldRender() && includesEdge(edgeSet, BSRight)) { - LayoutRect sideRect = outerBorder.rect(); + IntRect sideRect = outerBorder.rect(); sideRect.shiftXEdgeTo(sideRect.maxX() - edges[BSRight].width); bool usePath = renderRadii && (borderStyleHasInnerDetail(edges[BSRight].style) || borderWillArcInnerEdge(innerBorder.radii().bottomRight(), innerBorder.radii().topRight())); @@ -1657,7 +1715,7 @@ void RenderBoxModelObject::paintTranslucentBorderSides(GraphicsContext* graphics commonColorEdgeSet |= edgeFlagForSide(currSide); } - bool useTransparencyLayer = commonColor.hasAlpha(); + bool useTransparencyLayer = includesAdjacentEdges(commonColorEdgeSet) && commonColor.hasAlpha(); if (useTransparencyLayer) { graphicsContext->beginTransparencyLayer(static_cast<float>(commonColor.alpha()) / 255); commonColor = Color(commonColor.red(), commonColor.green(), commonColor.blue()); @@ -1753,7 +1811,7 @@ void RenderBoxModelObject::paintBorder(const PaintInfo& info, const LayoutRect& for (int i = BSTop; i <= BSLeft; ++i) { const BorderEdge& currEdge = edges[i]; if (currEdge.shouldRender()) { - LayoutRect sideRect = calculateSideRect(outerBorder, edges, i); + IntRect sideRect = calculateSideRect(outerBorder, edges, i); path.addRect(sideRect); } } @@ -1933,7 +1991,7 @@ void RenderBoxModelObject::drawBoxSideFromPath(GraphicsContext* graphicsContext, graphicsContext->setStrokeStyle(NoStroke); graphicsContext->setFillColor(color, style->colorSpace()); - graphicsContext->drawRect(borderRect); + graphicsContext->drawRect(pixelSnappedIntRect(borderRect)); } #else void RenderBoxModelObject::paintBorder(const PaintInfo& info, const IntRect& rect, const RenderStyle* style, @@ -2375,9 +2433,9 @@ void RenderBoxModelObject::clipBorderSidePolygon(GraphicsContext* graphicsContex graphicsContext->clipConvexPolygon(4, secondQuad, !secondEdgeMatches); } -static LayoutRect calculateSideRectIncludingInner(const RoundedRect& outerBorder, const BorderEdge edges[], BoxSide side) +static IntRect calculateSideRectIncludingInner(const RoundedRect& outerBorder, const BorderEdge edges[], BoxSide side) { - LayoutRect sideRect = outerBorder.rect(); + IntRect sideRect = outerBorder.rect(); int width; switch (side) { @@ -2556,6 +2614,53 @@ bool RenderBoxModelObject::borderObscuresBackground() const return true; } +bool RenderBoxModelObject::boxShadowShouldBeAppliedToBackground(BackgroundBleedAvoidance bleedAvoidance, InlineFlowBox* inlineFlowBox) const +{ + if (bleedAvoidance != BackgroundBleedNone) + return false; + + if (style()->hasAppearance()) + return false; + + bool hasOneNormalBoxShadow = false; + for (const ShadowData* currentShadow = style()->boxShadow(); currentShadow; currentShadow = currentShadow->next()) { + if (currentShadow->style() != Normal) + continue; + + if (hasOneNormalBoxShadow) + return false; + hasOneNormalBoxShadow = true; + + if (currentShadow->spread()) + return false; + } + + if (!hasOneNormalBoxShadow) + return false; + + Color backgroundColor = style()->visitedDependentColor(CSSPropertyBackgroundColor); + if (!backgroundColor.isValid() || backgroundColor.alpha() < 255) + return false; + + const FillLayer* lastBackgroundLayer = style()->backgroundLayers(); + for (const FillLayer* next = lastBackgroundLayer->next(); next; next = lastBackgroundLayer->next()) + lastBackgroundLayer = next; + + if (lastBackgroundLayer->clip() != BorderFillBox) + return false; + + if (lastBackgroundLayer->image() && style()->hasBorderRadius()) + return false; + + if (inlineFlowBox && !inlineFlowBox->boxShadowCanBeAppliedToBackground(*lastBackgroundLayer)) + return false; + + if (hasOverflowClip() && lastBackgroundLayer->attachment() == LocalBackgroundAttachment) + return false; + + return true; +} + static inline LayoutRect areaCastingShadowInHole(const LayoutRect& holeRect, int shadowBlur, int shadowSpread, const LayoutSize& shadowOffset) { LayoutRect bounds(holeRect); @@ -2634,7 +2739,7 @@ void RenderBoxModelObject::paintBoxShadow(const PaintInfo& info, const LayoutRec if (!rectToClipOut.isEmpty()) context->clipOutRoundedRect(rectToClipOut); - RoundedRect influenceRect(shadowRect, border.radii()); + RoundedRect influenceRect(pixelSnappedIntRect(shadowRect), border.radii()); influenceRect.expandRadii(2 * shadowBlur + shadowSpread); if (allCornersClippedOut(influenceRect, info.rect)) context->fillRect(fillRect.rect(), Color::black, s->colorSpace()); @@ -2658,7 +2763,7 @@ void RenderBoxModelObject::paintBoxShadow(const PaintInfo& info, const LayoutRec } if (!rectToClipOut.isEmpty()) - context->clipOut(rectToClipOut); + context->clipOut(pixelSnappedIntRect(rectToClipOut)); context->fillRect(fillRect.rect(), Color::black, s->colorSpace()); } } else { @@ -2693,7 +2798,7 @@ void RenderBoxModelObject::paintBoxShadow(const PaintInfo& info, const LayoutRec Color fillColor(shadowColor.red(), shadowColor.green(), shadowColor.blue(), 255); LayoutRect outerRect = areaCastingShadowInHole(border.rect(), shadowBlur, shadowSpread, shadowOffset); - RoundedRect roundedHole(holeRect, border.radii()); + RoundedRect roundedHole(pixelSnappedIntRect(holeRect), border.radii()); GraphicsContextStateSaver stateSaver(*context); if (hasBorderRadius) { @@ -2713,7 +2818,7 @@ void RenderBoxModelObject::paintBoxShadow(const PaintInfo& info, const LayoutRec else context->setShadow(shadowOffset, shadowBlur, shadowColor, s->colorSpace()); - context->fillRectWithRoundedHole(outerRect, roundedHole, fillColor, s->colorSpace()); + context->fillRectWithRoundedHole(pixelSnappedIntRect(outerRect), roundedHole, fillColor, s->colorSpace()); } } } diff --git a/Source/WebCore/rendering/RenderBoxModelObject.h b/Source/WebCore/rendering/RenderBoxModelObject.h index 027b1fb89..11e97c3fd 100644 --- a/Source/WebCore/rendering/RenderBoxModelObject.h +++ b/Source/WebCore/rendering/RenderBoxModelObject.h @@ -127,6 +127,8 @@ public: void paintBoxShadow(const PaintInfo&, const LayoutRect&, const RenderStyle*, ShadowStyle, bool includeLogicalLeftEdge = true, bool includeLogicalRightEdge = true); void paintFillLayerExtended(const PaintInfo&, const Color&, const FillLayer*, const LayoutRect&, BackgroundBleedAvoidance, InlineFlowBox* = 0, const LayoutSize& = LayoutSize(), CompositeOperator = CompositeSourceOver, RenderObject* backgroundObject = 0); + virtual bool boxShadowShouldBeAppliedToBackground(BackgroundBleedAvoidance, InlineFlowBox* = 0) const; + // Overridden by subclasses to determine line height and baseline position. virtual LayoutUnit lineHeight(bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const = 0; virtual LayoutUnit baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const = 0; @@ -218,7 +220,7 @@ private: BoxSide, bool firstEdgeMatches, bool secondEdgeMatches); void clipBorderSideForComplexInnerPath(GraphicsContext*, const RoundedRect&, const RoundedRect&, BoxSide, const class BorderEdge[]); void paintOneBorderSide(GraphicsContext*, const RenderStyle*, const RoundedRect& outerBorder, const RoundedRect& innerBorder, - const LayoutRect& sideRect, BoxSide, BoxSide adjacentSide1, BoxSide adjacentSide2, const class BorderEdge[], + const IntRect& sideRect, BoxSide, BoxSide adjacentSide1, BoxSide adjacentSide2, const class BorderEdge[], const Path*, BackgroundBleedAvoidance, bool includeLogicalLeftEdge, bool includeLogicalRightEdge, bool antialias, const Color* overrideColor = 0); void paintTranslucentBorderSides(GraphicsContext*, const RenderStyle*, const RoundedRect& outerBorder, const RoundedRect& innerBorder, const class BorderEdge[], BackgroundBleedAvoidance, bool includeLogicalLeftEdge, bool includeLogicalRightEdge, bool antialias = false); diff --git a/Source/WebCore/rendering/RenderButton.cpp b/Source/WebCore/rendering/RenderButton.cpp index e6d1920fe..dd23130a6 100644 --- a/Source/WebCore/rendering/RenderButton.cpp +++ b/Source/WebCore/rendering/RenderButton.cpp @@ -118,14 +118,6 @@ void RenderButton::updateFromElement() } } -bool RenderButton::canHaveChildren() const -{ - // Input elements can't have children, but button elements can. We'll - // write the code assuming any other button types that might emerge in the future - // can also have children. - return !node()->hasTagName(inputTag); -} - void RenderButton::setText(const String& str) { if (str.isEmpty()) { @@ -157,6 +149,11 @@ void RenderButton::updateBeforeAfterContent(PseudoId type) children()->updateBeforeAfterContent(this, type); } +RenderText* RenderButton::buttonText() const +{ + return m_buttonText; +} + LayoutRect RenderButton::controlClipRect(const LayoutPoint& additionalOffset) const { // Clip to the padding box to at least give content the extra padding space. diff --git a/Source/WebCore/rendering/RenderButton.h b/Source/WebCore/rendering/RenderButton.h index 24cecd2f2..c851abc7d 100644 --- a/Source/WebCore/rendering/RenderButton.h +++ b/Source/WebCore/rendering/RenderButton.h @@ -50,14 +50,13 @@ public: virtual void updateBeforeAfterContent(PseudoId); + virtual RenderText* buttonText() const OVERRIDE; virtual bool hasControlClip() const { return true; } virtual LayoutRect controlClipRect(const LayoutPoint&) const; void setText(const String&); String text() const; - virtual bool canHaveChildren() const; - private: virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle); virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); diff --git a/Source/WebCore/rendering/RenderDeprecatedFlexibleBox.h b/Source/WebCore/rendering/RenderDeprecatedFlexibleBox.h index 417ebac75..101bedbe3 100644 --- a/Source/WebCore/rendering/RenderDeprecatedFlexibleBox.h +++ b/Source/WebCore/rendering/RenderDeprecatedFlexibleBox.h @@ -49,6 +49,7 @@ public: virtual bool isDeprecatedFlexibleBox() const { return true; } virtual bool isFlexingChildren() const { return m_flexingChildren; } virtual bool isStretchingChildren() const { return m_stretchingChildren; } + virtual RenderText* buttonText() const { return 0; } void placeChild(RenderBox* child, const LayoutPoint& location); diff --git a/Source/WebCore/rendering/RenderDetailsMarker.cpp b/Source/WebCore/rendering/RenderDetailsMarker.cpp index 0b1de6973..c1468b543 100644 --- a/Source/WebCore/rendering/RenderDetailsMarker.cpp +++ b/Source/WebCore/rendering/RenderDetailsMarker.cpp @@ -132,7 +132,7 @@ void RenderDetailsMarker::paint(PaintInfo& paintInfo, const LayoutPoint& paintOf overflowRect.moveBy(boxOrigin); overflowRect.inflate(maximalOutlineSize(paintInfo.phase)); - if (!paintInfo.rect.intersects(overflowRect)) + if (!paintInfo.rect.intersects(pixelSnappedIntRect(overflowRect))) return; const Color color(style()->visitedDependentColor(CSSPropertyColor)); diff --git a/Source/WebCore/rendering/RenderEmbeddedObject.cpp b/Source/WebCore/rendering/RenderEmbeddedObject.cpp index 0140c1ed6..bdafd62d5 100644 --- a/Source/WebCore/rendering/RenderEmbeddedObject.cpp +++ b/Source/WebCore/rendering/RenderEmbeddedObject.cpp @@ -190,7 +190,7 @@ void RenderEmbeddedObject::paintReplaced(PaintInfo& paintInfo, const LayoutPoint bool RenderEmbeddedObject::getReplacementTextGeometry(const LayoutPoint& accumulatedOffset, FloatRect& contentRect, Path& path, FloatRect& replacementTextRect, Font& font, TextRun& run, float& textWidth) const { contentRect = contentBoxRect(); - contentRect.moveBy(accumulatedOffset); + contentRect.moveBy(roundedIntPoint(accumulatedOffset)); FontDescription fontDescription; RenderTheme::defaultTheme()->systemFont(CSSValueWebkitSmallControl, fontDescription); diff --git a/Source/WebCore/rendering/RenderFieldset.cpp b/Source/WebCore/rendering/RenderFieldset.cpp index 3a70866e2..1d18bb9df 100644 --- a/Source/WebCore/rendering/RenderFieldset.cpp +++ b/Source/WebCore/rendering/RenderFieldset.cpp @@ -132,16 +132,17 @@ void RenderFieldset::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint // cases the legend is embedded in the right and bottom borders respectively. // https://bugs.webkit.org/show_bug.cgi?id=47236 if (style()->isHorizontalWritingMode()) { - LayoutUnit yOff = (legend->y() > 0) ? 0 : (legend->height() - borderTop()) / 2; + LayoutUnit yOff = (legend->y() > 0) ? zeroLayoutUnit : (legend->height() - borderTop()) / 2; paintRect.setHeight(paintRect.height() - yOff); paintRect.setY(paintRect.y() + yOff); } else { - LayoutUnit xOff = (legend->x() > 0) ? 0 : (legend->width() - borderLeft()) / 2; + LayoutUnit xOff = (legend->x() > 0) ? zeroLayoutUnit : (legend->width() - borderLeft()) / 2; paintRect.setWidth(paintRect.width() - xOff); paintRect.setX(paintRect.x() + xOff); } - - paintBoxShadow(paintInfo, paintRect, style(), Normal); + + if (!boxShadowShouldBeAppliedToBackground(determineBackgroundBleedAvoidance(paintInfo.context))) + paintBoxShadow(paintInfo, paintRect, style(), Normal); paintFillLayers(paintInfo, style()->visitedDependentColor(CSSPropertyBackgroundColor), style()->backgroundLayers(), paintRect); paintBoxShadow(paintInfo, paintRect, style(), Inset); diff --git a/Source/WebCore/rendering/RenderFileUploadControl.cpp b/Source/WebCore/rendering/RenderFileUploadControl.cpp index a1ae15b5c..a927f3fae 100644 --- a/Source/WebCore/rendering/RenderFileUploadControl.cpp +++ b/Source/WebCore/rendering/RenderFileUploadControl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2007, 2012 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -32,6 +32,7 @@ #include "RenderText.h" #include "RenderTheme.h" #include "ShadowRoot.h" +#include "ShadowRootList.h" #include "TextRun.h" #include "VisiblePosition.h" #include <math.h> @@ -85,7 +86,7 @@ void RenderFileUploadControl::updateFromElement() static int nodeWidth(Node* node) { - return node ? node->renderBox()->width() : 0; + return node ? node->renderBox()->width() : zeroLayoutUnit; } int RenderFileUploadControl::maxFilenameWidth() const @@ -177,10 +178,15 @@ void RenderFileUploadControl::computePreferredLogicalWidths() else { // Figure out how big the filename space needs to be for a given number of characters // (using "0" as the nominal character). - const UChar ch = '0'; - const String str = String(&ch, 1); - float charWidth = font.width(constructTextRun(this, font, str, style, TextRun::AllowTrailingExpansion)); - m_maxPreferredLogicalWidth = (int)ceilf(charWidth * defaultWidthNumChars); + const UChar character = '0'; + const String characterAsString = String(&character, 1); + float minDefaultLabelWidth = defaultWidthNumChars * font.width(constructTextRun(this, font, characterAsString, style, TextRun::AllowTrailingExpansion)); + + const String label = theme()->fileListDefaultLabel(node()->toInputElement()->multiple()); + float defaultLabelWidth = font.width(constructTextRun(this, font, label, style, TextRun::AllowTrailingExpansion)); + if (HTMLInputElement* button = uploadButton()) + defaultLabelWidth += button->renderer()->maxPreferredLogicalWidth() + afterButtonSpacing; + m_maxPreferredLogicalWidth = static_cast<int>(ceilf(max(minDefaultLabelWidth, defaultLabelWidth))); } if (style->minWidth().isFixed() && style->minWidth().value() > 0) { @@ -212,9 +218,9 @@ HTMLInputElement* RenderFileUploadControl::uploadButton() const { HTMLInputElement* input = static_cast<HTMLInputElement*>(node()); - ASSERT(input->shadowRoot()); + ASSERT(input->hasShadowRoot()); - Node* buttonNode = input->shadowRoot()->firstChild(); + Node* buttonNode = input->shadowRootList()->oldestShadowRoot()->firstChild(); return buttonNode && buttonNode->isHTMLElement() && buttonNode->hasTagName(inputTag) ? static_cast<HTMLInputElement*>(buttonNode) : 0; } diff --git a/Source/WebCore/rendering/RenderFileUploadControl.h b/Source/WebCore/rendering/RenderFileUploadControl.h index 30ee6231c..11d959dac 100644 --- a/Source/WebCore/rendering/RenderFileUploadControl.h +++ b/Source/WebCore/rendering/RenderFileUploadControl.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2007, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2007, 2009, 2012 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public diff --git a/Source/WebCore/rendering/RenderFlexibleBox.cpp b/Source/WebCore/rendering/RenderFlexibleBox.cpp index b025cd317..f2f993d7b 100644 --- a/Source/WebCore/rendering/RenderFlexibleBox.cpp +++ b/Source/WebCore/rendering/RenderFlexibleBox.cpp @@ -40,55 +40,13 @@ namespace WebCore { // Normally, -1 and 0 are not valid in a HashSet, but these are relatively likely flex-order values. Instead, // we make the two smallest int values invalid flex-order values (in the css parser code we clamp them to // int min + 2). -struct FlexOrderHashTraits : WTF::GenericHashTraits<int> { +struct RenderFlexibleBox::FlexOrderHashTraits : WTF::GenericHashTraits<int> { static const bool emptyValueIsZero = false; static int emptyValue() { return std::numeric_limits<int>::min(); } static void constructDeletedValue(int& slot) { slot = std::numeric_limits<int>::min() + 1; } static bool isDeletedValue(int value) { return value == std::numeric_limits<int>::min() + 1; } }; -typedef HashSet<int, DefaultHash<int>::Hash, FlexOrderHashTraits> FlexOrderHashSet; - -class RenderFlexibleBox::TreeOrderIterator { -public: - explicit TreeOrderIterator(RenderFlexibleBox* flexibleBox) - : m_flexibleBox(flexibleBox) - , m_currentChild(0) - { - } - - RenderBox* first() - { - reset(); - return next(); - } - - RenderBox* next() - { - m_currentChild = m_currentChild ? m_currentChild->nextSiblingBox() : m_flexibleBox->firstChildBox(); - - if (m_currentChild) - m_flexOrderValues.add(m_currentChild->style()->flexOrder()); - - return m_currentChild; - } - - void reset() - { - m_currentChild = 0; - } - - const FlexOrderHashSet& flexOrderValues() - { - return m_flexOrderValues; - } - -private: - RenderFlexibleBox* m_flexibleBox; - RenderBox* m_currentChild; - FlexOrderHashSet m_flexOrderValues; -}; - class RenderFlexibleBox::FlexOrderIterator { public: FlexOrderIterator(RenderFlexibleBox* flexibleBox, const FlexOrderHashSet& flexOrderValues) @@ -156,6 +114,84 @@ const char* RenderFlexibleBox::renderName() const return "RenderFlexibleBox"; } +static LayoutUnit marginLogicalWidthForChild(RenderBox* child, RenderStyle* parentStyle) +{ + // A margin has three types: fixed, percentage, and auto (variable). + // Auto and percentage margins become 0 when computing min/max width. + // Fixed margins can be added in as is. + Length marginLeft = child->style()->marginStartUsing(parentStyle); + Length marginRight = child->style()->marginEndUsing(parentStyle); + LayoutUnit margin = 0; + if (marginLeft.isFixed()) + margin += marginLeft.value(); + if (marginRight.isFixed()) + margin += marginRight.value(); + return margin; +} + +void RenderFlexibleBox::computePreferredLogicalWidths() +{ + ASSERT(preferredLogicalWidthsDirty()); + + RenderStyle* styleToUse = style(); + if (styleToUse->logicalWidth().isFixed() && styleToUse->logicalWidth().value() > 0) + m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = computeContentBoxLogicalWidth(styleToUse->logicalWidth().value()); + else { + m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = 0; + + for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) { + if (child->isPositioned()) + continue; + + LayoutUnit margin = marginLogicalWidthForChild(child, style()); + bool hasOrthogonalWritingMode = child->isHorizontalWritingMode() != isHorizontalWritingMode(); + LayoutUnit minPreferredLogicalWidth = hasOrthogonalWritingMode ? child->logicalHeight() : child->minPreferredLogicalWidth(); + LayoutUnit maxPreferredLogicalWidth = hasOrthogonalWritingMode ? child->logicalHeight() : child->maxPreferredLogicalWidth(); + minPreferredLogicalWidth += margin; + maxPreferredLogicalWidth += margin; + if (!isColumnFlow()) { + m_minPreferredLogicalWidth += minPreferredLogicalWidth; + m_maxPreferredLogicalWidth += maxPreferredLogicalWidth; + } else { + m_minPreferredLogicalWidth = std::max(minPreferredLogicalWidth, m_minPreferredLogicalWidth); + m_maxPreferredLogicalWidth = std::max(maxPreferredLogicalWidth, m_maxPreferredLogicalWidth); + } + } + + m_maxPreferredLogicalWidth = std::max(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth); + } + + LayoutUnit scrollbarWidth = 0; + if (hasOverflowClip()) { + if (isHorizontalWritingMode() && styleToUse->overflowY() == OSCROLL) { + layer()->setHasVerticalScrollbar(true); + scrollbarWidth = verticalScrollbarWidth(); + } else if (!isHorizontalWritingMode() && styleToUse->overflowX() == OSCROLL) { + layer()->setHasHorizontalScrollbar(true); + scrollbarWidth = horizontalScrollbarHeight(); + } + } + + m_maxPreferredLogicalWidth += scrollbarWidth; + m_minPreferredLogicalWidth += scrollbarWidth; + + if (styleToUse->logicalMinWidth().isFixed() && styleToUse->logicalMinWidth().value() > 0) { + m_maxPreferredLogicalWidth = std::max(m_maxPreferredLogicalWidth, computeContentBoxLogicalWidth(styleToUse->logicalMinWidth().value())); + m_minPreferredLogicalWidth = std::max(m_minPreferredLogicalWidth, computeContentBoxLogicalWidth(styleToUse->logicalMinWidth().value())); + } + + if (styleToUse->logicalMaxWidth().isFixed()) { + m_maxPreferredLogicalWidth = std::min(m_maxPreferredLogicalWidth, computeContentBoxLogicalWidth(styleToUse->logicalMaxWidth().value())); + m_minPreferredLogicalWidth = std::min(m_minPreferredLogicalWidth, computeContentBoxLogicalWidth(styleToUse->logicalMaxWidth().value())); + } + + LayoutUnit borderAndPadding = borderAndPaddingLogicalWidth(); + m_minPreferredLogicalWidth += borderAndPadding; + m_maxPreferredLogicalWidth += borderAndPadding; + + setPreferredLogicalWidthsDirty(false); +} + void RenderFlexibleBox::layoutBlock(bool relayoutChildren, int, BlockLayoutPass) { ASSERT(needsLayout()); @@ -465,26 +501,25 @@ LayoutUnit RenderFlexibleBox::preferredMainAxisContentExtentForChild(RenderBox* void RenderFlexibleBox::layoutFlexItems(bool relayoutChildren) { + FlexOrderHashSet flexOrderValues; + computeMainAxisPreferredSizes(relayoutChildren, flexOrderValues); + + OrderedFlexItemList orderedChildren; + LayoutUnit preferredMainAxisExtent; float totalPositiveFlexibility; float totalNegativeFlexibility; - TreeOrderIterator treeIterator(this); + FlexOrderIterator flexIterator(this, flexOrderValues); + computeFlexOrder(flexIterator, orderedChildren, preferredMainAxisExtent, totalPositiveFlexibility, totalNegativeFlexibility); - WTF::Vector<LayoutUnit> preferredSizes; - computeMainAxisPreferredSizes(relayoutChildren, treeIterator, preferredSizes, totalPositiveFlexibility, totalNegativeFlexibility); - LayoutUnit preferredMainAxisExtent = 0; - for (size_t i = 0; i < preferredSizes.size(); ++i) - preferredMainAxisExtent += preferredSizes[i]; LayoutUnit availableFreeSpace = mainAxisContentExtent() - preferredMainAxisExtent; - - FlexOrderIterator flexIterator(this, treeIterator.flexOrderValues()); InflexibleFlexItemSize inflexibleItems; WTF::Vector<LayoutUnit> childSizes; - while (!runFreeSpaceAllocationAlgorithm(flexIterator, availableFreeSpace, totalPositiveFlexibility, totalNegativeFlexibility, inflexibleItems, childSizes)) { + while (!runFreeSpaceAllocationAlgorithm(orderedChildren, availableFreeSpace, totalPositiveFlexibility, totalNegativeFlexibility, inflexibleItems, childSizes)) { ASSERT(totalPositiveFlexibility >= 0 && totalNegativeFlexibility >= 0); ASSERT(inflexibleItems.size() > 0); } - layoutAndPlaceChildren(flexIterator, childSizes, availableFreeSpace, totalPositiveFlexibility); + layoutAndPlaceChildren(orderedChildren, childSizes, availableFreeSpace); } float RenderFlexibleBox::positiveFlexForChild(RenderBox* child) const @@ -512,16 +547,14 @@ LayoutUnit RenderFlexibleBox::marginBoxAscent(RenderBox* child) return ascent + flowAwareMarginBeforeForChild(child); } -void RenderFlexibleBox::computeMainAxisPreferredSizes(bool relayoutChildren, TreeOrderIterator& iterator, WTF::Vector<LayoutUnit>& preferredSizes, float& totalPositiveFlexibility, float& totalNegativeFlexibility) +void RenderFlexibleBox::computeMainAxisPreferredSizes(bool relayoutChildren, FlexOrderHashSet& flexOrderValues) { - totalPositiveFlexibility = totalNegativeFlexibility = 0; - LayoutUnit flexboxAvailableContentExtent = mainAxisContentExtent(); - for (RenderBox* child = iterator.first(); child; child = iterator.next()) { - if (child->isPositioned()) { - preferredSizes.append(0); + for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) { + flexOrderValues.add(child->style()->flexOrder()); + + if (child->isPositioned()) continue; - } child->clearOverrideSize(); if (mainAxisLengthForChild(child).isAuto()) { @@ -530,35 +563,51 @@ void RenderFlexibleBox::computeMainAxisPreferredSizes(bool relayoutChildren, Tre child->layoutIfNeeded(); } - LayoutUnit preferredSize = mainAxisBorderAndPaddingExtentForChild(child) + preferredMainAxisContentExtentForChild(child); - // We set the margins because we want to make sure 'auto' has a margin // of 0 and because if we're not auto sizing, we don't do a layout that // computes the start/end margins. if (isHorizontalFlow()) { child->setMarginLeft(child->style()->marginLeft().calcMinValue(flexboxAvailableContentExtent)); child->setMarginRight(child->style()->marginRight().calcMinValue(flexboxAvailableContentExtent)); - preferredSize += child->marginLeft() + child->marginRight(); } else { child->setMarginTop(child->style()->marginTop().calcMinValue(flexboxAvailableContentExtent)); child->setMarginBottom(child->style()->marginBottom().calcMinValue(flexboxAvailableContentExtent)); - preferredSize += child->marginTop() + child->marginBottom(); } + } +} + +void RenderFlexibleBox::computeFlexOrder(FlexOrderIterator& iterator, OrderedFlexItemList& orderedChildren, LayoutUnit& preferredMainAxisExtent, float& totalPositiveFlexibility, float& totalNegativeFlexibility) +{ + orderedChildren.clear(); + preferredMainAxisExtent = 0; + totalPositiveFlexibility = totalNegativeFlexibility = 0; + for (RenderBox* child = iterator.first(); child; child = iterator.next()) { + orderedChildren.append(child); + if (child->isPositioned()) + continue; - preferredSizes.append(preferredSize); + LayoutUnit childMainAxisExtent = mainAxisBorderAndPaddingExtentForChild(child) + preferredMainAxisContentExtentForChild(child); + if (isHorizontalFlow()) + childMainAxisExtent += child->marginLeft() + child->marginRight(); + else + childMainAxisExtent += child->marginTop() + child->marginBottom(); + // FIXME: When implementing multiline, we would return here if adding + // the child's main axis extent would cause us to overflow. + preferredMainAxisExtent += childMainAxisExtent; totalPositiveFlexibility += positiveFlexForChild(child); totalNegativeFlexibility += negativeFlexForChild(child); } } // Returns true if we successfully ran the algorithm and sized the flex items. -bool RenderFlexibleBox::runFreeSpaceAllocationAlgorithm(FlexOrderIterator& iterator, LayoutUnit& availableFreeSpace, float& totalPositiveFlexibility, float& totalNegativeFlexibility, InflexibleFlexItemSize& inflexibleItems, WTF::Vector<LayoutUnit>& childSizes) +bool RenderFlexibleBox::runFreeSpaceAllocationAlgorithm(const OrderedFlexItemList& children, LayoutUnit& availableFreeSpace, float& totalPositiveFlexibility, float& totalNegativeFlexibility, InflexibleFlexItemSize& inflexibleItems, WTF::Vector<LayoutUnit>& childSizes) { childSizes.clear(); LayoutUnit flexboxAvailableContentExtent = mainAxisContentExtent(); - for (RenderBox* child = iterator.first(); child; child = iterator.next()) { + for (size_t i = 0; i < children.size(); ++i) { + RenderBox* child = children[i]; if (child->isPositioned()) { childSizes.append(0); continue; @@ -600,27 +649,25 @@ bool RenderFlexibleBox::runFreeSpaceAllocationAlgorithm(FlexOrderIterator& itera return true; } -static bool hasPackingSpace(LayoutUnit availableFreeSpace, float totalPositiveFlexibility) -{ - return availableFreeSpace > 0 && !totalPositiveFlexibility; -} - -static LayoutUnit initialPackingOffset(LayoutUnit availableFreeSpace, float totalPositiveFlexibility, EFlexPack flexPack, size_t numberOfChildren) +static LayoutUnit initialPackingOffset(LayoutUnit availableFreeSpace, EFlexPack flexPack, size_t numberOfChildren) { - if (hasPackingSpace(availableFreeSpace, totalPositiveFlexibility)) { + if (availableFreeSpace > 0) { if (flexPack == PackEnd) return availableFreeSpace; if (flexPack == PackCenter) return availableFreeSpace / 2; if (flexPack == PackDistribute && numberOfChildren) return availableFreeSpace / (2 * numberOfChildren); + } else if (availableFreeSpace < 0) { + if (flexPack == PackCenter || flexPack == PackDistribute) + return availableFreeSpace / 2; } return 0; } -static LayoutUnit packingSpaceBetweenChildren(LayoutUnit availableFreeSpace, float totalPositiveFlexibility, EFlexPack flexPack, size_t numberOfChildren) +static LayoutUnit packingSpaceBetweenChildren(LayoutUnit availableFreeSpace, EFlexPack flexPack, size_t numberOfChildren) { - if (hasPackingSpace(availableFreeSpace, totalPositiveFlexibility) && numberOfChildren > 1) { + if (availableFreeSpace > 0 && numberOfChildren > 1) { if (flexPack == PackJustify) return availableFreeSpace / (numberOfChildren - 1); if (flexPack == PackDistribute) @@ -664,10 +711,10 @@ static EFlexAlign flexAlignForChild(RenderBox* child) return align; } -void RenderFlexibleBox::layoutAndPlaceChildren(FlexOrderIterator& iterator, const WTF::Vector<LayoutUnit>& childSizes, LayoutUnit availableFreeSpace, float totalPositiveFlexibility) +void RenderFlexibleBox::layoutAndPlaceChildren(const OrderedFlexItemList& children, const WTF::Vector<LayoutUnit>& childSizes, LayoutUnit availableFreeSpace) { LayoutUnit mainAxisOffset = flowAwareBorderStart() + flowAwarePaddingStart(); - mainAxisOffset += initialPackingOffset(availableFreeSpace, totalPositiveFlexibility, style()->flexPack(), childSizes.size()); + mainAxisOffset += initialPackingOffset(availableFreeSpace, style()->flexPack(), childSizes.size()); if (style()->flexDirection() == FlowRowReverse) mainAxisOffset += isHorizontalFlow() ? verticalScrollbarWidth() : horizontalScrollbarHeight(); @@ -675,11 +722,11 @@ void RenderFlexibleBox::layoutAndPlaceChildren(FlexOrderIterator& iterator, cons LayoutUnit totalMainExtent = mainAxisExtent(); LayoutUnit maxAscent = 0, maxDescent = 0; // Used when flex-align: baseline. bool shouldFlipMainAxis = !isColumnFlow() && !isLeftToRightFlow(); - size_t i = 0; - for (RenderBox* child = iterator.first(); child; child = iterator.next(), ++i) { + for (size_t i = 0; i < children.size(); ++i) { + RenderBox* child = children[i]; if (child->isPositioned()) { prepareChildForPositionedLayout(child, mainAxisOffset, crossAxisOffset); - mainAxisOffset += packingSpaceBetweenChildren(availableFreeSpace, totalPositiveFlexibility, style()->flexPack(), childSizes.size()); + mainAxisOffset += packingSpaceBetweenChildren(availableFreeSpace, style()->flexPack(), childSizes.size()); continue; } LayoutUnit childPreferredSize = childSizes[i] + mainAxisBorderAndPaddingExtentForChild(child); @@ -687,6 +734,7 @@ void RenderFlexibleBox::layoutAndPlaceChildren(FlexOrderIterator& iterator, cons child->setChildNeedsLayout(true); child->layoutIfNeeded(); + LayoutUnit childCrossAxisExtent; if (flexAlignForChild(child) == AlignBaseline) { LayoutUnit ascent = marginBoxAscent(child); LayoutUnit descent = (crossAxisMarginExtentForChild(child) + crossAxisExtentForChild(child)) - ascent; @@ -694,10 +742,11 @@ void RenderFlexibleBox::layoutAndPlaceChildren(FlexOrderIterator& iterator, cons maxAscent = std::max(maxAscent, ascent); maxDescent = std::max(maxDescent, descent); - if (crossAxisLength().isAuto()) - setCrossAxisExtent(std::max(crossAxisExtent(), crossAxisBorderAndPaddingExtent() + crossAxisMarginExtentForChild(child) + maxAscent + maxDescent + crossAxisScrollbarExtent())); - } else if (crossAxisLength().isAuto()) - setCrossAxisExtent(std::max(crossAxisExtent(), crossAxisBorderAndPaddingExtent() + crossAxisMarginExtentForChild(child) + crossAxisExtentForChild(child) + crossAxisScrollbarExtent())); + childCrossAxisExtent = maxAscent + maxDescent; + } else + childCrossAxisExtent = crossAxisExtentForChild(child); + if (crossAxisLength().isAuto()) + setCrossAxisExtent(std::max(crossAxisExtent(), crossAxisBorderAndPaddingExtent() + crossAxisMarginExtentForChild(child) + childCrossAxisExtent + crossAxisScrollbarExtent())); mainAxisOffset += flowAwareMarginStartForChild(child); @@ -709,7 +758,7 @@ void RenderFlexibleBox::layoutAndPlaceChildren(FlexOrderIterator& iterator, cons setFlowAwareLocationForChild(child, childLocation); mainAxisOffset += childMainExtent + flowAwareMarginEndForChild(child); - mainAxisOffset += packingSpaceBetweenChildren(availableFreeSpace, totalPositiveFlexibility, style()->flexPack(), childSizes.size()); + mainAxisOffset += packingSpaceBetweenChildren(availableFreeSpace, style()->flexPack(), childSizes.size()); if (isColumnFlow()) setLogicalHeight(mainAxisOffset + flowAwareBorderEnd() + flowAwarePaddingEnd() + scrollbarLogicalHeight()); @@ -719,27 +768,27 @@ void RenderFlexibleBox::layoutAndPlaceChildren(FlexOrderIterator& iterator, cons // We have to do an extra pass for column-reverse to reposition the flex items since the start depends // on the height of the flexbox, which we only know after we've positioned all the flex items. computeLogicalHeight(); - layoutColumnReverse(iterator, childSizes, availableFreeSpace, totalPositiveFlexibility); + layoutColumnReverse(children, childSizes, availableFreeSpace); } - alignChildren(iterator, maxAscent); + alignChildren(children, maxAscent); } -void RenderFlexibleBox::layoutColumnReverse(FlexOrderIterator& iterator, const WTF::Vector<LayoutUnit>& childSizes, LayoutUnit availableFreeSpace, float totalPositiveFlexibility) +void RenderFlexibleBox::layoutColumnReverse(const OrderedFlexItemList& children, const WTF::Vector<LayoutUnit>& childSizes, LayoutUnit availableFreeSpace) { // This is similar to the logic in layoutAndPlaceChildren, except we place the children // starting from the end of the flexbox. We also don't need to layout anything since we're // just moving the children to a new position. LayoutUnit mainAxisOffset = logicalHeight() - flowAwareBorderEnd() - flowAwarePaddingEnd(); - mainAxisOffset -= initialPackingOffset(availableFreeSpace, totalPositiveFlexibility, style()->flexPack(), childSizes.size()); + mainAxisOffset -= initialPackingOffset(availableFreeSpace, style()->flexPack(), childSizes.size()); mainAxisOffset -= isHorizontalFlow() ? verticalScrollbarWidth() : horizontalScrollbarHeight(); LayoutUnit crossAxisOffset = flowAwareBorderBefore() + flowAwarePaddingBefore(); - size_t i = 0; - for (RenderBox* child = iterator.first(); child; child = iterator.next(), ++i) { + for (size_t i = 0; i < children.size(); ++i) { + RenderBox* child = children[i]; if (child->isPositioned()) { child->layer()->setStaticBlockPosition(mainAxisOffset); - mainAxisOffset -= packingSpaceBetweenChildren(availableFreeSpace, totalPositiveFlexibility, style()->flexPack(), childSizes.size()); + mainAxisOffset -= packingSpaceBetweenChildren(availableFreeSpace, style()->flexPack(), childSizes.size()); continue; } mainAxisOffset -= mainAxisExtentForChild(child) + flowAwareMarginEndForChild(child); @@ -750,7 +799,7 @@ void RenderFlexibleBox::layoutColumnReverse(FlexOrderIterator& iterator, const W child->repaintDuringLayoutIfMoved(oldRect); mainAxisOffset -= flowAwareMarginStartForChild(child); - mainAxisOffset -= packingSpaceBetweenChildren(availableFreeSpace, totalPositiveFlexibility, style()->flexPack(), childSizes.size()); + mainAxisOffset -= packingSpaceBetweenChildren(availableFreeSpace, style()->flexPack(), childSizes.size()); } } @@ -767,19 +816,12 @@ void RenderFlexibleBox::adjustAlignmentForChild(RenderBox* child, LayoutUnit del child->repaintDuringLayoutIfMoved(oldRect); } -void RenderFlexibleBox::alignChildren(FlexOrderIterator& iterator, LayoutUnit maxAscent) +void RenderFlexibleBox::alignChildren(const OrderedFlexItemList& children, LayoutUnit maxAscent) { LayoutUnit crossExtent = crossAxisExtent(); - for (RenderBox* child = iterator.first(); child; child = iterator.next()) { - // direction:rtl + flex-direction:column means the cross-axis direction is flipped. - if (!style()->isLeftToRightDirection() && isColumnFlow()) { - LayoutPoint location = flowAwareLocationForChild(child); - location.setY(crossExtent - crossAxisExtentForChild(child) - location.y()); - setFlowAwareLocationForChild(child, location); - } - - // FIXME: Make sure this does the right thing with column flows. + for (size_t i = 0; i < children.size(); ++i) { + RenderBox* child = children[i]; switch (flexAlignForChild(child)) { case AlignAuto: ASSERT_NOT_REACHED(); @@ -814,6 +856,14 @@ void RenderFlexibleBox::alignChildren(FlexOrderIterator& iterator, LayoutUnit ma break; } } + + // direction:rtl + flex-direction:column means the cross-axis direction is flipped. + if (!style()->isLeftToRightDirection() && isColumnFlow()) { + LayoutPoint location = flowAwareLocationForChild(child); + location.setY(crossExtent - crossAxisExtentForChild(child) - location.y()); + setFlowAwareLocationForChild(child, location); + } + } } diff --git a/Source/WebCore/rendering/RenderFlexibleBox.h b/Source/WebCore/rendering/RenderFlexibleBox.h index 0833217b6..0ee715f7e 100644 --- a/Source/WebCore/rendering/RenderFlexibleBox.h +++ b/Source/WebCore/rendering/RenderFlexibleBox.h @@ -43,15 +43,18 @@ public: virtual const char* renderName() const; virtual bool isFlexibleBox() const { return true; } - + virtual void computePreferredLogicalWidths(); virtual void layoutBlock(bool relayoutChildren, int pageLogicalHeight = 0, BlockLayoutPass = NormalLayoutPass); bool isHorizontalFlow() const; private: - class TreeOrderIterator; + struct FlexOrderHashTraits; + typedef HashSet<int, DefaultHash<int>::Hash, FlexOrderHashTraits> FlexOrderHashSet; + class FlexOrderIterator; typedef WTF::HashMap<const RenderBox*, LayoutUnit> InflexibleFlexItemSize; + typedef WTF::Vector<RenderBox*> OrderedFlexItemList; bool hasOrthogonalFlow(RenderBox* child) const; bool isColumnFlow() const; @@ -95,13 +98,14 @@ private: LayoutUnit availableAlignmentSpaceForChild(RenderBox*); LayoutUnit marginBoxAscent(RenderBox*); - void computeMainAxisPreferredSizes(bool relayoutChildren, TreeOrderIterator&, WTF::Vector<LayoutUnit>&, float& totalPositiveFlexibility, float& totalNegativeFlexibility); - bool runFreeSpaceAllocationAlgorithm(FlexOrderIterator&, LayoutUnit& availableFreeSpace, float& totalPositiveFlexibility, float& totalNegativeFlexibility, InflexibleFlexItemSize&, WTF::Vector<LayoutUnit>& childSizes); + void computeMainAxisPreferredSizes(bool relayoutChildren, FlexOrderHashSet&); + void computeFlexOrder(FlexOrderIterator&, OrderedFlexItemList& orderedChildren, LayoutUnit& preferredMainAxisExtent, float& totalPositiveFlexibility, float& totalNegativeFlexibility); + bool runFreeSpaceAllocationAlgorithm(const OrderedFlexItemList&, LayoutUnit& availableFreeSpace, float& totalPositiveFlexibility, float& totalNegativeFlexibility, InflexibleFlexItemSize&, WTF::Vector<LayoutUnit>& childSizes); void setLogicalOverrideSize(RenderBox* child, LayoutUnit childPreferredSize); void prepareChildForPositionedLayout(RenderBox* child, LayoutUnit mainAxisOffset, LayoutUnit crossAxisOffset); - void layoutAndPlaceChildren(FlexOrderIterator&, const WTF::Vector<LayoutUnit>& childSizes, LayoutUnit availableFreeSpace, float totalPositiveFlexibility); - void layoutColumnReverse(FlexOrderIterator&, const WTF::Vector<LayoutUnit>& childSizes, LayoutUnit availableFreeSpace, float totalPositiveFlexibility); - void alignChildren(FlexOrderIterator&, LayoutUnit maxAscent); + void layoutAndPlaceChildren(const OrderedFlexItemList&, const WTF::Vector<LayoutUnit>& childSizes, LayoutUnit availableFreeSpace); + void layoutColumnReverse(const OrderedFlexItemList&, const WTF::Vector<LayoutUnit>& childSizes, LayoutUnit availableFreeSpace); + void alignChildren(const OrderedFlexItemList&, LayoutUnit maxAscent); }; } // namespace WebCore diff --git a/Source/WebCore/rendering/RenderFlowThread.cpp b/Source/WebCore/rendering/RenderFlowThread.cpp index 9e39d9607..9e47d4dc9 100644 --- a/Source/WebCore/rendering/RenderFlowThread.cpp +++ b/Source/WebCore/rendering/RenderFlowThread.cpp @@ -51,7 +51,9 @@ RenderFlowThread::RenderFlowThread(Node* node, const AtomicString& flowThread) , m_regionsInvalidated(false) , m_regionsHaveUniformLogicalWidth(true) , m_regionsHaveUniformLogicalHeight(true) + , m_overflow(false) { + ASSERT(node->document()->cssRegionsEnabled()); setIsAnonymous(false); setInRenderFlowThread(); } @@ -137,6 +139,15 @@ void RenderFlowThread::removeFlowChild(RenderObject* child) m_flowThreadChildList.remove(child); } +void RenderFlowThread::removeFlowChildInfo(RenderObject* child) +{ + if (child->isBox()) { + removeRenderBoxRegionInfo(toRenderBox(child)); + if (child->canHaveRegionStyle()) + clearRenderBoxCustomStyle(toRenderBox(child)); + } +} + // Compare two regions to determine in which one the content should flow first. // The function returns true if the first passed region is "less" than the second passed region. // If the first region appears before second region in DOM, @@ -373,10 +384,10 @@ void RenderFlowThread::layout() continue; LayoutRect regionRect; if (isHorizontalWritingMode()) { - regionRect = LayoutRect(style()->direction() == LTR ? 0 : logicalWidth() - region->contentWidth(), logicalHeight, region->contentWidth(), region->contentHeight()); + regionRect = LayoutRect(style()->direction() == LTR ? zeroLayoutUnit : logicalWidth() - region->contentWidth(), logicalHeight, region->contentWidth(), region->contentHeight()); logicalHeight += regionRect.height(); } else { - regionRect = LayoutRect(logicalHeight, style()->direction() == LTR ? 0 : logicalWidth() - region->contentHeight(), region->contentWidth(), region->contentHeight()); + regionRect = LayoutRect(logicalHeight, style()->direction() == LTR ? zeroLayoutUnit : logicalWidth() - region->contentHeight(), region->contentWidth(), region->contentHeight()); logicalHeight += regionRect.width(); } region->setRegionRect(regionRect); @@ -410,7 +421,7 @@ void RenderFlowThread::computeLogicalWidth() LayoutUnit regionLogicalWidth = isHorizontalWritingMode() ? region->contentWidth() : region->contentHeight(); if (regionLogicalWidth != logicalWidth) { - LayoutUnit logicalLeft = style()->direction() == LTR ? 0 : logicalWidth - regionLogicalWidth; + LayoutUnit logicalLeft = style()->direction() == LTR ? zeroLayoutUnit : logicalWidth - regionLogicalWidth; region->setRenderBoxRegionInfo(this, logicalLeft, regionLogicalWidth, false); } } @@ -445,7 +456,7 @@ void RenderFlowThread::paintIntoRegion(PaintInfo& paintInfo, RenderRegion* regio LayoutRect regionClippingRect(paintOffset + (regionOverflowRect.location() - regionRect.location()), regionOverflowRect.size()); PaintInfo info(paintInfo); - info.rect.intersect(regionClippingRect); + info.rect.intersect(pixelSnappedIntRect(regionClippingRect)); if (!info.rect.isEmpty()) { context->save(); @@ -464,7 +475,7 @@ void RenderFlowThread::paintIntoRegion(PaintInfo& paintInfo, RenderRegion* regio renderFlowThreadOffset = LayoutPoint(paintOffset - regionRect.location()); context->translate(renderFlowThreadOffset.x(), renderFlowThreadOffset.y()); - info.rect.moveBy(-renderFlowThreadOffset); + info.rect.moveBy(-roundedIntPoint(renderFlowThreadOffset)); layer()->paint(context, info.rect, 0, 0, region, RenderLayer::PaintLayerTemporaryClipRects); @@ -491,7 +502,7 @@ bool RenderFlowThread::hitTestRegion(RenderRegion* region, const HitTestRequest& LayoutPoint transformedPoint(pointInContainer.x() - renderFlowThreadOffset.x(), pointInContainer.y() - renderFlowThreadOffset.y()); // Always ignore clipping, since the RenderFlowThread has nothing to do with the bounds of the FrameView. - HitTestRequest newRequest(request.type() & HitTestRequest::IgnoreClipping); + HitTestRequest newRequest(request.type() | HitTestRequest::IgnoreClipping); RenderRegion* oldRegion = result.region(); result.setRegion(region); @@ -531,14 +542,14 @@ void RenderFlowThread::repaintRectangleInRegions(const LayoutRect& repaintRect, flipForWritingMode(flippedRegionRect); // Put the region rects into physical coordinates. flipForWritingMode(flippedRegionOverflowRect); - LayoutRect clippedRect(flippedRegionOverflowRect); - clippedRect.intersect(repaintRect); + LayoutRect clippedRect(repaintRect); + clippedRect.intersect(flippedRegionOverflowRect); if (clippedRect.isEmpty()) continue; - + // Put the region rect into the region's physical coordinate space. - clippedRect.setLocation(region->contentBoxRect().location() + (repaintRect.location() - flippedRegionRect.location())); - + clippedRect.setLocation(region->contentBoxRect().location() + (clippedRect.location() - flippedRegionRect.location())); + // Now switch to the region's writing mode coordinate space and let it repaint itself. region->flipForWritingMode(clippedRect); LayoutStateDisabler layoutStateDisabler(view()); // We can't use layout state to repaint, since the region is somewhere else. @@ -806,6 +817,9 @@ void RenderFlowThread::clearRenderBoxCustomStyle(const RenderBox* box, void RenderFlowThread::setRegionRangeForBox(const RenderBox* box, LayoutUnit offsetFromLogicalTopOfFirstPage) { + if (!hasRegions()) + return; + // FIXME: Not right for differing writing-modes. RenderRegion* startRegion = renderRegionForLine(offsetFromLogicalTopOfFirstPage, true); RenderRegion* endRegion = renderRegionForLine(offsetFromLogicalTopOfFirstPage + box->logicalHeight(), true); @@ -855,9 +869,40 @@ void RenderFlowThread::getRegionRangeForBox(const RenderBox* box, RenderRegion*& WebKitNamedFlow* RenderFlowThread::ensureNamedFlow() { if (!m_namedFlow) - m_namedFlow = WebKitNamedFlow::create(); + m_namedFlow = WebKitNamedFlow::create(this); return m_namedFlow.get(); } +void RenderFlowThread::computeOverflowStateForRegions(LayoutUnit oldClientAfterEdge) +{ + LayoutUnit height = oldClientAfterEdge; + // FIXME: the visual overflow of middle region (if it is the last one to contain any content in a render flow thread) + // might not be taken into account because the render flow thread height is greater that that regions height + its visual overflow + // because of how computeLogicalHeight is implemented for RenderFlowThread (as a sum of all regions height). + // This means that the middle region will be marked as fit (even if it has visual overflow flowing into the next region) + if (hasRenderOverflow()) + height = isHorizontalWritingMode() ? visualOverflowRect().maxY() : visualOverflowRect().maxX(); + + for (RenderRegionList::iterator iter = m_regionList.begin(); iter != m_regionList.end(); ++iter) { + RenderRegion* region = *iter; + if (!region->isValid()) { + region->setRegionState(RenderRegion::RegionUndefined); + continue; + } + LayoutUnit flowMin = height - (isHorizontalWritingMode() ? region->regionRect().y() : region->regionRect().x()); + LayoutUnit flowMax = height - (isHorizontalWritingMode() ? region->regionRect().maxY() : region->regionRect().maxX()); + RenderRegion::RegionState state = RenderRegion::RegionFit; + if (flowMin <= 0) + state = RenderRegion::RegionEmpty; + if (flowMax > 0) + state = RenderRegion::RegionOverflow; + region->setRegionState(state); + } + + // With the regions overflow state computed we can also set the overflow for the named flow. + RenderRegion* lastReg = lastRegion(); + m_overflow = lastReg && (lastReg->regionState() == RenderRegion::RegionOverflow); +} + } // namespace WebCore diff --git a/Source/WebCore/rendering/RenderFlowThread.h b/Source/WebCore/rendering/RenderFlowThread.h index 4b1b36663..d05938891 100644 --- a/Source/WebCore/rendering/RenderFlowThread.h +++ b/Source/WebCore/rendering/RenderFlowThread.h @@ -74,7 +74,12 @@ public: void addFlowChild(RenderObject* newChild, RenderObject* beforeChild = 0); void removeFlowChild(RenderObject*); + void removeFlowChildInfo(RenderObject*); bool hasChildren() const { return !m_flowThreadChildList.isEmpty(); } +#ifndef NDEBUG + bool hasChild(RenderObject* child) const { return m_flowThreadChildList.contains(child); } + bool hasChildInfo(RenderObject* child) const { return child && child->isBox() && m_regionRangeMap.contains(toRenderBox(child)); } +#endif void addRegionToThread(RenderRegion*); void removeRegionFromThread(RenderRegion*); @@ -128,7 +133,9 @@ public: const RenderRegion* oldStartRegion = 0, const RenderRegion* oldEndRegion = 0, const RenderRegion* newStartRegion = 0, const RenderRegion* newEndRegion = 0); WebKitNamedFlow* ensureNamedFlow(); + void computeOverflowStateForRegions(LayoutUnit oldClientAfterEdge); + bool overflow() const { return m_overflow; } private: virtual const char* renderName() const { return "RenderFlowThread"; } @@ -189,6 +196,7 @@ private: bool m_regionsInvalidated; bool m_regionsHaveUniformLogicalWidth; bool m_regionsHaveUniformLogicalHeight; + bool m_overflow; RefPtr<WebKitNamedFlow> m_namedFlow; }; diff --git a/Source/WebCore/rendering/RenderFrameSet.cpp b/Source/WebCore/rendering/RenderFrameSet.cpp index fc2c97f17..bcce93ef8 100644 --- a/Source/WebCore/rendering/RenderFrameSet.cpp +++ b/Source/WebCore/rendering/RenderFrameSet.cpp @@ -80,7 +80,7 @@ static Color borderFillColor() return Color(208, 208, 208); } -void RenderFrameSet::paintColumnBorder(const PaintInfo& paintInfo, const LayoutRect& borderRect) +void RenderFrameSet::paintColumnBorder(const PaintInfo& paintInfo, const IntRect& borderRect) { if (!paintInfo.rect.intersects(borderRect)) return; @@ -100,7 +100,7 @@ void RenderFrameSet::paintColumnBorder(const PaintInfo& paintInfo, const LayoutR } } -void RenderFrameSet::paintRowBorder(const PaintInfo& paintInfo, const LayoutRect& borderRect) +void RenderFrameSet::paintRowBorder(const PaintInfo& paintInfo, const IntRect& borderRect) { if (!paintInfo.rect.intersects(borderRect)) return; @@ -142,7 +142,7 @@ void RenderFrameSet::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset) child->paint(paintInfo, adjustedPaintOffset); xPos += m_cols.m_sizes[c]; if (borderThickness && m_cols.m_allowBorder[c + 1]) { - paintColumnBorder(paintInfo, LayoutRect(adjustedPaintOffset.x() + xPos, adjustedPaintOffset.y() + yPos, borderThickness, height())); + paintColumnBorder(paintInfo, pixelSnappedIntRect(LayoutRect(adjustedPaintOffset.x() + xPos, adjustedPaintOffset.y() + yPos, borderThickness, height()))); xPos += borderThickness; } child = child->nextSibling(); @@ -151,7 +151,7 @@ void RenderFrameSet::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset) } yPos += m_rows.m_sizes[r]; if (borderThickness && m_rows.m_allowBorder[r + 1]) { - paintRowBorder(paintInfo, LayoutRect(adjustedPaintOffset.x(), adjustedPaintOffset.y() + yPos, width(), borderThickness)); + paintRowBorder(paintInfo, pixelSnappedIntRect(LayoutRect(adjustedPaintOffset.x(), adjustedPaintOffset.y() + yPos, width(), borderThickness))); yPos += borderThickness; } } @@ -571,7 +571,7 @@ void RenderFrameSet::positionFramesWithFlattening() int height = m_rows.m_sizes[r]; for (int c = 0; c < cols; c++) { - IntRect oldFrameRect = child->frameRect(); + IntRect oldFrameRect = pixelSnappedIntRect(child->frameRect()); int width = m_cols.m_sizes[c]; @@ -619,7 +619,7 @@ void RenderFrameSet::positionFramesWithFlattening() xPos = 0; for (int c = 0; c < cols; c++) { // ensure the rows and columns are filled - IntRect oldRect = child->frameRect(); + IntRect oldRect = pixelSnappedIntRect(child->frameRect()); child->setLocation(IntPoint(xPos, yPos)); child->setHeight(m_rows.m_sizes[r]); @@ -802,11 +802,12 @@ bool RenderFrameSet::isChildAllowed(RenderObject* child, RenderStyle*) const CursorDirective RenderFrameSet::getCursor(const LayoutPoint& point, Cursor& cursor) const { - if (canResizeRow(point)) { + IntPoint roundedPoint = roundedIntPoint(point); + if (canResizeRow(roundedPoint)) { cursor = rowResizeCursor(); return SetCursor; } - if (canResizeColumn(point)) { + if (canResizeColumn(roundedPoint)) { cursor = columnResizeCursor(); return SetCursor; } diff --git a/Source/WebCore/rendering/RenderFrameSet.h b/Source/WebCore/rendering/RenderFrameSet.h index 373d0d02c..97be97428 100644 --- a/Source/WebCore/rendering/RenderFrameSet.h +++ b/Source/WebCore/rendering/RenderFrameSet.h @@ -68,8 +68,8 @@ public: bool isResizingRow() const; bool isResizingColumn() const; - bool canResizeRow(const LayoutPoint&) const; - bool canResizeColumn(const LayoutPoint&) const; + bool canResizeRow(const IntPoint&) const; + bool canResizeColumn(const IntPoint&) const; void notifyFrameEdgeInfoChanged(); @@ -119,8 +119,8 @@ private: void startResizing(GridAxis&, int position); void continueResizing(GridAxis&, int position); - void paintRowBorder(const PaintInfo&, const LayoutRect&); - void paintColumnBorder(const PaintInfo&, const LayoutRect&); + void paintRowBorder(const PaintInfo&, const IntRect&); + void paintColumnBorder(const PaintInfo&, const IntRect&); RenderObjectChildList m_children; diff --git a/Source/WebCore/rendering/RenderImage.cpp b/Source/WebCore/rendering/RenderImage.cpp index 9a0e576ad..de3e7e190 100644 --- a/Source/WebCore/rendering/RenderImage.cpp +++ b/Source/WebCore/rendering/RenderImage.cpp @@ -273,7 +273,7 @@ void RenderImage::paintReplaced(PaintInfo& paintInfo, const LayoutPoint& paintOf context->setStrokeStyle(SolidStroke); context->setStrokeColor(Color::lightGray, style()->colorSpace()); context->setFillColor(Color::transparent, style()->colorSpace()); - context->drawRect(LayoutRect(paintOffset.x() + leftBorder + leftPad, paintOffset.y() + topBorder + topPad, cWidth, cHeight)); + context->drawRect(pixelSnappedIntRect(LayoutRect(paintOffset.x() + leftBorder + leftPad, paintOffset.y() + topBorder + topPad, cWidth, cHeight))); bool errorPictureDrawn = false; LayoutSize imageOffset; @@ -299,7 +299,7 @@ void RenderImage::paintReplaced(PaintInfo& paintInfo, const LayoutPoint& paintOf if (centerY < 0) centerY = 0; imageOffset = LayoutSize(leftBorder + leftPad + centerX + 1, topBorder + topPad + centerY + 1); - context->drawImage(image.get(), style()->colorSpace(), IntRect(paintOffset + imageOffset, imageSize)); + context->drawImage(image.get(), style()->colorSpace(), IntRect(roundedIntPoint(paintOffset + imageOffset), imageSize)); errorPictureDrawn = true; } diff --git a/Source/WebCore/rendering/RenderInline.cpp b/Source/WebCore/rendering/RenderInline.cpp index a4d95c003..3be57ae0a 100644 --- a/Source/WebCore/rendering/RenderInline.cpp +++ b/Source/WebCore/rendering/RenderInline.cpp @@ -126,6 +126,33 @@ void RenderInline::updateBoxModelInfoFromStyle() setHasReflection(false); } +static bool hasRelPositionedInlineAncestor(RenderObject* p) +{ + while (p && p->isRenderInline()) { + if (p->isRelPositioned()) + return true; + p = p->parent(); + } + return false; +} + +static void updateStyleOfAnonymousBlockContinuations(RenderObject* block, const RenderStyle* newStyle, const RenderStyle* oldStyle) +{ + for (;block && block->isAnonymousBlock(); block = block->nextSibling()) { + if (!toRenderBlock(block)->isAnonymousBlockContinuation() || block->style()->position() == newStyle->position()) + continue; + // If we are no longer relatively positioned but our descendant block(s) still have a relatively positioned ancestor then + // their containing anonymous block should keep its relative positioning. + RenderInline* cont = toRenderBlock(block)->inlineElementContinuation(); + if (oldStyle->position() == RelativePosition && hasRelPositionedInlineAncestor(cont)) + continue; + RefPtr<RenderStyle> blockStyle = RenderStyle::createAnonymousStyle(block->style()); + blockStyle->setPosition(newStyle->position()); + blockStyle->setDisplay(BLOCK); + block->setStyle(blockStyle); + } +} + void RenderInline::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle) { RenderBoxModelObject::styleDidChange(diff, oldStyle); @@ -137,13 +164,24 @@ void RenderInline::styleDidChange(StyleDifference diff, const RenderStyle* oldSt // and after the block share the same style, but the block doesn't // need to pass its style on to anyone else. RenderStyle* newStyle = style(); - for (RenderInline* currCont = inlineElementContinuation(); currCont; currCont = currCont->inlineElementContinuation()) { + RenderInline* continuation = inlineElementContinuation(); + for (RenderInline* currCont = continuation; currCont; currCont = currCont->inlineElementContinuation()) { RenderBoxModelObject* nextCont = currCont->continuation(); currCont->setContinuation(0); currCont->setStyle(newStyle); currCont->setContinuation(nextCont); } + // If an inline's relative positioning has changed then any descendant blocks will need to change their relative positioning accordingly. + // Do this by updating the position of the descendant blocks' containing anonymous blocks - there may be more than one. + if (continuation && oldStyle && newStyle->position() != oldStyle->position() + && (newStyle->position() == RelativePosition || (oldStyle->position() == RelativePosition))) { + // If any descendant blocks exist then they will be in the next anonymous block and its siblings. + RenderObject* block = containingBlock()->nextSibling(); + ASSERT(block && block->isAnonymousBlock()); + updateStyleOfAnonymousBlockContinuations(block, newStyle, oldStyle); + } + if (!m_alwaysCreateLineBoxes) { bool alwaysCreateLineBoxes = hasSelfPaintingLayer() || hasBoxDecorations() || newStyle->hasPadding() || newStyle->hasMargin() || hasOutline(); if (oldStyle && alwaysCreateLineBoxes) { @@ -245,6 +283,11 @@ void RenderInline::addChildIgnoringContinuation(RenderObject* newChild, RenderOb // the children after |beforeChild| and put them in a clone of this object. RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyle(style()); newStyle->setDisplay(BLOCK); + + // If inside an inline affected by relative positioning the block needs to be affected by it too. + // Giving the block a layer like this allows it to collect the x/y offsets from inline parents later. + if (hasRelPositionedInlineAncestor(this)) + newStyle->setPosition(RelativePosition); RenderBlock* newBox = new (renderArena()) RenderBlock(document() /* anonymous box */); newBox->setStyle(newStyle.release()); @@ -988,7 +1031,7 @@ LayoutRect RenderInline::clippedOverflowRectForRepaint(RenderBoxModelObject* rep // layer's size instead. Even if the layer's size is wrong, the layer itself will repaint // anyway if its size does change. LayoutRect repaintRect(r); - repaintRect.move(-cb->layer()->scrolledContentOffset()); // For overflow:auto/scroll/hidden. + repaintRect.move(-cb->scrolledContentOffset()); // For overflow:auto/scroll/hidden. LayoutRect boxRect(LayoutPoint(), cb->layer()->size()); r = intersection(repaintRect, boxRect); @@ -1089,7 +1132,7 @@ void RenderInline::computeRectForRepaint(RenderBoxModelObject* repaintContainer, // o->height() is inaccurate if we're in the middle of a layout of |o|, so use the // layer's size instead. Even if the layer's size is wrong, the layer itself will repaint // anyway if its size does change. - topLeft -= containerBox->layer()->scrolledContentOffset(); // For overflow:auto/scroll/hidden. + topLeft -= containerBox->scrolledContentOffset(); // For overflow:auto/scroll/hidden. LayoutRect repaintRect(topLeft, rect.size()); LayoutRect boxRect(LayoutPoint(), containerBox->layer()->size()); @@ -1120,7 +1163,7 @@ LayoutSize RenderInline::offsetFromContainer(RenderObject* container, const Layo container->adjustForColumns(offset, point); if (container->hasOverflowClip()) - offset -= toRenderBox(container)->layer()->scrolledContentOffset(); + offset -= toRenderBox(container)->scrolledContentOffset(); return offset; } @@ -1403,24 +1446,24 @@ void RenderInline::paintOutlineForLine(GraphicsContext* graphicsContext, const L const Color outlineColor) { RenderStyle* styleToUse = style(); - LayoutUnit outlineWidth = styleToUse->outlineWidth(); + int outlineWidth = styleToUse->outlineWidth(); EBorderStyle outlineStyle = styleToUse->outlineStyle(); bool antialias = shouldAntialiasLines(graphicsContext); - LayoutUnit offset = style()->outlineOffset(); + int offset = style()->outlineOffset(); + + LayoutRect box(LayoutPoint(paintOffset.x() + thisline.x() - offset, paintOffset.y() + thisline.y() - offset), + LayoutSize(thisline.width() + offset, thisline.height() + offset)); - LayoutUnit top = paintOffset.y() + thisline.y() - offset; - LayoutUnit left = paintOffset.x() + thisline.x() - offset; - LayoutUnit bottom = paintOffset.y() + thisline.maxY() + offset; - LayoutUnit right = paintOffset.x() + thisline.maxX() + offset; + IntRect pixelSnappedBox = pixelSnappedIntRect(box); // left edge drawLineForBoxSide(graphicsContext, - left - outlineWidth, - top - (lastline.isEmpty() || thisline.x() < lastline.x() || (lastline.maxX() - 1) <= thisline.x() ? outlineWidth : 0), - left, - bottom + (nextline.isEmpty() || thisline.x() <= nextline.x() || (nextline.maxX() - 1) <= thisline.x() ? outlineWidth : 0), + pixelSnappedBox.x() - outlineWidth, + pixelSnappedBox.y() - (lastline.isEmpty() || thisline.x() < lastline.x() || (lastline.maxX() - 1) <= thisline.x() ? outlineWidth : 0), + pixelSnappedBox.x(), + pixelSnappedBox.maxY() + (nextline.isEmpty() || thisline.x() <= nextline.x() || (nextline.maxX() - 1) <= thisline.x() ? outlineWidth : 0), BSLeft, outlineColor, outlineStyle, (lastline.isEmpty() || thisline.x() < lastline.x() || (lastline.maxX() - 1) <= thisline.x() ? outlineWidth : -outlineWidth), @@ -1429,10 +1472,10 @@ void RenderInline::paintOutlineForLine(GraphicsContext* graphicsContext, const L // right edge drawLineForBoxSide(graphicsContext, - right, - top - (lastline.isEmpty() || lastline.maxX() < thisline.maxX() || (thisline.maxX() - 1) <= lastline.x() ? outlineWidth : 0), - right + outlineWidth, - bottom + (nextline.isEmpty() || nextline.maxX() <= thisline.maxX() || (thisline.maxX() - 1) <= nextline.x() ? outlineWidth : 0), + pixelSnappedBox.maxX(), + pixelSnappedBox.y() - (lastline.isEmpty() || lastline.maxX() < thisline.maxX() || (thisline.maxX() - 1) <= lastline.x() ? outlineWidth : 0), + pixelSnappedBox.maxX() + outlineWidth, + pixelSnappedBox.maxY() + (nextline.isEmpty() || nextline.maxX() <= thisline.maxX() || (thisline.maxX() - 1) <= nextline.x() ? outlineWidth : 0), BSRight, outlineColor, outlineStyle, (lastline.isEmpty() || lastline.maxX() < thisline.maxX() || (thisline.maxX() - 1) <= lastline.x() ? outlineWidth : -outlineWidth), @@ -1441,31 +1484,31 @@ void RenderInline::paintOutlineForLine(GraphicsContext* graphicsContext, const L // upper edge if (thisline.x() < lastline.x()) drawLineForBoxSide(graphicsContext, - left - outlineWidth, - top - outlineWidth, - min(right + outlineWidth, (lastline.isEmpty() ? 1000000 : paintOffset.x() + lastline.x())), - top, + pixelSnappedBox.x() - outlineWidth, + pixelSnappedBox.y() - outlineWidth, + min(pixelSnappedBox.maxX() + outlineWidth, (lastline.isEmpty() ? 1000000 : paintOffset.x() + lastline.x())), + pixelSnappedBox.y(), BSTop, outlineColor, outlineStyle, outlineWidth, - (!lastline.isEmpty() && paintOffset.x() + lastline.x() + 1 < right + outlineWidth) ? -outlineWidth : outlineWidth, + (!lastline.isEmpty() && paintOffset.x() + lastline.x() + 1 < pixelSnappedBox.maxX() + outlineWidth) ? -outlineWidth : outlineWidth, antialias); if (lastline.maxX() < thisline.maxX()) drawLineForBoxSide(graphicsContext, - max(lastline.isEmpty() ? -1000000 : paintOffset.x() + lastline.maxX(), left - outlineWidth), - top - outlineWidth, - right + outlineWidth, - top, + max(lastline.isEmpty() ? -1000000 : paintOffset.x() + lastline.maxX(), pixelSnappedBox.x() - outlineWidth), + pixelSnappedBox.y() - outlineWidth, + pixelSnappedBox.maxX() + outlineWidth, + pixelSnappedBox.y(), BSTop, outlineColor, outlineStyle, - (!lastline.isEmpty() && left - outlineWidth < paintOffset.x() + lastline.maxX()) ? -outlineWidth : outlineWidth, + (!lastline.isEmpty() && pixelSnappedBox.x() - outlineWidth < paintOffset.x() + lastline.maxX()) ? -outlineWidth : outlineWidth, outlineWidth, antialias); if (thisline.x() == thisline.maxX()) drawLineForBoxSide(graphicsContext, - left - outlineWidth, - top - outlineWidth, - right + outlineWidth, - top, + pixelSnappedBox.x() - outlineWidth, + pixelSnappedBox.y() - outlineWidth, + pixelSnappedBox.maxX() + outlineWidth, + pixelSnappedBox.y(), BSTop, outlineColor, outlineStyle, outlineWidth, outlineWidth, @@ -1474,31 +1517,31 @@ void RenderInline::paintOutlineForLine(GraphicsContext* graphicsContext, const L // lower edge if (thisline.x() < nextline.x()) drawLineForBoxSide(graphicsContext, - left - outlineWidth, - bottom, - min(right + outlineWidth, !nextline.isEmpty() ? paintOffset.x() + nextline.x() + 1 : 1000000), - bottom + outlineWidth, + pixelSnappedBox.x() - outlineWidth, + pixelSnappedBox.maxY(), + min(pixelSnappedBox.maxX() + outlineWidth, !nextline.isEmpty() ? paintOffset.x() + nextline.x() + 1 : 1000000), + pixelSnappedBox.maxY() + outlineWidth, BSBottom, outlineColor, outlineStyle, outlineWidth, - (!nextline.isEmpty() && paintOffset.x() + nextline.x() + 1 < right + outlineWidth) ? -outlineWidth : outlineWidth, + (!nextline.isEmpty() && paintOffset.x() + nextline.x() + 1 < pixelSnappedBox.maxX() + outlineWidth) ? -outlineWidth : outlineWidth, antialias); if (nextline.maxX() < thisline.maxX()) drawLineForBoxSide(graphicsContext, - max(!nextline.isEmpty() ? paintOffset.x() + nextline.maxX() : -1000000, left - outlineWidth), - bottom, - right + outlineWidth, - bottom + outlineWidth, + max(!nextline.isEmpty() ? paintOffset.x() + nextline.maxX() : -1000000, pixelSnappedBox.x() - outlineWidth), + pixelSnappedBox.maxY(), + pixelSnappedBox.maxX() + outlineWidth, + pixelSnappedBox.maxY() + outlineWidth, BSBottom, outlineColor, outlineStyle, - (!nextline.isEmpty() && left - outlineWidth < paintOffset.x() + nextline.maxX()) ? -outlineWidth : outlineWidth, + (!nextline.isEmpty() && pixelSnappedBox.x() - outlineWidth < paintOffset.x() + nextline.maxX()) ? -outlineWidth : outlineWidth, outlineWidth, antialias); if (thisline.x() == thisline.maxX()) drawLineForBoxSide(graphicsContext, - left - outlineWidth, - bottom, - right + outlineWidth, - bottom + outlineWidth, + pixelSnappedBox.x() - outlineWidth, + pixelSnappedBox.maxY(), + pixelSnappedBox.maxX() + outlineWidth, + pixelSnappedBox.maxY() + outlineWidth, BSBottom, outlineColor, outlineStyle, outlineWidth, outlineWidth, diff --git a/Source/WebCore/rendering/RenderLayer.cpp b/Source/WebCore/rendering/RenderLayer.cpp index ee6e8beea..a5b028b65 100644 --- a/Source/WebCore/rendering/RenderLayer.cpp +++ b/Source/WebCore/rendering/RenderLayer.cpp @@ -77,6 +77,7 @@ #include "Page.h" #include "PlatformMouseEvent.h" #include "RenderArena.h" +#include "RenderFlowThread.h" #include "RenderInline.h" #include "RenderMarquee.h" #include "RenderReplica.h" @@ -357,7 +358,7 @@ void RenderLayer::updateLayerPositions(LayoutPoint* offsetFromRoot, UpdateLayerP // as canUseConvertToLayerCoords may be true for an ancestor layer. convertToLayerCoords(root(), offset); } - positionOverflowControls(toSize(offset)); + positionOverflowControls(toSize(roundedIntPoint(offset))); updateVisibilityStatus(); @@ -375,8 +376,8 @@ void RenderLayer::updateLayerPositions(LayoutPoint* offsetFromRoot, UpdateLayerP ASSERT(!view->layoutStateEnabled()); RenderBoxModelObject* repaintContainer = renderer()->containerForRepaint(); - IntRect oldRepaintRect = m_repaintRect; - IntRect oldOutlineBox = m_outlineBox; + LayoutRect oldRepaintRect = m_repaintRect; + LayoutRect oldOutlineBox = m_outlineBox; computeRepaintRects(offsetFromRoot); // FIXME: Should ASSERT that value calculated for m_outlineBox using the cached offset is the same // as the value not using the cached offset, but we can't due to https://bugs.webkit.org/show_bug.cgi?id=37048 @@ -433,7 +434,7 @@ LayoutRect RenderLayer::repaintRectIncludingDescendants() const return repaintRect; } -void RenderLayer::computeRepaintRects(IntPoint* offsetFromRoot) +void RenderLayer::computeRepaintRects(LayoutPoint* offsetFromRoot) { ASSERT(!m_visibleContentStatusDirty); @@ -453,8 +454,9 @@ void RenderLayer::clearRepaintRects() void RenderLayer::updateLayerPositionsAfterScroll(UpdateLayerPositionsAfterScrollFlags flags) { - ASSERT(!m_visibleDescendantStatusDirty); - ASSERT(!m_visibleContentStatusDirty); + // FIXME: This shouldn't be needed, but there are some corner cases where + // these flags are still dirty. Update so that the check below is valid. + updateVisibilityStatus(); // If we have no visible content and no visible descendants, there is no point recomputing // our rectangles as they will be empty. If our visibility changes, we are expected to @@ -1191,22 +1193,16 @@ void RenderLayer::removeOnlyThisLayer() // Dirty the clip rects. clearClipRectsIncludingDescendants(); - // Remove us from the parent. - RenderLayer* parent = m_parent; RenderLayer* nextSib = nextSibling(); bool hasLayerOffset; const LayoutPoint offsetFromRootBeforeMove = computeOffsetFromRoot(hasLayerOffset); - parent->removeChild(this); - - if (reflection()) - removeChild(reflectionLayer()); // Now walk our kids and reattach them to our parent. RenderLayer* current = m_first; while (current) { RenderLayer* next = current->nextSibling(); removeChild(current); - parent->addChild(current, nextSib); + m_parent->addChild(current, nextSib); current->setRepaintStatus(NeedsFullRepaint); LayoutPoint offsetFromRoot = offsetFromRootBeforeMove; // updateLayerPositions depends on hasLayer() already being false for proper layout. @@ -1215,6 +1211,11 @@ void RenderLayer::removeOnlyThisLayer() current = next; } + // Remove us from the parent. + if (reflection()) + removeChild(reflectionLayer()); + m_parent->removeChild(this); + m_renderer->destroyLayer(); } @@ -1237,8 +1238,21 @@ void RenderLayer::insertOnlyThisLayer() clearClipRectsIncludingDescendants(); } -void -RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, LayoutPoint& location) const +void RenderLayer::convertToPixelSnappedLayerCoords(const RenderLayer* ancestorLayer, IntPoint& roundedLocation) const +{ + LayoutPoint location = roundedLocation; + convertToLayerCoords(ancestorLayer, location); + roundedLocation = roundedIntPoint(location); +} + +void RenderLayer::convertToPixelSnappedLayerCoords(const RenderLayer* ancestorLayer, IntRect& roundedRect) const +{ + LayoutRect rect = roundedRect; + convertToLayerCoords(ancestorLayer, rect); + roundedRect = pixelSnappedIntRect(rect); +} + +void RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, LayoutPoint& location) const { if (ancestorLayer == this) return; @@ -1325,8 +1339,7 @@ RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, LayoutPoint& location += toSize(m_topLeft); } -void -RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, LayoutRect& rect) const +void RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, LayoutRect& rect) const { LayoutPoint delta; convertToLayerCoords(ancestorLayer, delta); @@ -1578,7 +1591,7 @@ void RenderLayer::scrollRectToVisible(const LayoutRect& rect, const ScrollAlignm LayoutRect viewRect = frameView->visibleContentRect(); LayoutRect r = getRectToExpose(viewRect, rect, alignX, alignY); - frameView->setScrollPosition(r.location()); + frameView->setScrollPosition(roundedIntPoint(r.location())); // This is the outermost view of a web page, so after scrolling this view we // scroll its container by calling Page::scrollRectIntoView. @@ -1587,7 +1600,7 @@ void RenderLayer::scrollRectToVisible(const LayoutRect& rect, const ScrollAlignm // The canAutoscroll function in EventHandler also knows about this. if (Frame* frame = frameView->frame()) { if (Page* page = frame->page()) - page->chrome()->scrollRectIntoView(rect); + page->chrome()->scrollRectIntoView(pixelSnappedIntRect(rect)); } } } @@ -1725,29 +1738,29 @@ void RenderLayer::resize(const PlatformMouseEvent& evt, const LayoutSize& oldOff LayoutSize difference = (currentSize + newOffset - adjustedOldOffset).expandedTo(minimumSize) - currentSize; ASSERT(element->isStyledElement()); - StylePropertySet* styleDeclaration = static_cast<StyledElement*>(element)->ensureInlineStyleDecl(); + StyledElement* styledElement = static_cast<StyledElement*>(element); bool isBoxSizingBorder = renderer->style()->boxSizing() == BORDER_BOX; if (resize != RESIZE_VERTICAL && difference.width()) { if (element->isFormControlElement()) { // Make implicit margins from the theme explicit (see <http://bugs.webkit.org/show_bug.cgi?id=9547>). - styleDeclaration->setProperty(CSSPropertyMarginLeft, String::number(renderer->marginLeft() / zoomFactor) + "px", false); - styleDeclaration->setProperty(CSSPropertyMarginRight, String::number(renderer->marginRight() / zoomFactor) + "px", false); + styledElement->setInlineStyleProperty(CSSPropertyMarginLeft, String::number(renderer->marginLeft() / zoomFactor) + "px", false); + styledElement->setInlineStyleProperty(CSSPropertyMarginRight, String::number(renderer->marginRight() / zoomFactor) + "px", false); } - LayoutUnit baseWidth = renderer->width() - (isBoxSizingBorder ? 0 : renderer->borderAndPaddingWidth()); + LayoutUnit baseWidth = renderer->width() - (isBoxSizingBorder ? zeroLayoutUnit : renderer->borderAndPaddingWidth()); baseWidth = baseWidth / zoomFactor; - styleDeclaration->setProperty(CSSPropertyWidth, String::number(baseWidth + difference.width()) + "px", false); + styledElement->setInlineStyleProperty(CSSPropertyWidth, String::number(baseWidth + difference.width()) + "px", false); } if (resize != RESIZE_HORIZONTAL && difference.height()) { if (element->isFormControlElement()) { // Make implicit margins from the theme explicit (see <http://bugs.webkit.org/show_bug.cgi?id=9547>). - styleDeclaration->setProperty(CSSPropertyMarginTop, String::number(renderer->marginTop() / zoomFactor) + "px", false); - styleDeclaration->setProperty(CSSPropertyMarginBottom, String::number(renderer->marginBottom() / zoomFactor) + "px", false); + styledElement->setInlineStyleProperty(CSSPropertyMarginTop, String::number(renderer->marginTop() / zoomFactor) + "px", false); + styledElement->setInlineStyleProperty(CSSPropertyMarginBottom, String::number(renderer->marginBottom() / zoomFactor) + "px", false); } - LayoutUnit baseHeight = renderer->height() - (isBoxSizingBorder ? 0 : renderer->borderAndPaddingHeight()); + LayoutUnit baseHeight = renderer->height() - (isBoxSizingBorder ? zeroLayoutUnit : renderer->borderAndPaddingHeight()); baseHeight = baseHeight / zoomFactor; - styleDeclaration->setProperty(CSSPropertyHeight, String::number(baseHeight + difference.height()) + "px", false); + styledElement->setInlineStyleProperty(CSSPropertyHeight, String::number(baseHeight + difference.height()) + "px", false); } document->updateLayout(); @@ -1788,7 +1801,7 @@ IntPoint RenderLayer::minimumScrollPosition() const IntPoint RenderLayer::maximumScrollPosition() const { // FIXME: m_scrollSize may not be up-to-date if m_scrollDimensionsDirty is true. - return scrollOrigin() + m_scrollSize - visibleContentRect(true).size(); + return scrollOrigin() + roundedIntSize(m_scrollSize) - visibleContentRect(true).size(); } IntRect RenderLayer::visibleContentRect(bool includeScrollbars) const @@ -1850,7 +1863,7 @@ IntRect RenderLayer::scrollCornerRect() const bool hasVerticalBar = verticalScrollbar(); bool hasResizer = renderer()->style()->resize() != RESIZE_NONE; if ((hasHorizontalBar && hasVerticalBar) || (hasResizer && (hasHorizontalBar || hasVerticalBar))) - return cornerRect(this, renderBox()->borderBoxRect()); + return cornerRect(this, pixelSnappedIntRect(renderBox()->borderBoxRect())); return IntRect(); } @@ -1869,7 +1882,7 @@ IntRect RenderLayer::scrollCornerAndResizerRect() const return IntRect(); IntRect scrollCornerAndResizer = scrollCornerRect(); if (scrollCornerAndResizer.isEmpty()) - scrollCornerAndResizer = resizerCornerRect(this, box->borderBoxRect()); + scrollCornerAndResizer = resizerCornerRect(this, pixelSnappedIntRect(box->borderBoxRect())); return scrollCornerAndResizer; } @@ -2131,12 +2144,12 @@ int RenderLayer::horizontalScrollbarHeight(OverlayScrollbarSizeRelevancy relevan return m_hBar->height(); } -LayoutSize RenderLayer::offsetFromResizeCorner(const LayoutPoint& absolutePoint) const +IntSize RenderLayer::offsetFromResizeCorner(const IntPoint& absolutePoint) const { // Currently the resize corner is always the bottom right corner // FIXME: This assumes the location is 0, 0. Is this guaranteed to always be the case? - LayoutPoint bottomRight = toPoint(size()); - LayoutPoint localPoint = absoluteToContents(absolutePoint); + IntPoint bottomRight = toPoint(size()); + IntPoint localPoint = roundedIntPoint(absoluteToContents(absolutePoint)); return localPoint - bottomRight; } @@ -2145,7 +2158,7 @@ bool RenderLayer::hasOverflowControls() const return m_hBar || m_vBar || m_scrollCorner || renderer()->style()->resize() != RESIZE_NONE; } -void RenderLayer::positionOverflowControls(const LayoutSize& offsetFromLayer) +void RenderLayer::positionOverflowControls(const IntSize& offsetFromLayer) { if (!m_hBar && !m_vBar && (!renderer()->hasOverflowClip() || renderer()->style()->resize() == RESIZE_NONE)) return; @@ -2154,7 +2167,7 @@ void RenderLayer::positionOverflowControls(const LayoutSize& offsetFromLayer) if (!box) return; - const IntRect borderBox = box->borderBoxRect(); + const IntRect borderBox = pixelSnappedIntRect(box->borderBoxRect()); const IntRect& scrollCorner = scrollCornerRect(); IntRect absBounds(borderBox.location() + offsetFromLayer, borderBox.size()); if (m_vBar) @@ -2397,7 +2410,7 @@ void RenderLayer::updateScrollInfoAfterLayout() updateOverflowStatus(horizontalOverflow, verticalOverflow); } -void RenderLayer::paintOverflowControls(GraphicsContext* context, const LayoutPoint& paintOffset, const LayoutRect& damageRect, bool paintingOverlayControls) +void RenderLayer::paintOverflowControls(GraphicsContext* context, const IntPoint& paintOffset, const IntRect& damageRect, bool paintingOverlayControls) { // Don't do anything if we have no overflow. if (!renderer()->hasOverflowClip()) @@ -2421,7 +2434,7 @@ void RenderLayer::paintOverflowControls(GraphicsContext* context, const LayoutPo if (paintingOverlayControls && !hasOverlayScrollbars()) return; - LayoutPoint adjustedPaintOffset = paintOffset; + IntPoint adjustedPaintOffset = paintOffset; if (paintingOverlayControls) adjustedPaintOffset = m_cachedOverlayScrollbarOffset; @@ -2457,12 +2470,12 @@ void RenderLayer::paintOverflowControls(GraphicsContext* context, const LayoutPo paintResizer(context, adjustedPaintOffset, damageRect); } -void RenderLayer::paintScrollCorner(GraphicsContext* context, const LayoutPoint& paintOffset, const LayoutRect& damageRect) +void RenderLayer::paintScrollCorner(GraphicsContext* context, const IntPoint& paintOffset, const IntRect& damageRect) { RenderBox* box = renderBox(); ASSERT(box); - LayoutRect absRect = scrollCornerRect(); + IntRect absRect = scrollCornerRect(); absRect.moveBy(paintOffset); if (!absRect.intersects(damageRect)) return; @@ -2483,7 +2496,7 @@ void RenderLayer::paintScrollCorner(GraphicsContext* context, const LayoutPoint& context->fillRect(absRect, Color::white, box->style()->colorSpace()); } -void RenderLayer::drawPlatformResizerImage(GraphicsContext* context, LayoutRect resizerCornerRect) +void RenderLayer::drawPlatformResizerImage(GraphicsContext* context, IntRect resizerCornerRect) { float deviceScaleFactor = WebCore::deviceScaleFactor(renderer()->frame()); @@ -2504,7 +2517,7 @@ void RenderLayer::drawPlatformResizerImage(GraphicsContext* context, LayoutRect context->drawImage(resizeCornerImage.get(), renderer()->style()->colorSpace(), imageRect); } -void RenderLayer::paintResizer(GraphicsContext* context, const LayoutPoint& paintOffset, const LayoutRect& damageRect) +void RenderLayer::paintResizer(GraphicsContext* context, const IntPoint& paintOffset, const IntRect& damageRect) { if (renderer()->style()->resize() == RESIZE_NONE) return; @@ -2512,7 +2525,7 @@ void RenderLayer::paintResizer(GraphicsContext* context, const LayoutPoint& pain RenderBox* box = renderBox(); ASSERT(box); - LayoutRect absRect = resizerCornerRect(this, box->borderBoxRect()); + IntRect absRect = resizerCornerRect(this, pixelSnappedIntRect(box->borderBoxRect())); absRect.moveBy(paintOffset); if (!absRect.intersects(damageRect)) return; @@ -2534,8 +2547,8 @@ void RenderLayer::paintResizer(GraphicsContext* context, const LayoutPoint& pain if (!hasOverlayScrollbars() && (m_vBar || m_hBar)) { GraphicsContextStateSaver stateSaver(*context); context->clip(absRect); - LayoutRect largerCorner = absRect; - largerCorner.setSize(LayoutSize(largerCorner.width() + 1, largerCorner.height() + 1)); + IntRect largerCorner = absRect; + largerCorner.setSize(IntSize(largerCorner.width() + 1, largerCorner.height() + 1)); context->setStrokeColor(Color(makeRGB(217, 217, 217)), ColorSpaceDeviceRGB); context->setStrokeThickness(1.0f); context->setFillColor(Color::transparent, ColorSpaceDeviceRGB); @@ -2543,7 +2556,7 @@ void RenderLayer::paintResizer(GraphicsContext* context, const LayoutPoint& pain } } -bool RenderLayer::isPointInResizeControl(const LayoutPoint& absolutePoint) const +bool RenderLayer::isPointInResizeControl(const IntPoint& absolutePoint) const { if (!renderer()->hasOverflowClip() || renderer()->style()->resize() == RESIZE_NONE) return false; @@ -2551,13 +2564,13 @@ bool RenderLayer::isPointInResizeControl(const LayoutPoint& absolutePoint) const RenderBox* box = renderBox(); ASSERT(box); - LayoutPoint localPoint = absoluteToContents(absolutePoint); + IntPoint localPoint = roundedIntPoint(absoluteToContents(absolutePoint)); - LayoutRect localBounds(0, 0, box->width(), box->height()); + IntRect localBounds(0, 0, box->pixelSnappedWidth(), box->pixelSnappedHeight()); return resizerCornerRect(this, localBounds).contains(localPoint); } -bool RenderLayer::hitTestOverflowControls(HitTestResult& result, const LayoutPoint& localPoint) +bool RenderLayer::hitTestOverflowControls(HitTestResult& result, const IntPoint& localPoint) { if (!m_hBar && !m_vBar && (!renderer()->hasOverflowClip() || renderer()->style()->resize() == RESIZE_NONE)) return false; @@ -2567,7 +2580,7 @@ bool RenderLayer::hitTestOverflowControls(HitTestResult& result, const LayoutPoi IntRect resizeControlRect; if (renderer()->style()->resize() != RESIZE_NONE) { - resizeControlRect = resizerCornerRect(this, box->borderBoxRect()); + resizeControlRect = resizerCornerRect(this, pixelSnappedIntRect(box->borderBoxRect())); if (resizeControlRect.contains(localPoint)) return true; } @@ -2645,7 +2658,7 @@ void RenderLayer::clipToRect(RenderLayer* rootLayer, GraphicsContext* context, c if (clipRect.rect() == paintDirtyRect) return; context->save(); - context->clip(clipRect.rect()); + context->clip(pixelSnappedIntRect(clipRect.rect())); if (!clipRect.hasRadius()) return; @@ -2946,7 +2959,7 @@ void RenderLayer::paintLayerContents(RenderLayer* rootLayer, GraphicsContext* co if (isPaintingOverlayScrollbars) { clipToRect(rootLayer, context, paintDirtyRect, damageRect); - paintOverflowControls(context, paintOffset, damageRect.rect(), true); + paintOverflowControls(context, roundedIntPoint(paintOffset), pixelSnappedIntRect(damageRect.rect()), true); restoreClip(context, paintDirtyRect, damageRect); } @@ -3110,9 +3123,9 @@ bool RenderLayer::hitTest(const HitTestRequest& request, HitTestResult& result) { renderer()->document()->updateLayout(); - LayoutRect hitTestArea = renderer()->view()->documentRect(); + IntRect hitTestArea = renderer()->isRenderFlowThread() ? toRenderFlowThread(renderer())->borderBoxRect() : renderer()->view()->documentRect(); if (!request.ignoreClipping()) - hitTestArea.intersect(frameVisibleRect(renderer())); + hitTestArea.intersect(pixelSnappedIntRect(frameVisibleRect(renderer()))); RenderLayer* insideLayer = hitTestLayer(this, 0, request, result, hitTestArea, result.point(), false); if (!insideLayer) { @@ -3747,7 +3760,7 @@ void RenderLayer::calculateRects(const RenderLayer* rootLayer, RenderRegion* reg backgroundRect.intersect(layerBoundsWithVisualOverflow); } else { // Shift the bounds to be for our region only. - LayoutRect bounds = renderBox()->borderBoxRectInRegion(region); + LayoutRect bounds = pixelSnappedIntRect(renderBox()->borderBoxRectInRegion(region)); bounds.moveBy(offset); backgroundRect.intersect(bounds); } @@ -4269,7 +4282,7 @@ void RenderLayer::setBackingNeedsRepaintInRect(const LayoutRect& r) if (view) view->repaintViewRectangle(absRect); } else - backing()->setContentsNeedDisplayInRect(r); + backing()->setContentsNeedDisplayInRect(pixelSnappedIntRect(r)); } // Since we're only painting non-composited layers, we know that they all share the same repaintContainer. diff --git a/Source/WebCore/rendering/RenderLayer.h b/Source/WebCore/rendering/RenderLayer.h index bb4797bb2..4c5be0cdc 100644 --- a/Source/WebCore/rendering/RenderLayer.h +++ b/Source/WebCore/rendering/RenderLayer.h @@ -295,8 +295,6 @@ public: // Scrolling methods for layers that can scroll their overflow. void scrollByRecursively(LayoutUnit xDelta, LayoutUnit yDelta, ScrollOffsetClamping = ScrollOffsetUnclamped); - LayoutSize scrolledContentOffset() const { return scrollOffset() + m_scrollOverflow; } - int scrollXOffset() const { return m_scrollOffset.width() + scrollOrigin().x(); } int scrollYOffset() const { return m_scrollOffset.height() + scrollOrigin().y(); } IntSize scrollOffset() const { return IntSize(scrollXOffset(), scrollYOffset()); } @@ -327,13 +325,13 @@ public: int horizontalScrollbarHeight(OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize) const; bool hasOverflowControls() const; - bool isPointInResizeControl(const LayoutPoint& absolutePoint) const; - bool hitTestOverflowControls(HitTestResult&, const LayoutPoint& localPoint); - LayoutSize offsetFromResizeCorner(const LayoutPoint& absolutePoint) const; + bool isPointInResizeControl(const IntPoint& absolutePoint) const; + bool hitTestOverflowControls(HitTestResult&, const IntPoint& localPoint); + IntSize offsetFromResizeCorner(const IntPoint& absolutePoint) const; - void paintOverflowControls(GraphicsContext*, const LayoutPoint&, const LayoutRect& damageRect, bool paintingOverlayControls = false); - void paintScrollCorner(GraphicsContext*, const LayoutPoint&, const LayoutRect& damageRect); - void paintResizer(GraphicsContext*, const LayoutPoint&, const LayoutRect& damageRect); + void paintOverflowControls(GraphicsContext*, const IntPoint&, const IntRect& damageRect, bool paintingOverlayControls = false); + void paintScrollCorner(GraphicsContext*, const IntPoint&, const IntRect& damageRect); + void paintResizer(GraphicsContext*, const IntPoint&, const IntRect& damageRect); void updateScrollInfoAfterLayout(); @@ -425,6 +423,8 @@ public: RenderLayer* ancestorCompositingLayer() const { return enclosingCompositingLayer(false); } #endif + void convertToPixelSnappedLayerCoords(const RenderLayer* ancestorLayer, IntPoint& location) const; + void convertToPixelSnappedLayerCoords(const RenderLayer* ancestorLayer, IntRect&) const; void convertToLayerCoords(const RenderLayer* ancestorLayer, LayoutPoint& location) const; void convertToLayerCoords(const RenderLayer* ancestorLayer, LayoutRect&) const; @@ -524,6 +524,9 @@ public: #if ENABLE(CSS_FILTERS) virtual void filterNeedsRepaint(); + bool hasFilter() const { return renderer()->hasFilter(); } +#else + bool hasFilter() const { return false; } #endif // Overloaded new operator. Derived classes must override operator new @@ -565,7 +568,7 @@ public: private: void updateZOrderListsSlowCase(); - void computeRepaintRects(IntPoint* offsetFromRoot = 0); + void computeRepaintRects(LayoutPoint* offsetFromRoot = 0); void clearRepaintRects(); void clipToRect(RenderLayer* rootLayer, GraphicsContext*, const LayoutRect& paintDirtyRect, const ClipRect&, @@ -574,6 +577,9 @@ private: bool shouldRepaintAfterLayout() const; + friend IntSize RenderBox::scrolledContentOffset() const; + IntSize scrolledContentOffset() const { return scrollOffset() + m_scrollOverflow; } + // The normal operator new is disallowed on all render objects. void* operator new(size_t) throw(); @@ -710,11 +716,11 @@ private: // Convert a point in absolute coords into layer coords, taking transforms into account LayoutPoint absoluteToContents(const LayoutPoint&) const; - void positionOverflowControls(const LayoutSize&); + void positionOverflowControls(const IntSize&); void updateScrollCornerStyle(); void updateResizerStyle(); - void drawPlatformResizerImage(GraphicsContext*, LayoutRect resizerCornerRect); + void drawPlatformResizerImage(GraphicsContext*, IntRect resizerCornerRect); void updatePagination(); bool isPaginated() const { return m_isPaginated; } @@ -818,7 +824,7 @@ protected: LayoutSize m_scrollOverflow; // The width/height of our scrolled area. - IntSize m_scrollSize; + LayoutSize m_scrollSize; // For layers with overflow, we have a pair of scrollbars. RefPtr<Scrollbar> m_hBar; @@ -840,7 +846,7 @@ protected: const RenderLayer* m_clipRectsRoot; // Root layer used to compute clip rects. #endif - LayoutPoint m_cachedOverlayScrollbarOffset; + IntPoint m_cachedOverlayScrollbarOffset; RenderMarquee* m_marquee; // Used by layers with overflow:marquee diff --git a/Source/WebCore/rendering/RenderLayerBacking.cpp b/Source/WebCore/rendering/RenderLayerBacking.cpp index 9503a8275..f559970b4 100644 --- a/Source/WebCore/rendering/RenderLayerBacking.cpp +++ b/Source/WebCore/rendering/RenderLayerBacking.cpp @@ -70,7 +70,7 @@ using namespace HTMLNames; static bool hasBoxDecorations(const RenderStyle*); static bool hasBoxDecorationsOrBackground(const RenderObject*); static bool hasBoxDecorationsOrBackgroundImage(const RenderStyle*); -static LayoutRect clipBox(RenderBox* renderer); +static IntRect clipBox(RenderBox* renderer); static inline bool isAcceleratedCanvas(RenderObject* renderer) { @@ -101,7 +101,7 @@ RenderLayerBacking::RenderLayerBacking(RenderLayer* layer) if (page && frame && page->mainFrame() == frame) { m_isMainFrameRenderViewLayer = true; -#if ENABLE(THREADED_SCROLLING) +#if PLATFORM(MAC) // FIXME: It's a little weird that we base this decision on whether there's a scrolling coordinator or not. if (page->scrollingCoordinator()) m_usingTiledCacheLayer = true; @@ -229,7 +229,7 @@ static bool layerOrAncestorIsFullScreen(RenderLayer* layer) void RenderLayerBacking::updateCompositedBounds() { - LayoutRect layerBounds = compositor()->calculateCompositedBounds(m_owningLayer, m_owningLayer); + IntRect layerBounds = compositor()->calculateCompositedBounds(m_owningLayer, m_owningLayer); // Clip to the size of the document or enclosing overflow-scroll layer. // If this or an ancestor is transformed, we can't currently compute the correct rect to intersect with. @@ -254,7 +254,7 @@ void RenderLayerBacking::updateCompositedBounds() m_owningLayer->convertToLayerCoords(rootLayer, delta); clippingBounds.move(-delta.x(), -delta.y()); - layerBounds.intersect(clippingBounds); + layerBounds.intersect(pixelSnappedIntRect(clippingBounds)); } // If the element has a transform-origin that has fixed lengths, and the renderer has zero size, @@ -371,7 +371,7 @@ bool RenderLayerBacking::updateGraphicsLayerConfiguration() return layerConfigChanged; } -static LayoutRect clipBox(RenderBox* renderer) +static IntRect clipBox(RenderBox* renderer) { LayoutRect result = PaintInfo::infiniteRect(); if (renderer->hasOverflowClip()) @@ -380,7 +380,7 @@ static LayoutRect clipBox(RenderBox* renderer) if (renderer->hasClip()) result.intersect(renderer->clipRect(LayoutPoint(), 0)); // FIXME: Incorrect for CSS regions. - return result; + return pixelSnappedIntRect(result); } void RenderLayerBacking::updateGraphicsLayerGeometry() @@ -416,24 +416,24 @@ void RenderLayerBacking::updateGraphicsLayerGeometry() RenderLayer* compAncestor = m_owningLayer->ancestorCompositingLayer(); // We compute everything relative to the enclosing compositing layer. - LayoutRect ancestorCompositingBounds; + IntRect ancestorCompositingBounds; if (compAncestor) { ASSERT(compAncestor->backing()); - ancestorCompositingBounds = compAncestor->backing()->compositedBounds(); + ancestorCompositingBounds = pixelSnappedIntRect(compAncestor->backing()->compositedBounds()); } - LayoutRect localCompositingBounds = compositedBounds(); + IntRect localCompositingBounds = pixelSnappedIntRect(compositedBounds()); - LayoutRect relativeCompositingBounds(localCompositingBounds); - LayoutPoint delta; - m_owningLayer->convertToLayerCoords(compAncestor, delta); + IntRect relativeCompositingBounds(localCompositingBounds); + IntPoint delta; + m_owningLayer->convertToPixelSnappedLayerCoords(compAncestor, delta); relativeCompositingBounds.moveBy(delta); - LayoutPoint graphicsLayerParentLocation; + IntPoint graphicsLayerParentLocation; if (compAncestor && compAncestor->backing()->hasClippingLayer()) { // If the compositing ancestor has a layer to clip children, we parent in that, and therefore // position relative to it. - LayoutRect clippingBox = clipBox(toRenderBox(compAncestor->renderer())); + IntRect clippingBox = clipBox(toRenderBox(compAncestor->renderer())); graphicsLayerParentLocation = clippingBox.location(); } else if (compAncestor) graphicsLayerParentLocation = ancestorCompositingBounds.location(); @@ -444,7 +444,7 @@ void RenderLayerBacking::updateGraphicsLayerGeometry() // Call calculateRects to get the backgroundRect which is what is used to clip the contents of this // layer. Note that we call it with temporaryClipRects = true because normally when computing clip rects // for a compositing layer, rootLayer is the layer itself. - LayoutRect parentClipRect = m_owningLayer->backgroundClipRect(compAncestor, 0, true).rect(); // FIXME: Incorrect for CSS regions. + IntRect parentClipRect = pixelSnappedIntRect(m_owningLayer->backgroundClipRect(compAncestor, 0, true).rect()); // FIXME: Incorrect for CSS regions. ASSERT(parentClipRect != PaintInfo::infiniteRect()); m_ancestorClippingLayer->setPosition(FloatPoint() + (parentClipRect.location() - graphicsLayerParentLocation)); m_ancestorClippingLayer->setSize(parentClipRect.size()); @@ -457,7 +457,7 @@ void RenderLayerBacking::updateGraphicsLayerGeometry() } m_graphicsLayer->setPosition(FloatPoint() + (relativeCompositingBounds.location() - graphicsLayerParentLocation)); - m_graphicsLayer->setOffsetFromRenderer(localCompositingBounds.location() - LayoutPoint()); + m_graphicsLayer->setOffsetFromRenderer(localCompositingBounds.location() - IntPoint()); FloatSize oldSize = m_graphicsLayer->size(); FloatSize newSize = relativeCompositingBounds.size(); @@ -470,12 +470,12 @@ void RenderLayerBacking::updateGraphicsLayerGeometry() } // If we have a layer that clips children, position it. - LayoutRect clippingBox; + IntRect clippingBox; if (m_clippingLayer) { clippingBox = clipBox(toRenderBox(renderer())); m_clippingLayer->setPosition(FloatPoint() + (clippingBox.location() - localCompositingBounds.location())); m_clippingLayer->setSize(clippingBox.size()); - m_clippingLayer->setOffsetFromRenderer(clippingBox.location() - LayoutPoint()); + m_clippingLayer->setOffsetFromRenderer(clippingBox.location() - IntPoint()); } if (m_maskLayer) { @@ -488,10 +488,10 @@ void RenderLayerBacking::updateGraphicsLayerGeometry() } if (m_owningLayer->hasTransform()) { - const LayoutRect borderBox = toRenderBox(renderer())->borderBoxRect(); + const IntRect borderBox = pixelSnappedIntRect(toRenderBox(renderer())->borderBoxRect()); // Get layout bounds in the coords of compAncestor to match relativeCompositingBounds. - LayoutRect layerBounds = LayoutRect(delta, borderBox.size()); + IntRect layerBounds = IntRect(delta, borderBox.size()); // Update properties that depend on layer dimensions FloatPoint3D transformOrigin = computeTransformOrigin(borderBox); @@ -524,12 +524,12 @@ void RenderLayerBacking::updateGraphicsLayerGeometry() if (m_foregroundLayer) { FloatPoint foregroundPosition; FloatSize foregroundSize = newSize; - LayoutSize foregroundOffset = m_graphicsLayer->offsetFromRenderer(); + IntSize foregroundOffset = m_graphicsLayer->offsetFromRenderer(); if (m_clippingLayer) { // If we have a clipping layer (which clips descendants), then the foreground layer is a child of it, // so that it gets correctly sorted with children. In that case, position relative to the clipping layer. foregroundSize = FloatSize(clippingBox.size()); - foregroundOffset = clippingBox.location() - LayoutPoint(); + foregroundOffset = clippingBox.location() - IntPoint(); } m_foregroundLayer->setPosition(foregroundPosition); @@ -1002,7 +1002,7 @@ void RenderLayerBacking::updateImageContents() image->startAnimation(); } -FloatPoint3D RenderLayerBacking::computeTransformOrigin(const LayoutRect& borderBox) const +FloatPoint3D RenderLayerBacking::computeTransformOrigin(const IntRect& borderBox) const { RenderStyle* style = renderer()->style(); @@ -1014,7 +1014,7 @@ FloatPoint3D RenderLayerBacking::computeTransformOrigin(const LayoutRect& border return origin; } -FloatPoint RenderLayerBacking::computePerspectiveOrigin(const LayoutRect& borderBox) const +FloatPoint RenderLayerBacking::computePerspectiveOrigin(const IntRect& borderBox) const { RenderStyle* style = renderer()->style(); @@ -1029,26 +1029,26 @@ FloatPoint RenderLayerBacking::computePerspectiveOrigin(const LayoutRect& border } // Return the offset from the top-left of this compositing layer at which the renderer's contents are painted. -LayoutSize RenderLayerBacking::contentOffsetInCompostingLayer() const +IntSize RenderLayerBacking::contentOffsetInCompostingLayer() const { - return LayoutSize(-m_compositedBounds.x(), -m_compositedBounds.y()); + return IntSize(-m_compositedBounds.x(), -m_compositedBounds.y()); } -LayoutRect RenderLayerBacking::contentsBox() const +IntRect RenderLayerBacking::contentsBox() const { if (!renderer()->isBox()) - return LayoutRect(); + return IntRect(); - LayoutRect contentsRect; + IntRect contentsRect; #if ENABLE(VIDEO) if (renderer()->isVideo()) { RenderVideo* videoRenderer = toRenderVideo(renderer()); contentsRect = videoRenderer->videoBox(); } else #endif - contentsRect = toRenderBox(renderer())->contentBoxRect(); + contentsRect = pixelSnappedIntRect(toRenderBox(renderer())->contentBoxRect()); - LayoutSize contentOffset = contentOffsetInCompostingLayer(); + IntSize contentOffset = contentOffsetInCompostingLayer(); contentsRect.move(contentOffset); return contentsRect; } @@ -1077,29 +1077,29 @@ void RenderLayerBacking::setContentsNeedDisplay() } // r is in the coordinate space of the layer's render object -void RenderLayerBacking::setContentsNeedDisplayInRect(const LayoutRect& r) +void RenderLayerBacking::setContentsNeedDisplayInRect(const IntRect& r) { if (m_graphicsLayer && m_graphicsLayer->drawsContent()) { - LayoutRect layerDirtyRect = r; + IntRect layerDirtyRect = r; layerDirtyRect.move(-m_graphicsLayer->offsetFromRenderer()); m_graphicsLayer->setNeedsDisplayInRect(layerDirtyRect); } if (m_foregroundLayer && m_foregroundLayer->drawsContent()) { - LayoutRect layerDirtyRect = r; + IntRect layerDirtyRect = r; layerDirtyRect.move(-m_foregroundLayer->offsetFromRenderer()); m_foregroundLayer->setNeedsDisplayInRect(layerDirtyRect); } if (m_maskLayer && m_maskLayer->drawsContent()) { - LayoutRect layerDirtyRect = r; + IntRect layerDirtyRect = r; layerDirtyRect.move(-m_maskLayer->offsetFromRenderer()); m_maskLayer->setNeedsDisplayInRect(layerDirtyRect); } } void RenderLayerBacking::paintIntoLayer(RenderLayer* rootLayer, GraphicsContext* context, - const LayoutRect& paintDirtyRect, // In the coords of rootLayer. + const IntRect& paintDirtyRect, // In the coords of rootLayer. PaintBehavior paintBehavior, GraphicsLayerPaintingPhase paintingPhase, RenderObject* paintingRoot) { @@ -1124,28 +1124,28 @@ void RenderLayerBacking::paintIntoLayer(RenderLayer* rootLayer, GraphicsContext* ASSERT(!m_owningLayer->m_usedTransparency); } -static void paintScrollbar(Scrollbar* scrollbar, GraphicsContext& context, const LayoutRect& clip) +static void paintScrollbar(Scrollbar* scrollbar, GraphicsContext& context, const IntRect& clip) { if (!scrollbar) return; context.save(); - const LayoutRect& scrollbarRect = scrollbar->frameRect(); + const IntRect& scrollbarRect = scrollbar->frameRect(); context.translate(-scrollbarRect.x(), -scrollbarRect.y()); - LayoutRect transformedClip = clip; + IntRect transformedClip = clip; transformedClip.moveBy(scrollbarRect.location()); scrollbar->paint(&context, transformedClip); context.restore(); } // Up-call from compositing layer drawing callback. -void RenderLayerBacking::paintContents(const GraphicsLayer* graphicsLayer, GraphicsContext& context, GraphicsLayerPaintingPhase paintingPhase, const LayoutRect& clip) +void RenderLayerBacking::paintContents(const GraphicsLayer* graphicsLayer, GraphicsContext& context, GraphicsLayerPaintingPhase paintingPhase, const IntRect& clip) { if (graphicsLayer == m_graphicsLayer.get() || graphicsLayer == m_foregroundLayer.get() || graphicsLayer == m_maskLayer.get()) { - InspectorInstrumentationCookie cookie = InspectorInstrumentation::willPaint(m_owningLayer->renderer()->frame(), clip); + InspectorInstrumentationCookie cookie = InspectorInstrumentation::willPaint(m_owningLayer->renderer()->frame(), &context, clip); // The dirtyRect is in the coords of the painting root. - LayoutRect dirtyRect = compositedBounds(); + IntRect dirtyRect = compositedBounds(); dirtyRect.intersect(clip); // We have to use the same root as for hit testing, because both methods can compute and cache clipRects. @@ -1157,13 +1157,13 @@ void RenderLayerBacking::paintContents(const GraphicsLayer* graphicsLayer, Graph } else if (graphicsLayer == layerForVerticalScrollbar()) { paintScrollbar(m_owningLayer->verticalScrollbar(), context, clip); } else if (graphicsLayer == layerForScrollCorner()) { - const LayoutRect& scrollCornerAndResizer = m_owningLayer->scrollCornerAndResizerRect(); + const IntRect& scrollCornerAndResizer = m_owningLayer->scrollCornerAndResizerRect(); context.save(); context.translate(-scrollCornerAndResizer.x(), -scrollCornerAndResizer.y()); - LayoutRect transformedClip = clip; + IntRect transformedClip = clip; transformedClip.moveBy(scrollCornerAndResizer.location()); - m_owningLayer->paintScrollCorner(&context, LayoutPoint(), transformedClip); - m_owningLayer->paintResizer(&context, LayoutPoint(), transformedClip); + m_owningLayer->paintScrollCorner(&context, IntPoint(), transformedClip); + m_owningLayer->paintResizer(&context, IntPoint(), transformedClip); context.restore(); } } @@ -1197,12 +1197,20 @@ bool RenderLayerBacking::startAnimation(double timeOffset, const Animation* anim { bool hasOpacity = keyframes.containsProperty(CSSPropertyOpacity); bool hasTransform = renderer()->isBox() && keyframes.containsProperty(CSSPropertyWebkitTransform); - - if (!hasOpacity && !hasTransform) +#if ENABLE(CSS_FILTERS) + bool hasFilter = keyframes.containsProperty(CSSPropertyWebkitFilter); +#else + bool hasFilter = false; +#endif + + if (!hasOpacity && !hasTransform && !hasFilter) return false; KeyframeValueList transformVector(AnimatedPropertyWebkitTransform); KeyframeValueList opacityVector(AnimatedPropertyOpacity); +#if ENABLE(CSS_FILTERS) + KeyframeValueList filterVector(AnimatedPropertyWebkitFilter); +#endif size_t numKeyframes = keyframes.size(); for (size_t i = 0; i < numKeyframes; ++i) { @@ -1222,22 +1230,41 @@ bool RenderLayerBacking::startAnimation(double timeOffset, const Animation* anim if ((hasOpacity && isFirstOrLastKeyframe) || currentKeyframe.containsProperty(CSSPropertyOpacity)) opacityVector.insert(new FloatAnimationValue(key, keyframeStyle->opacity(), tf)); + +#if ENABLE(CSS_FILTERS) + if ((hasFilter && isFirstOrLastKeyframe) || currentKeyframe.containsProperty(CSSPropertyWebkitFilter)) + filterVector.insert(new FilterAnimationValue(key, &(keyframeStyle->filter()), tf)); +#endif } bool didAnimateTransform = false; bool didAnimateOpacity = false; +#if ENABLE(CSS_FILTERS) + bool didAnimateFilter = false; +#endif - if (hasTransform && m_graphicsLayer->addAnimation(transformVector, toRenderBox(renderer())->borderBoxRect().size(), anim, keyframes.animationName(), timeOffset)) { + if (hasTransform && m_graphicsLayer->addAnimation(transformVector, pixelSnappedIntRect(toRenderBox(renderer())->borderBoxRect()).size(), anim, keyframes.animationName(), timeOffset)) { didAnimateTransform = true; compositor()->didStartAcceleratedAnimation(CSSPropertyWebkitTransform); } - if (hasOpacity && m_graphicsLayer->addAnimation(opacityVector, LayoutSize(), anim, keyframes.animationName(), timeOffset)) { + if (hasOpacity && m_graphicsLayer->addAnimation(opacityVector, IntSize(), anim, keyframes.animationName(), timeOffset)) { didAnimateOpacity = true; compositor()->didStartAcceleratedAnimation(CSSPropertyOpacity); } +#if ENABLE(CSS_FILTERS) + if (hasFilter && m_graphicsLayer->addAnimation(filterVector, IntSize(), anim, keyframes.animationName(), timeOffset)) { + didAnimateFilter = true; + compositor()->didStartAcceleratedAnimation(CSSPropertyWebkitFilter); + } +#endif + +#if ENABLE(CSS_FILTERS) + return didAnimateTransform || didAnimateOpacity || didAnimateFilter; +#else return didAnimateTransform || didAnimateOpacity; +#endif } void RenderLayerBacking::animationPaused(double timeOffset, const String& animationName) @@ -1254,6 +1281,10 @@ bool RenderLayerBacking::startTransition(double timeOffset, int property, const { bool didAnimateOpacity = false; bool didAnimateTransform = false; +#if ENABLE(CSS_FILTERS) + bool didAnimateFilter = false; +#endif + ASSERT(property != cAnimateAll); if (property == (int)CSSPropertyOpacity) { @@ -1263,7 +1294,7 @@ bool RenderLayerBacking::startTransition(double timeOffset, int property, const opacityVector.insert(new FloatAnimationValue(0, compositingOpacity(fromStyle->opacity()))); opacityVector.insert(new FloatAnimationValue(1, compositingOpacity(toStyle->opacity()))); // The boxSize param is only used for transform animations (which can only run on RenderBoxes), so we pass an empty size here. - if (m_graphicsLayer->addAnimation(opacityVector, LayoutSize(), opacityAnim, GraphicsLayer::animationNameForTransition(AnimatedPropertyOpacity), timeOffset)) { + if (m_graphicsLayer->addAnimation(opacityVector, IntSize(), opacityAnim, GraphicsLayer::animationNameForTransition(AnimatedPropertyOpacity), timeOffset)) { // To ensure that the correct opacity is visible when the animation ends, also set the final opacity. updateLayerOpacity(toStyle); didAnimateOpacity = true; @@ -1277,21 +1308,46 @@ bool RenderLayerBacking::startTransition(double timeOffset, int property, const KeyframeValueList transformVector(AnimatedPropertyWebkitTransform); transformVector.insert(new TransformAnimationValue(0, &fromStyle->transform())); transformVector.insert(new TransformAnimationValue(1, &toStyle->transform())); - if (m_graphicsLayer->addAnimation(transformVector, toRenderBox(renderer())->borderBoxRect().size(), transformAnim, GraphicsLayer::animationNameForTransition(AnimatedPropertyWebkitTransform), timeOffset)) { - // To ensure that the correct transform is visible when the animation ends, also set the final opacity. + if (m_graphicsLayer->addAnimation(transformVector, pixelSnappedIntRect(toRenderBox(renderer())->borderBoxRect()).size(), transformAnim, GraphicsLayer::animationNameForTransition(AnimatedPropertyWebkitTransform), timeOffset)) { + // To ensure that the correct transform is visible when the animation ends, also set the final transform. updateLayerTransform(toStyle); didAnimateTransform = true; } } } +#if ENABLE(CSS_FILTERS) + if (property == (int)CSSPropertyWebkitFilter && m_owningLayer->hasFilter()) { + const Animation* filterAnim = toStyle->transitionForProperty(CSSPropertyWebkitFilter); + if (filterAnim && !filterAnim->isEmptyOrZeroDuration()) { + KeyframeValueList filterVector(AnimatedPropertyWebkitFilter); + filterVector.insert(new FilterAnimationValue(0, &fromStyle->filter())); + filterVector.insert(new FilterAnimationValue(1, &toStyle->filter())); + if (m_graphicsLayer->addAnimation(filterVector, IntSize(), filterAnim, GraphicsLayer::animationNameForTransition(AnimatedPropertyWebkitFilter), timeOffset)) { + // To ensure that the correct filter is visible when the animation ends, also set the final filter. + updateLayerFilters(toStyle); + didAnimateFilter = true; + } + } + } +#endif + if (didAnimateOpacity) compositor()->didStartAcceleratedAnimation(CSSPropertyOpacity); if (didAnimateTransform) compositor()->didStartAcceleratedAnimation(CSSPropertyWebkitTransform); +#if ENABLE(CSS_FILTERS) + if (didAnimateFilter) + compositor()->didStartAcceleratedAnimation(CSSPropertyWebkitFilter); +#endif + +#if ENABLE(CSS_FILTERS) + return didAnimateOpacity || didAnimateTransform || didAnimateFilter; +#else return didAnimateOpacity || didAnimateTransform; +#endif } void RenderLayerBacking::transitionPaused(double timeOffset, int property) @@ -1330,12 +1386,12 @@ void RenderLayerBacking::resumeAnimations() m_graphicsLayer->resumeAnimations(); } -LayoutRect RenderLayerBacking::compositedBounds() const +IntRect RenderLayerBacking::compositedBounds() const { return m_compositedBounds; } -void RenderLayerBacking::setCompositedBounds(const LayoutRect& bounds) +void RenderLayerBacking::setCompositedBounds(const IntRect& bounds) { m_compositedBounds = bounds; @@ -1353,6 +1409,13 @@ int RenderLayerBacking::graphicsLayerToCSSProperty(AnimatedPropertyID property) case AnimatedPropertyBackgroundColor: cssProperty = CSSPropertyBackgroundColor; break; + case AnimatedPropertyWebkitFilter: +#if ENABLE(CSS_FILTERS) + cssProperty = CSSPropertyWebkitFilter; +#else + ASSERT_NOT_REACHED(); +#endif + break; case AnimatedPropertyInvalid: ASSERT_NOT_REACHED(); } @@ -1368,6 +1431,10 @@ AnimatedPropertyID RenderLayerBacking::cssToGraphicsLayerProperty(int cssPropert return AnimatedPropertyOpacity; case CSSPropertyBackgroundColor: return AnimatedPropertyBackgroundColor; +#if ENABLE(CSS_FILTERS) + case CSSPropertyWebkitFilter: + return AnimatedPropertyWebkitFilter; +#endif // It's fine if we see other css properties here; they are just not accelerated. } return AnimatedPropertyInvalid; diff --git a/Source/WebCore/rendering/RenderLayerBacking.h b/Source/WebCore/rendering/RenderLayerBacking.h index b2d481c57..e1fafc0ac 100644 --- a/Source/WebCore/rendering/RenderLayerBacking.h +++ b/Source/WebCore/rendering/RenderLayerBacking.h @@ -99,7 +99,7 @@ public: void setContentsNeedDisplay(); // r is in the coordinate space of the layer's render object - void setContentsNeedDisplayInRect(const LayoutRect&); + void setContentsNeedDisplayInRect(const IntRect&); // Notification from the renderer that its content changed. void contentChanged(RenderLayer::ContentChangeType); @@ -116,8 +116,8 @@ public: void suspendAnimations(double time = 0); void resumeAnimations(); - LayoutRect compositedBounds() const; - void setCompositedBounds(const LayoutRect&); + IntRect compositedBounds() const; + void setCompositedBounds(const IntRect&); void updateCompositedBounds(); void updateAfterWidgetResize(); @@ -127,7 +127,7 @@ public: virtual void notifyAnimationStarted(const GraphicsLayer*, double startTime); virtual void notifySyncRequired(const GraphicsLayer*); - virtual void paintContents(const GraphicsLayer*, GraphicsContext&, GraphicsLayerPaintingPhase, const LayoutRect& clip); + virtual void paintContents(const GraphicsLayer*, GraphicsContext&, GraphicsLayerPaintingPhase, const IntRect& clip); virtual float deviceScaleFactor() const; virtual float pageScaleFactor() const; @@ -136,7 +136,7 @@ public: virtual bool showDebugBorders(const GraphicsLayer*) const; virtual bool showRepaintCounter(const GraphicsLayer*) const; - LayoutRect contentsBox() const; + IntRect contentsBox() const; // For informative purposes only. CompositingLayerType compositingLayerType() const; @@ -169,11 +169,11 @@ private: GraphicsLayerPaintingPhase paintingPhaseForPrimaryLayer() const; - LayoutSize contentOffsetInCompostingLayer() const; + IntSize contentOffsetInCompostingLayer() const; // Result is transform origin in pixels. - FloatPoint3D computeTransformOrigin(const LayoutRect& borderBox) const; + FloatPoint3D computeTransformOrigin(const IntRect& borderBox) const; // Result is perspective origin in pixels. - FloatPoint computePerspectiveOrigin(const LayoutRect& borderBox) const; + FloatPoint computePerspectiveOrigin(const IntRect& borderBox) const; void updateLayerOpacity(const RenderStyle*); void updateLayerTransform(const RenderStyle*); @@ -200,7 +200,7 @@ private: bool containsNonEmptyRenderers() const; bool hasVisibleNonCompositingDescendantLayers() const; - void paintIntoLayer(RenderLayer* rootLayer, GraphicsContext*, const LayoutRect& paintDirtyRect, PaintBehavior, GraphicsLayerPaintingPhase, RenderObject* paintingRoot); + void paintIntoLayer(RenderLayer* rootLayer, GraphicsContext*, const IntRect& paintDirtyRect, PaintBehavior, GraphicsLayerPaintingPhase, RenderObject* paintingRoot); static int graphicsLayerToCSSProperty(AnimatedPropertyID); static AnimatedPropertyID cssToGraphicsLayerProperty(int); @@ -221,7 +221,7 @@ private: OwnPtr<GraphicsLayer> m_layerForVerticalScrollbar; OwnPtr<GraphicsLayer> m_layerForScrollCorner; - LayoutRect m_compositedBounds; + IntRect m_compositedBounds; bool m_artificiallyInflatedBounds; // bounds had to be made non-zero to make transform-origin work bool m_isMainFrameRenderViewLayer; diff --git a/Source/WebCore/rendering/RenderLayerCompositor.cpp b/Source/WebCore/rendering/RenderLayerCompositor.cpp index 5c0ab779f..75a280c95 100644 --- a/Source/WebCore/rendering/RenderLayerCompositor.cpp +++ b/Source/WebCore/rendering/RenderLayerCompositor.cpp @@ -51,16 +51,13 @@ #include "RenderVideo.h" #include "RenderView.h" #include "ScrollbarTheme.h" +#include "ScrollingCoordinator.h" #include "Settings.h" #if ENABLE(PLUGIN_PROXY_FOR_VIDEO) #include "HTMLMediaElement.h" #endif -#if ENABLE(THREADED_SCROLLING) -#include "ScrollingCoordinator.h" -#endif - #if PROFILE_LAYER_REBUILD #include <wtf/CurrentTime.h> #endif @@ -456,10 +453,10 @@ void RenderLayerCompositor::repaintOnCompositingChange(RenderLayer* layer) // The bounds of the GraphicsLayer created for a compositing layer is the union of the bounds of all the descendant // RenderLayers that are rendered by the composited RenderLayer. -LayoutRect RenderLayerCompositor::calculateCompositedBounds(const RenderLayer* layer, const RenderLayer* ancestorLayer) +IntRect RenderLayerCompositor::calculateCompositedBounds(const RenderLayer* layer, const RenderLayer* ancestorLayer) { if (!canBeComposited(layer)) - return LayoutRect(); + return IntRect(); LayoutRect boundingBoxRect = layer->localBoundingBox(); if (layer->renderer()->isRoot()) { @@ -467,8 +464,8 @@ LayoutRect RenderLayerCompositor::calculateCompositedBounds(const RenderLayer* l // then it has to be big enough to cover the viewport in order to display the background. This is akin // to the code in RenderBox::paintRootBoxFillLayers(). if (m_renderView->frameView()) { - int rw = m_renderView->frameView()->contentsWidth(); - int rh = m_renderView->frameView()->contentsHeight(); + LayoutUnit rw = m_renderView->frameView()->contentsWidth(); + LayoutUnit rh = m_renderView->frameView()->contentsHeight(); boundingBoxRect.setWidth(max(boundingBoxRect.width(), rw - boundingBoxRect.x())); boundingBoxRect.setHeight(max(boundingBoxRect.height(), rh - boundingBoxRect.y())); @@ -481,7 +478,7 @@ LayoutRect RenderLayerCompositor::calculateCompositedBounds(const RenderLayer* l LayoutPoint ancestorRelOffset; layer->convertToLayerCoords(ancestorLayer, ancestorRelOffset); boundingBoxRect.moveBy(ancestorRelOffset); - return boundingBoxRect; + return pixelSnappedIntRect(boundingBoxRect); } if (RenderLayer* reflection = layer->reflectionLayer()) { @@ -536,7 +533,7 @@ LayoutRect RenderLayerCompositor::calculateCompositedBounds(const RenderLayer* l layer->convertToLayerCoords(ancestorLayer, ancestorRelOffset); unionBounds.moveBy(ancestorRelOffset); - return unionBounds; + return pixelSnappedIntRect(unionBounds); } void RenderLayerCompositor::layerWasAdded(RenderLayer* /*parent*/, RenderLayer* /*child*/) @@ -582,7 +579,7 @@ RenderLayer* RenderLayerCompositor::enclosingNonStackingClippingLayer(const Rend return 0; } -void RenderLayerCompositor::addToOverlapMap(OverlapMap& overlapMap, RenderLayer* layer, LayoutRect& layerBounds, bool& boundsComputed) +void RenderLayerCompositor::addToOverlapMap(OverlapMap& overlapMap, RenderLayer* layer, IntRect& layerBounds, bool& boundsComputed) { if (layer->isRootLayer()) return; @@ -591,11 +588,11 @@ void RenderLayerCompositor::addToOverlapMap(OverlapMap& overlapMap, RenderLayer* layerBounds = layer->renderer()->localToAbsoluteQuad(FloatRect(layer->localBoundingBox())).enclosingBoundingBox(); // Empty rects never intersect, but we need them to for the purposes of overlap testing. if (layerBounds.isEmpty()) - layerBounds.setSize(LayoutSize(1, 1)); + layerBounds.setSize(IntSize(1, 1)); boundsComputed = true; } - LayoutRect clipRect = layer->backgroundClipRect(rootRenderLayer(), 0, true).rect(); // FIXME: Incorrect for CSS regions. + IntRect clipRect = pixelSnappedIntRect(layer->backgroundClipRect(rootRenderLayer(), 0, true).rect()); // FIXME: Incorrect for CSS regions. clipRect.scale(pageScaleFactor()); clipRect.intersect(layerBounds); overlapMap.add(layer, clipRect); @@ -606,7 +603,7 @@ void RenderLayerCompositor::addToOverlapMapRecursive(OverlapMap& overlapMap, Ren if (!canBeComposited(layer) || overlapMap.contains(layer)) return; - LayoutRect bounds; + IntRect bounds; bool haveComputedBounds = false; addToOverlapMap(overlapMap, layer, bounds, haveComputedBounds); @@ -640,11 +637,11 @@ void RenderLayerCompositor::addToOverlapMapRecursive(OverlapMap& overlapMap, Ren } } -bool RenderLayerCompositor::overlapsCompositedLayers(OverlapMap& overlapMap, const LayoutRect& layerBounds) +bool RenderLayerCompositor::overlapsCompositedLayers(OverlapMap& overlapMap, const IntRect& layerBounds) { RenderLayerCompositor::OverlapMap::const_iterator end = overlapMap.end(); for (RenderLayerCompositor::OverlapMap::const_iterator it = overlapMap.begin(); it != end; ++it) { - const LayoutRect& bounds = it->second; + const IntRect& bounds = it->second; if (layerBounds.intersects(bounds)) return true; } @@ -673,13 +670,13 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O bool mustOverlapCompositedLayers = compositingState.m_subtreeIsCompositing; bool haveComputedBounds = false; - LayoutRect absBounds; + IntRect absBounds; if (overlapMap && !overlapMap->isEmpty()) { // If we're testing for overlap, we only need to composite if we overlap something that is already composited. absBounds = layer->renderer()->localToAbsoluteQuad(FloatRect(layer->localBoundingBox())).enclosingBoundingBox(); // Empty rects never intersect, but we need them to for the purposes of overlap testing. if (absBounds.isEmpty()) - absBounds.setSize(LayoutSize(1, 1)); + absBounds.setSize(IntSize(1, 1)); haveComputedBounds = true; mustOverlapCompositedLayers = overlapsCompositedLayers(*overlapMap, absBounds); } @@ -953,7 +950,7 @@ void RenderLayerCompositor::rebuildCompositingLayerTree(RenderLayer* layer, Vect } } -void RenderLayerCompositor::frameViewDidChangeLocation(const LayoutPoint& contentsOffset) +void RenderLayerCompositor::frameViewDidChangeLocation(const IntPoint& contentsOffset) { if (m_overflowControlsHostLayer) m_overflowControlsHostLayer->setPosition(contentsOffset); @@ -978,13 +975,22 @@ void RenderLayerCompositor::frameViewDidChangeSize() void RenderLayerCompositor::frameViewDidScroll() { FrameView* frameView = m_renderView->frameView(); - LayoutPoint scrollPosition = frameView->scrollPosition(); + IntPoint scrollPosition = frameView->scrollPosition(); if (RenderLayerBacking* backing = rootRenderLayer()->backing()) backing->graphicsLayer()->visibleRectChanged(); - if (m_scrollLayer) - m_scrollLayer->setPosition(FloatPoint(-scrollPosition.x(), -scrollPosition.y())); + if (!m_scrollLayer) + return; + + // If there's a scrolling coordinator that manages scrolling for this frame view, + // it will also manage updating the scroll layer position. + if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) { + if (scrollingCoordinator->coordinatesScrollingForFrameView(frameView)) + return; + } + + m_scrollLayer->setPosition(FloatPoint(-scrollPosition.x(), -scrollPosition.y())); } String RenderLayerCompositor::layerTreeAsText(bool showDebugInfo) @@ -1126,12 +1132,12 @@ void RenderLayerCompositor::updateCompositingDescendantGeometry(RenderLayer* com } -void RenderLayerCompositor::repaintCompositedLayersAbsoluteRect(const LayoutRect& absRect) +void RenderLayerCompositor::repaintCompositedLayersAbsoluteRect(const IntRect& absRect) { recursiveRepaintLayerRect(rootRenderLayer(), absRect); } -void RenderLayerCompositor::recursiveRepaintLayerRect(RenderLayer* layer, const LayoutRect& rect) +void RenderLayerCompositor::recursiveRepaintLayerRect(RenderLayer* layer, const IntRect& rect) { // FIXME: This method does not work correctly with transforms. if (layer->isComposited()) @@ -1142,8 +1148,8 @@ void RenderLayerCompositor::recursiveRepaintLayerRect(RenderLayer* layer, const size_t listSize = negZOrderList->size(); for (size_t i = 0; i < listSize; ++i) { RenderLayer* curLayer = negZOrderList->at(i); - LayoutRect childRect(rect); - curLayer->convertToLayerCoords(layer, childRect); + IntRect childRect(rect); + curLayer->convertToPixelSnappedLayerCoords(layer, childRect); recursiveRepaintLayerRect(curLayer, childRect); } } @@ -1152,8 +1158,8 @@ void RenderLayerCompositor::recursiveRepaintLayerRect(RenderLayer* layer, const size_t listSize = posZOrderList->size(); for (size_t i = 0; i < listSize; ++i) { RenderLayer* curLayer = posZOrderList->at(i); - LayoutRect childRect(rect); - curLayer->convertToLayerCoords(layer, childRect); + IntRect childRect(rect); + curLayer->convertToPixelSnappedLayerCoords(layer, childRect); recursiveRepaintLayerRect(curLayer, childRect); } } @@ -1162,8 +1168,8 @@ void RenderLayerCompositor::recursiveRepaintLayerRect(RenderLayer* layer, const size_t listSize = normalFlowList->size(); for (size_t i = 0; i < listSize; ++i) { RenderLayer* curLayer = normalFlowList->at(i); - LayoutRect childRect(rect); - curLayer->convertToLayerCoords(layer, childRect); + IntRect childRect(rect); + curLayer->convertToPixelSnappedLayerCoords(layer, childRect); recursiveRepaintLayerRect(curLayer, childRect); } } @@ -1223,7 +1229,7 @@ void RenderLayerCompositor::clearBackingForAllLayers() void RenderLayerCompositor::updateRootLayerPosition() { if (m_rootContentLayer) { - const LayoutRect& documentRect = m_renderView->documentRect(); + const IntRect& documentRect = m_renderView->documentRect(); m_rootContentLayer->setSize(documentRect.size()); m_rootContentLayer->setPosition(documentRect.location()); } @@ -1463,7 +1469,7 @@ bool RenderLayerCompositor::requiresCompositingForPlugin(RenderObject* renderer) return pluginRenderer->hasLayer() && pluginRenderer->layer()->isComposited(); // Don't go into compositing mode if height or width are zero, or size is 1x1. - LayoutRect contentBox = pluginRenderer->contentBoxRect(); + IntRect contentBox = pixelSnappedIntRect(pluginRenderer->contentBoxRect()); return contentBox.height() * contentBox.width() > 1; } @@ -1488,7 +1494,7 @@ bool RenderLayerCompositor::requiresCompositingForFrame(RenderObject* renderer) return frameRenderer->hasLayer() && frameRenderer->layer()->isComposited(); // Don't go into compositing mode if height or width are zero. - LayoutRect contentBox = frameRenderer->contentBoxRect(); + IntRect contentBox = pixelSnappedIntRect(frameRenderer->contentBoxRect()); return contentBox.height() * contentBox.width() > 0; } @@ -1556,6 +1562,11 @@ bool RenderLayerCompositor::requiresCompositingForPosition(RenderObject* rendere if (container != m_renderView) return false; + // Fixed position elements that are invisible in the current view don't get their own layer. + FrameView* frameView = m_renderView->frameView(); + if (frameView && !layer->absoluteBoundingBox().intersects(LayoutRect(frameView->scrollXForFixedPosition(), frameView->scrollYForFixedPosition(), frameView->layoutWidth(), frameView->layoutHeight()))) + return false; + return true; } @@ -1592,31 +1603,31 @@ bool RenderLayerCompositor::requiresScrollLayer(RootLayerAttachment attachment) || attachment == RootLayerAttachedViaEnclosingFrame; // a composited frame on Mac } -static void paintScrollbar(Scrollbar* scrollbar, GraphicsContext& context, const LayoutRect& clip) +static void paintScrollbar(Scrollbar* scrollbar, GraphicsContext& context, const IntRect& clip) { if (!scrollbar) return; context.save(); - const LayoutRect& scrollbarRect = scrollbar->frameRect(); + const IntRect& scrollbarRect = scrollbar->frameRect(); context.translate(-scrollbarRect.x(), -scrollbarRect.y()); - LayoutRect transformedClip = clip; + IntRect transformedClip = clip; transformedClip.moveBy(scrollbarRect.location()); scrollbar->paint(&context, transformedClip); context.restore(); } -void RenderLayerCompositor::paintContents(const GraphicsLayer* graphicsLayer, GraphicsContext& context, GraphicsLayerPaintingPhase, const LayoutRect& clip) +void RenderLayerCompositor::paintContents(const GraphicsLayer* graphicsLayer, GraphicsContext& context, GraphicsLayerPaintingPhase, const IntRect& clip) { if (graphicsLayer == layerForHorizontalScrollbar()) paintScrollbar(m_renderView->frameView()->horizontalScrollbar(), context, clip); else if (graphicsLayer == layerForVerticalScrollbar()) paintScrollbar(m_renderView->frameView()->verticalScrollbar(), context, clip); else if (graphicsLayer == layerForScrollCorner()) { - const LayoutRect& scrollCorner = m_renderView->frameView()->scrollCornerRect(); + const IntRect& scrollCorner = m_renderView->frameView()->scrollCornerRect(); context.save(); context.translate(-scrollCorner.x(), -scrollCorner.y()); - LayoutRect transformedClip = clip; + IntRect transformedClip = clip; transformedClip.moveBy(scrollCorner.location()); m_renderView->frameView()->paintScrollCorner(&context, transformedClip); context.restore(); @@ -1628,6 +1639,23 @@ void RenderLayerCompositor::paintContents(const GraphicsLayer* graphicsLayer, Gr } } +void RenderLayerCompositor::documentBackgroundColorDidChange() +{ + RenderLayerBacking* backing = rootRenderLayer()->backing(); + if (!backing) + return; + + GraphicsLayer* graphicsLayer = backing->graphicsLayer(); + if (!graphicsLayer->client()->shouldUseTileCache(graphicsLayer)) + return; + + Color backgroundColor = m_renderView->frameView()->documentBackgroundColor(); + if (!backgroundColor.isValid() || backgroundColor.hasAlpha()) + backgroundColor = Color::white; + + graphicsLayer->setBackgroundColor(backgroundColor); +} + bool RenderLayerCompositor::showDebugBorders(const GraphicsLayer* layer) const { if (layer == m_layerForHorizontalScrollbar || layer == m_layerForVerticalScrollbar || layer == m_layerForScrollCorner) @@ -1682,12 +1710,11 @@ static bool shouldCompositeOverflowControls(FrameView* view) if (view->platformWidget()) return false; -#if ENABLE(THREADED_SCROLLING) if (Page* page = view->frame()->page()) { if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator()) - return scrollingCoordinator->coordinatesScrollingForFrameView(view); + if (scrollingCoordinator->coordinatesScrollingForFrameView(view)) + return true; } -#endif #if !PLATFORM(CHROMIUM) if (!view->hasOverlayScrollbars()) @@ -1722,10 +1749,8 @@ bool RenderLayerCompositor::requiresOverhangAreasLayer() const return false; // We do want a layer if we have a scrolling coordinator. -#if ENABLE(THREADED_SCROLLING) if (scrollingCoordinator()) return true; -#endif // Chromium always wants a layer. #if PLATFORM(CHROMIUM) @@ -1741,7 +1766,7 @@ bool RenderLayerCompositor::requiresContentShadowLayer() const if (m_renderView->document()->ownerElement()) return false; -#if PLATFORM(MAC) && ENABLE(THREADED_SCROLLING) +#if PLATFORM(MAC) // On Mac, we want a content shadow layer if we have a scrolling coordinator. if (scrollingCoordinator()) return true; @@ -1800,19 +1825,15 @@ void RenderLayerCompositor::updateOverflowControlsLayers() #endif m_overflowControlsHostLayer->addChild(m_layerForHorizontalScrollbar.get()); -#if ENABLE(THREADED_SCROLLING) if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) scrollingCoordinator->frameViewHorizontalScrollbarLayerDidChange(m_renderView->frameView(), m_layerForHorizontalScrollbar.get()); -#endif } } else if (m_layerForHorizontalScrollbar) { m_layerForHorizontalScrollbar->removeFromParent(); m_layerForHorizontalScrollbar = nullptr; -#if ENABLE(THREADED_SCROLLING) if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) scrollingCoordinator->frameViewHorizontalScrollbarLayerDidChange(m_renderView->frameView(), 0); -#endif } if (requiresVerticalScrollbarLayer()) { @@ -1823,19 +1844,15 @@ void RenderLayerCompositor::updateOverflowControlsLayers() #endif m_overflowControlsHostLayer->addChild(m_layerForVerticalScrollbar.get()); -#if ENABLE(THREADED_SCROLLING) if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) scrollingCoordinator->frameViewVerticalScrollbarLayerDidChange(m_renderView->frameView(), m_layerForVerticalScrollbar.get()); -#endif } } else if (m_layerForVerticalScrollbar) { m_layerForVerticalScrollbar->removeFromParent(); m_layerForVerticalScrollbar = nullptr; -#if ENABLE(THREADED_SCROLLING) if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) scrollingCoordinator->frameViewVerticalScrollbarLayerDidChange(m_renderView->frameView(), 0); -#endif } if (requiresScrollCornerLayer()) { @@ -1865,7 +1882,8 @@ void RenderLayerCompositor::ensureRootLayer() #ifndef NDEBUG m_rootContentLayer->setName("content root"); #endif - m_rootContentLayer->setSize(FloatSize(m_renderView->maxXLayoutOverflow(), m_renderView->maxYLayoutOverflow())); + IntRect overflowRect = m_renderView->pixelSnappedLayoutOverflowRect(); + m_rootContentLayer->setSize(FloatSize(overflowRect.maxX(), overflowRect.maxY())); m_rootContentLayer->setPosition(FloatPoint()); // Need to clip to prevent transformed content showing outside this frame @@ -1902,11 +1920,6 @@ void RenderLayerCompositor::ensureRootLayer() frameViewDidChangeSize(); frameViewDidScroll(); - -#if ENABLE(THREADED_SCROLLING) - if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) - scrollingCoordinator->frameViewScrollLayerDidChange(m_renderView->frameView(), m_scrollLayer.get()); -#endif } } else { if (m_overflowControlsHostLayer) { @@ -1941,14 +1954,14 @@ void RenderLayerCompositor::destroyRootLayer() m_layerForHorizontalScrollbar->removeFromParent(); m_layerForHorizontalScrollbar = nullptr; if (Scrollbar* horizontalScrollbar = m_renderView->frameView()->verticalScrollbar()) - m_renderView->frameView()->invalidateScrollbar(horizontalScrollbar, LayoutRect(LayoutPoint(0, 0), horizontalScrollbar->frameRect().size())); + m_renderView->frameView()->invalidateScrollbar(horizontalScrollbar, IntRect(IntPoint(0, 0), horizontalScrollbar->frameRect().size())); } if (m_layerForVerticalScrollbar) { m_layerForVerticalScrollbar->removeFromParent(); m_layerForVerticalScrollbar = nullptr; if (Scrollbar* verticalScrollbar = m_renderView->frameView()->verticalScrollbar()) - m_renderView->frameView()->invalidateScrollbar(verticalScrollbar, LayoutRect(LayoutPoint(0, 0), verticalScrollbar->frameRect().size())); + m_renderView->frameView()->invalidateScrollbar(verticalScrollbar, IntRect(IntPoint(0, 0), verticalScrollbar->frameRect().size())); } if (m_layerForScrollCorner) { @@ -1990,7 +2003,10 @@ void RenderLayerCompositor::attachRootLayer(RootLayerAttachment attachment) break; } } - + + if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) + scrollingCoordinator->frameViewRootLayerDidChange(m_renderView->frameView()); + m_rootLayerAttachment = attachment; rootLayerAttachmentChanged(); } @@ -2116,7 +2132,6 @@ void RenderLayerCompositor::deviceOrPageScaleFactorChanged() rootLayer->noteDeviceOrPageScaleFactorChangedIncludingDescendants(); } -#if ENABLE(THREADED_SCROLLING) ScrollingCoordinator* RenderLayerCompositor::scrollingCoordinator() const { if (Frame* frame = m_renderView->frameView()->frame()) { @@ -2126,7 +2141,6 @@ ScrollingCoordinator* RenderLayerCompositor::scrollingCoordinator() const return 0; } -#endif } // namespace WebCore diff --git a/Source/WebCore/rendering/RenderLayerCompositor.h b/Source/WebCore/rendering/RenderLayerCompositor.h index 00518f3df..86aea07a6 100644 --- a/Source/WebCore/rendering/RenderLayerCompositor.h +++ b/Source/WebCore/rendering/RenderLayerCompositor.h @@ -37,12 +37,10 @@ namespace WebCore { class GraphicsLayer; class RenderEmbeddedObject; class RenderPart; +class ScrollingCoordinator; #if ENABLE(VIDEO) class RenderVideo; #endif -#if ENABLE(THREADED_SCROLLING) -class ScrollingCoordinator; -#endif enum CompositingUpdateType { CompositingUpdateAfterLayoutOrStyleChange, @@ -121,7 +119,7 @@ public: bool needsContentsCompositingLayer(const RenderLayer*) const; // Return the bounding box required for compositing layer and its childern, relative to ancestorLayer. // If layerBoundingBox is not 0, on return it contains the bounding box of this layer only. - LayoutRect calculateCompositedBounds(const RenderLayer*, const RenderLayer* ancestorLayer); + IntRect calculateCompositedBounds(const RenderLayer*, const RenderLayer* ancestorLayer); // Repaint the appropriate layers when the given RenderLayer starts or stops being composited. void repaintOnCompositingChange(RenderLayer*); @@ -134,7 +132,7 @@ public: RenderLayer* enclosingNonStackingClippingLayer(const RenderLayer* layer) const; // Repaint parts of all composited layers that intersect the given absolute rectangle. - void repaintCompositedLayersAbsoluteRect(const LayoutRect&); + void repaintCompositedLayersAbsoluteRect(const IntRect&); RenderLayer* rootRenderLayer() const; GraphicsLayer* rootGraphicsLayer() const; @@ -183,7 +181,7 @@ public: static bool parentFrameContentLayers(RenderPart*); // Update the geometry of the layers used for clipping and scrolling in frames. - void frameViewDidChangeLocation(const LayoutPoint& contentsOffset); + void frameViewDidChangeLocation(const IntPoint& contentsOffset); void frameViewDidChangeSize(); void frameViewDidScroll(); @@ -209,11 +207,13 @@ public: GraphicsLayer* layerForOverhangAreas() const { return m_layerForOverhangAreas.get(); } #endif + void documentBackgroundColorDidChange(); + private: // GraphicsLayerClient Implementation virtual void notifyAnimationStarted(const GraphicsLayer*, double) { } virtual void notifySyncRequired(const GraphicsLayer*) { scheduleLayerFlush(); } - virtual void paintContents(const GraphicsLayer*, GraphicsContext&, GraphicsLayerPaintingPhase, const LayoutRect&); + virtual void paintContents(const GraphicsLayer*, GraphicsContext&, GraphicsLayerPaintingPhase, const IntRect&); virtual bool showDebugBorders(const GraphicsLayer*) const; virtual bool showRepaintCounter(const GraphicsLayer*) const; @@ -231,12 +231,12 @@ private: void clearBackingForLayerIncludingDescendants(RenderLayer*); // Repaint the given rect (which is layer's coords), and regions of child layers that intersect that rect. - void recursiveRepaintLayerRect(RenderLayer*, const LayoutRect&); + void recursiveRepaintLayerRect(RenderLayer*, const IntRect&); - typedef HashMap<RenderLayer*, LayoutRect> OverlapMap; - void addToOverlapMap(OverlapMap&, RenderLayer*, LayoutRect& layerBounds, bool& boundsComputed); + typedef HashMap<RenderLayer*, IntRect> OverlapMap; + void addToOverlapMap(OverlapMap&, RenderLayer*, IntRect& layerBounds, bool& boundsComputed); void addToOverlapMapRecursive(OverlapMap&, RenderLayer*); - static bool overlapsCompositedLayers(OverlapMap&, const LayoutRect& layerBounds); + static bool overlapsCompositedLayers(OverlapMap&, const IntRect& layerBounds); void updateCompositingLayersTimerFired(Timer<RenderLayerCompositor>*); @@ -272,6 +272,8 @@ private: bool isFlushingLayers() const { return m_flushingLayers; } + ScrollingCoordinator* scrollingCoordinator() const; + // Whether a running transition or animation enforces the need for a compositing layer. bool requiresCompositingForAnimation(RenderObject*) const; bool requiresCompositingForTransform(RenderObject*) const; @@ -294,10 +296,6 @@ private: bool requiresContentShadowLayer() const; #endif -#if ENABLE(THREADED_SCROLLING) - ScrollingCoordinator* scrollingCoordinator() const; -#endif - private: RenderView* m_renderView; OwnPtr<GraphicsLayer> m_rootContentLayer; diff --git a/Source/WebCore/rendering/RenderListBox.cpp b/Source/WebCore/rendering/RenderListBox.cpp index d47a1801e..68ae283e3 100644 --- a/Source/WebCore/rendering/RenderListBox.cpp +++ b/Source/WebCore/rendering/RenderListBox.cpp @@ -255,7 +255,7 @@ void RenderListBox::computeLogicalHeight() m_vBar->setSteps(1, max(1, numVisibleItems() - 1), itemHeight); m_vBar->setProportion(numVisibleItems(), numItems()); if (!enabled) { - scrollToYOffsetWithoutAnimation(0); + scrollToOffsetWithoutAnimation(VerticalScrollbar, 0); m_indexOffset = 0; } } @@ -473,7 +473,7 @@ int RenderListBox::listIndexAtOffset(const LayoutSize& offset) if (offset.height() < borderTop() + paddingTop() || offset.height() > height() - paddingBottom() - borderBottom()) return -1; - LayoutUnit scrollbarWidth = m_vBar ? m_vBar->width() : LayoutUnit(0); + int scrollbarWidth = m_vBar ? m_vBar->width() : 0; if (offset.width() < borderLeft() + paddingLeft() || offset.width() > width() - borderRight() - paddingRight() - scrollbarWidth) return -1; @@ -579,7 +579,7 @@ bool RenderListBox::scrollToRevealElementAtListIndex(int index) else newOffset = index - numVisibleItems() + 1; - ScrollableArea::scrollToYOffsetWithoutAnimation(newOffset); + scrollToOffsetWithoutAnimation(VerticalScrollbar, newOffset); return true; } @@ -638,7 +638,7 @@ LayoutUnit RenderListBox::itemHeight() const int RenderListBox::verticalScrollbarWidth() const { - return m_vBar && !m_vBar->isOverlayScrollbar() ? m_vBar->width() : LayoutUnit(0); + return m_vBar && !m_vBar->isOverlayScrollbar() ? m_vBar->width() : 0; } // FIXME: We ignore padding in the vertical direction as far as these values are concerned, since that's @@ -675,7 +675,7 @@ void RenderListBox::setScrollTop(int newTop) if (index < 0 || index >= numItems() || index == m_indexOffset) return; - ScrollableArea::scrollToYOffsetWithoutAnimation(index); + scrollToOffsetWithoutAnimation(VerticalScrollbar, index); } bool RenderListBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const LayoutPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction) diff --git a/Source/WebCore/rendering/RenderListBox.h b/Source/WebCore/rendering/RenderListBox.h index e63e00386..407fa5247 100644 --- a/Source/WebCore/rendering/RenderListBox.h +++ b/Source/WebCore/rendering/RenderListBox.h @@ -62,8 +62,6 @@ private: virtual void updateFromElement(); - virtual bool canHaveChildren() const { return false; } - virtual bool hasControlClip() const { return true; } virtual void paintObject(PaintInfo&, const LayoutPoint&); virtual LayoutRect controlClipRect(const LayoutPoint&) const; diff --git a/Source/WebCore/rendering/RenderListItem.cpp b/Source/WebCore/rendering/RenderListItem.cpp index a5b5b94e8..883218d4f 100644 --- a/Source/WebCore/rendering/RenderListItem.cpp +++ b/Source/WebCore/rendering/RenderListItem.cpp @@ -247,6 +247,9 @@ void RenderListItem::updateMarkerLocation() LayoutStateDisabler layoutStateDisabler(view()); updateFirstLetter(); m_marker->remove(); + // If markerPar is an anonymous block that will lose all its children, destroy it + if (markerPar && (markerPar != lineBoxParent) && markerPar->isAnonymousBlock() && !(toRenderBlock(markerPar)->firstChild())) + markerPar->destroy(); if (!lineBoxParent) lineBoxParent = this; lineBoxParent->addChild(m_marker, firstNonMarkerChild(lineBoxParent)); diff --git a/Source/WebCore/rendering/RenderListMarker.cpp b/Source/WebCore/rendering/RenderListMarker.cpp index e7f85283a..fe193987c 100644 --- a/Source/WebCore/rendering/RenderListMarker.cpp +++ b/Source/WebCore/rendering/RenderListMarker.cpp @@ -1110,7 +1110,7 @@ void RenderListMarker::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffse if (style()->visibility() != VISIBLE) return; - LayoutPoint boxOrigin(paintOffset + location()); + IntPoint boxOrigin(paintOffset + location()); LayoutRect overflowRect(visualOverflowRect()); overflowRect.moveBy(boxOrigin); overflowRect.inflate(maximalOutlineSize(paintInfo.phase)); diff --git a/Source/WebCore/rendering/RenderMarquee.cpp b/Source/WebCore/rendering/RenderMarquee.cpp index ad5892cc6..fe5dbaa22 100644 --- a/Source/WebCore/rendering/RenderMarquee.cpp +++ b/Source/WebCore/rendering/RenderMarquee.cpp @@ -125,13 +125,13 @@ int RenderMarquee::computePosition(EMarqueeDirection dir, bool stopAtContentEdge } if (dir == MRIGHT) { if (stopAtContentEdge) - return max(0, ltr ? (contentWidth - clientWidth) : (clientWidth - contentWidth)); + return max(zeroLayoutUnit, ltr ? (contentWidth - clientWidth) : (clientWidth - contentWidth)); else return ltr ? contentWidth : clientWidth; } else { if (stopAtContentEdge) - return min(0, ltr ? (contentWidth - clientWidth) : (clientWidth - contentWidth)); + return min(zeroLayoutUnit, ltr ? (contentWidth - clientWidth) : (clientWidth - contentWidth)); else return ltr ? -clientWidth : -contentWidth; } diff --git a/Source/WebCore/rendering/RenderMedia.h b/Source/WebCore/rendering/RenderMedia.h index 78e36c4ce..54e625af3 100644 --- a/Source/WebCore/rendering/RenderMedia.h +++ b/Source/WebCore/rendering/RenderMedia.h @@ -51,6 +51,7 @@ protected: private: virtual RenderObjectChildList* virtualChildren() { return children(); } virtual const RenderObjectChildList* virtualChildren() const { return children(); } + virtual bool canHaveChildren() const { return true; } virtual const char* renderName() const { return "RenderMedia"; } virtual bool isMedia() const { return true; } diff --git a/Source/WebCore/rendering/RenderMenuList.h b/Source/WebCore/rendering/RenderMenuList.h index b6f44364f..27872eba2 100644 --- a/Source/WebCore/rendering/RenderMenuList.h +++ b/Source/WebCore/rendering/RenderMenuList.h @@ -62,12 +62,12 @@ private: virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0); virtual void removeChild(RenderObject*); virtual bool createsAnonymousWrapper() const { return true; } - virtual bool canHaveChildren() const { return false; } virtual void updateFromElement(); - virtual bool hasControlClip() const { return true; } virtual LayoutRect controlClipRect(const LayoutPoint&) const; + virtual bool hasControlClip() const { return true; } + virtual RenderText* buttonText() const OVERRIDE { return m_buttonText; } virtual const char* renderName() const { return "RenderMenuList"; } diff --git a/Source/WebCore/rendering/RenderMeter.h b/Source/WebCore/rendering/RenderMeter.h index 6eb171761..c4deb12b2 100644 --- a/Source/WebCore/rendering/RenderMeter.h +++ b/Source/WebCore/rendering/RenderMeter.h @@ -42,7 +42,6 @@ private: virtual const char* renderName() const { return "RenderMeter"; } virtual bool isMeter() const { return true; } virtual bool requiresForcedStyleRecalcPropagation() const { return true; } - virtual bool canHaveChildren() const { return false; } virtual void updateFromElement(); double valueRatio() const; diff --git a/Source/WebCore/rendering/RenderObject.cpp b/Source/WebCore/rendering/RenderObject.cpp index 73d874416..a91b7f89c 100755 --- a/Source/WebCore/rendering/RenderObject.cpp +++ b/Source/WebCore/rendering/RenderObject.cpp @@ -158,7 +158,7 @@ RenderObject* RenderObject::createObject(Node* node, RenderStyle* style) case RUN_IN: case COMPACT: // Only non-replaced block elements can become a region. - if (!style->regionThread().isEmpty() && doc->renderView()) + if (doc->cssRegionsEnabled() && !style->regionThread().isEmpty() && doc->renderView()) return new (arena) RenderRegion(node, doc->renderView()->ensureRenderFlowThreadWithName(style->regionThread())); return new (arena) RenderBlock(node); case LIST_ITEM: @@ -266,6 +266,16 @@ static bool isBeforeAfterContentGeneratedByAncestor(RenderObject* renderer, Rend return false; } +RenderTable* RenderObject::createAnonymousTable() const +{ + RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyle(style()); + newStyle->setDisplay(TABLE); + + RenderTable* table = new (renderArena()) RenderTable(document() /* is anonymous */); + table->setStyle(newStyle.release()); + return table; +} + void RenderObject::addChild(RenderObject* newChild, RenderObject* beforeChild) { RenderObjectChildList* children = virtualChildren(); @@ -310,11 +320,7 @@ void RenderObject::addChild(RenderObject* newChild, RenderObject* beforeChild) if (afterChild && afterChild->isAnonymous() && afterChild->isTable() && !afterChild->isBeforeContent()) table = toRenderTable(afterChild); else { - table = new (renderArena()) RenderTable(document() /* is anonymous */); - RefPtr<RenderStyle> newStyle = RenderStyle::create(); - newStyle->inheritFrom(style()); - newStyle->setDisplay(TABLE); - table->setStyle(newStyle.release()); + table = createAnonymousTable(); addChild(table, beforeChild); } table->addChild(newChild); @@ -329,6 +335,17 @@ void RenderObject::addChild(RenderObject* newChild, RenderObject* beforeChild) toRenderText(newChild)->setText(textToTransform.release(), true); } + // SVG creates renderers for <g display="none">, as SVG requires children of hidden + // <g>s to have renderers - at least that's how our implementation works. Consider: + // <g display="none"><foreignObject><body style="position: relative">FOO... + // - requiresLayer() would return true for the <body>, creating a new RenderLayer + // - when the document is painted, both layers are painted. The <body> layer doesn't + // know that it's inside a "hidden SVG subtree", and thus paints, even if it shouldn't. + // To avoid the problem alltogether, detect early if we're inside a hidden SVG subtree + // and stop creating layers at all for these cases - they're not used anyways. + if (newChild->hasLayer() && !layerCreationAllowedForSubtree()) + toRenderBoxModelObject(newChild)->layer()->removeOnlyThisLayer(); + if (beforeChildHasBeforeAndAfterContent) children->updateBeforeAfterContent(this, BEFORE); } @@ -790,7 +807,7 @@ bool RenderObject::mustRepaintBackgroundOrBorder() const return false; } -void RenderObject::drawLineForBoxSide(GraphicsContext* graphicsContext, LayoutUnit x1, LayoutUnit y1, LayoutUnit x2, LayoutUnit y2, +void RenderObject::drawLineForBoxSide(GraphicsContext* graphicsContext, int x1, int y1, int x2, int y2, BoxSide side, Color color, EBorderStyle style, int adjacentWidth1, int adjacentWidth2, bool antialias) { @@ -1110,7 +1127,7 @@ void RenderObject::addPDFURLRect(GraphicsContext* context, const LayoutRect& rec const AtomicString& href = static_cast<Element*>(n)->getAttribute(hrefAttr); if (href.isNull()) return; - context->setURLForRect(n->document()->completeURL(href), rect); + context->setURLForRect(n->document()->completeURL(href), pixelSnappedIntRect(rect)); } void RenderObject::paintOutline(GraphicsContext* graphicsContext, const LayoutRect& paintRect) @@ -1124,7 +1141,7 @@ void RenderObject::paintOutline(GraphicsContext* graphicsContext, const LayoutRe Color outlineColor = styleToUse->visitedDependentColor(CSSPropertyOutlineColor); - LayoutUnit outlineOffset = styleToUse->outlineOffset(); + int outlineOffset = styleToUse->outlineOffset(); if (styleToUse->outlineStyleIsAuto() || hasOutlineAnnotation()) { if (!theme()->supportsFocusRing(styleToUse)) { @@ -1136,10 +1153,10 @@ void RenderObject::paintOutline(GraphicsContext* graphicsContext, const LayoutRe if (styleToUse->outlineStyleIsAuto() || styleToUse->outlineStyle() == BNONE) return; - LayoutRect inner = paintRect; + IntRect inner = pixelSnappedIntRect(paintRect); inner.inflate(outlineOffset); - LayoutRect outer = inner; + IntRect outer = pixelSnappedIntRect(inner); outer.inflate(outlineWidth); // FIXME: This prevents outlines from painting inside the object. See bug 12042 @@ -1161,14 +1178,14 @@ void RenderObject::paintOutline(GraphicsContext* graphicsContext, const LayoutRe outlineColor = Color(outlineColor.red(), outlineColor.green(), outlineColor.blue()); } - LayoutUnit leftOuter = outer.x(); - LayoutUnit leftInner = inner.x(); - LayoutUnit rightOuter = outer.maxX(); - LayoutUnit rightInner = inner.maxX(); - LayoutUnit topOuter = outer.y(); - LayoutUnit topInner = inner.y(); - LayoutUnit bottomOuter = outer.maxY(); - LayoutUnit bottomInner = inner.maxY(); + int leftOuter = outer.x(); + int leftInner = inner.x(); + int rightOuter = outer.maxX(); + int rightInner = inner.maxX(); + int topOuter = outer.y(); + int topInner = inner.y(); + int bottomOuter = outer.maxY(); + int bottomInner = inner.maxY(); drawLineForBoxSide(graphicsContext, leftOuter, topOuter, leftInner, bottomOuter, BSLeft, outlineColor, outlineStyle, outlineWidth, outlineWidth); drawLineForBoxSide(graphicsContext, leftOuter, topOuter, rightOuter, topInner, BSTop, outlineColor, outlineStyle, outlineWidth, outlineWidth); @@ -1417,8 +1434,8 @@ bool RenderObject::repaintAfterLayoutIfNeeded(RenderBoxModelObject* repaintConta LayoutUnit shadowRight; style()->getBoxShadowHorizontalExtent(shadowLeft, shadowRight); - LayoutUnit borderRight = isBox() ? toRenderBox(this)->borderRight() : LayoutUnit(0); - LayoutUnit boxWidth = isBox() ? toRenderBox(this)->width() : LayoutUnit(0); + LayoutUnit borderRight = isBox() ? toRenderBox(this)->borderRight() : zeroLayoutUnit; + LayoutUnit boxWidth = isBox() ? toRenderBox(this)->width() : zeroLayoutUnit; LayoutUnit borderWidth = max<LayoutUnit>(-outlineStyle->outlineOffset(), max(borderRight, max<LayoutUnit>(style()->borderTopRightRadius().width().calcValue(boxWidth), style()->borderBottomRightRadius().width().calcValue(boxWidth)))) + max(ow, shadowRight); LayoutRect rightRect(newOutlineBox.x() + min(newOutlineBox.width(), oldOutlineBox.width()) - borderWidth, newOutlineBox.y(), @@ -1436,8 +1453,8 @@ bool RenderObject::repaintAfterLayoutIfNeeded(RenderBoxModelObject* repaintConta LayoutUnit shadowBottom; style()->getBoxShadowVerticalExtent(shadowTop, shadowBottom); - LayoutUnit borderBottom = isBox() ? toRenderBox(this)->borderBottom() : LayoutUnit(0); - LayoutUnit boxHeight = isBox() ? toRenderBox(this)->height() : LayoutUnit(0); + LayoutUnit borderBottom = isBox() ? toRenderBox(this)->borderBottom() : zeroLayoutUnit; + LayoutUnit boxHeight = isBox() ? toRenderBox(this)->height() : zeroLayoutUnit; LayoutUnit borderHeight = max<LayoutUnit>(-outlineStyle->outlineOffset(), max(borderBottom, max<LayoutUnit>(style()->borderBottomLeftRadius().height().calcValue(boxHeight), style()->borderBottomRightRadius().height().calcValue(boxHeight)))) + max(ow, shadowBottom); LayoutRect bottomRect(newOutlineBox.x(), min(newOutlineBox.maxY(), oldOutlineBox.maxY()) - borderHeight, @@ -1500,7 +1517,7 @@ void RenderObject::computeRectForRepaint(RenderBoxModelObject* repaintContainer, RenderBox* boxParent = toRenderBox(o); LayoutRect repaintRect(rect); - repaintRect.move(-boxParent->layer()->scrolledContentOffset()); // For overflow:auto/scroll/hidden. + repaintRect.move(-boxParent->scrolledContentOffset()); // For overflow:auto/scroll/hidden. LayoutRect boxRect(LayoutPoint(), boxParent->layer()->size()); rect = intersection(repaintRect, boxRect); @@ -1931,6 +1948,12 @@ void RenderObject::propagateStyleToAnonymousChildren(bool blockChildrenOnly) if (child->style()->columnSpan()) newStyle->setColumnSpan(ColumnSpanAll); } + + // Preserve the position style of anonymous block continuations as they can have relative position when + // they contain block descendants of relative positioned inlines. + if (child->isRelPositioned() && toRenderBlock(child)->isAnonymousBlockContinuation()) + newStyle->setPosition(child->style()->position()); + newStyle->setDisplay(child->style()->display()); child->setStyle(newStyle.release()); } @@ -2006,7 +2029,7 @@ void RenderObject::mapLocalToContainer(RenderBoxModelObject* repaintContainer, b transformState.move(columnOffset); if (o->hasOverflowClip()) - transformState.move(-toRenderBox(o)->layer()->scrolledContentOffset()); + transformState.move(-toRenderBox(o)->scrolledContentOffset()); o->mapLocalToContainer(repaintContainer, fixed, useTransforms, transformState, wasFixed); } @@ -2017,7 +2040,7 @@ void RenderObject::mapAbsoluteToLocalPoint(bool fixed, bool useTransforms, Trans if (o) { o->mapAbsoluteToLocalPoint(fixed, useTransforms, transformState); if (o->hasOverflowClip()) - transformState.move(toRenderBox(o)->layer()->scrolledContentOffset()); + transformState.move(toRenderBox(o)->scrolledContentOffset()); } } @@ -2079,7 +2102,7 @@ LayoutSize RenderObject::offsetFromContainer(RenderObject* o, const LayoutPoint& o->adjustForColumns(offset, point); if (o->hasOverflowClip()) - offset -= toRenderBox(o)->layer()->scrolledContentOffset(); + offset -= toRenderBox(o)->scrolledContentOffset(); return offset; } @@ -2231,6 +2254,18 @@ void RenderObject::willBeDestroyed() remove(); +#ifndef NDEBUG + if (!documentBeingDestroyed() && view() && view()->hasRenderFlowThreads()) { + // After remove, the object and the associated information should not be in any flow thread. + const RenderFlowThreadList* flowThreadList = view()->renderFlowThreadList(); + for (RenderFlowThreadList::const_iterator iter = flowThreadList->begin(); iter != flowThreadList->end(); ++iter) { + const RenderFlowThread* renderFlowThread = *iter; + ASSERT(!renderFlowThread->hasChild(this)); + ASSERT(!renderFlowThread->hasChildInfo(this)); + } + } +#endif + // If this renderer had a parent, remove should have destroyed any counters // attached to this renderer and marked the affected other counters for // reevaluation. This apparently redundant check is here for the case when @@ -2247,6 +2282,33 @@ void RenderObject::willBeDestroyed() } } +void RenderObject::destroyAndCleanupAnonymousWrappers() +{ + RenderObject* parent = this->parent(); + + // If the tree is destroyed or our parent is not anonymous, there is no need for a clean-up phase. + if (documentBeingDestroyed() || !parent || !parent->isAnonymous()) { + destroy(); + return; + } + + bool parentIsLeftOverAnonymousWrapper = false; + + // Currently we only remove anonymous cells' wrapper but we should remove all unneeded + // wrappers. See http://webkit.org/b/52123 as an example where this is needed. + if (parent->isTableCell()) + parentIsLeftOverAnonymousWrapper = parent->firstChild() == this && parent->lastChild() == this; + + destroy(); + + // WARNING: |this| is deleted here. + + if (parentIsLeftOverAnonymousWrapper) { + ASSERT(!parent->firstChild()); + parent->destroyAndCleanupAnonymousWrappers(); + } +} + void RenderObject::destroy() { willBeDestroyed(); @@ -2487,7 +2549,7 @@ void RenderObject::getTextDecorationColors(int decorations, Color& underline, Co linethrough = decorationColor(curr); } } - if (curr->isFloating() || curr->isPositioned()) + if (curr->isFloating() || curr->isPositioned() || curr->isRubyText()) return; curr = curr->parent(); if (curr && curr->isAnonymousBlock() && toRenderBlock(curr)->continuation()) diff --git a/Source/WebCore/rendering/RenderObject.h b/Source/WebCore/rendering/RenderObject.h index 1bcda46aa..ac1bfc76d 100644 --- a/Source/WebCore/rendering/RenderObject.h +++ b/Source/WebCore/rendering/RenderObject.h @@ -58,6 +58,7 @@ class RenderInline; class RenderBlock; class RenderFlowThread; class RenderLayer; +class RenderTable; class RenderTheme; class TransformState; class VisiblePosition; @@ -219,6 +220,8 @@ public: // normal flow object. void handleDynamicFloatPositionChange(); + RenderTable* createAnonymousTable() const; + // RenderObject tree manipulation ////////////////////////////////////////// virtual bool canHaveChildren() const { return virtualChildren(); } @@ -352,6 +355,8 @@ public: bool isHTMLMarquee() const; + bool isTablePart() const { return isTableCell() || isTableCol() || isTableCaption() || isTableRow() || isTableSection(); } + inline bool isBeforeContent() const; inline bool isAfterContent() const; inline bool isBeforeOrAfterContent() const; @@ -359,16 +364,6 @@ public: static inline bool isAfterContent(const RenderObject* obj) { return obj && obj->isAfterContent(); } static inline bool isBeforeOrAfterContent(const RenderObject* obj) { return obj && obj->isBeforeOrAfterContent(); } - inline RenderObject* anonymousContainer(RenderObject* child) - { - RenderObject* container = child; - while (container->parent() != this) - container = container->parent(); - - ASSERT(container->isAnonymous()); - return container; - } - bool hasCounterNodeMap() const { return m_bitfields.hasCounterNodeMap(); } void setHasCounterNodeMap(bool hasCounterNodeMap) { m_bitfields.setHasCounterNodeMap(hasCounterNodeMap); } bool everHadLayout() const { return m_bitfields.everHadLayout(); } @@ -392,7 +387,8 @@ public: // to add SVG renderer methods to RenderObject with an ASSERT_NOT_REACHED() default implementation. virtual bool isSVGRoot() const { return false; } virtual bool isSVGContainer() const { return false; } - virtual bool isSVGViewportContainer() const { return false; } + virtual bool isSVGTransformableContainer() const { return false; } + virtual bool isSVGViewportContainer() const { return false; } virtual bool isSVGGradientStop() const { return false; } virtual bool isSVGHiddenContainer() const { return false; } virtual bool isSVGPath() const { return false; } @@ -801,6 +797,7 @@ public: // as a hook to detect the case of document destruction and don't waste time doing unnecessary work. bool documentBeingDestroyed() const; + void destroyAndCleanupAnonymousWrappers(); virtual void destroy(); // Virtual function helpers for the deprecated Flexible Box Layout (display: -webkit-box). @@ -856,13 +853,15 @@ public: RenderObject* rendererForRootBackground(); protected: + inline bool layerCreationAllowedForSubtree() const; + // Overrides should call the superclass at the end virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle); // Overrides should call the superclass at the start virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); void propagateStyleToAnonymousChildren(bool blockChildrenOnly = false); - void drawLineForBoxSide(GraphicsContext*, LayoutUnit x1, LayoutUnit y1, LayoutUnit x2, LayoutUnit y2, BoxSide, + void drawLineForBoxSide(GraphicsContext*, int x1, int y1, int x2, int y2, BoxSide, Color, EBorderStyle, int adjbw1, int adjbw2, bool antialias = false); void paintFocusRing(GraphicsContext*, const LayoutPoint&, RenderStyle*); @@ -1107,6 +1106,20 @@ inline bool RenderObject::preservesNewline() const return style()->preserveNewline(); } +inline bool RenderObject::layerCreationAllowedForSubtree() const +{ +#if ENABLE(SVG) + RenderObject* parentRenderer = parent(); + while (parentRenderer) { + if (parentRenderer->isSVGHiddenContainer()) + return false; + parentRenderer = parentRenderer->parent(); + } +#endif + + return true; +} + inline void makeMatrixRenderable(TransformationMatrix& matrix, bool has3DRendering) { #if !ENABLE(3D_RENDERING) diff --git a/Source/WebCore/rendering/RenderObjectChildList.cpp b/Source/WebCore/rendering/RenderObjectChildList.cpp index 24055bb16..efe6b8520 100644 --- a/Source/WebCore/rendering/RenderObjectChildList.cpp +++ b/Source/WebCore/rendering/RenderObjectChildList.cpp @@ -520,7 +520,15 @@ void RenderObjectChildList::updateBeforeAfterContent(RenderObject* owner, Pseudo renderer->destroy(); return; } - owner->addChild(generatedContentContainer, insertBefore); + + // When we don't have a first child and are part of a continuation chain, + // insertBefore is incorrectly set to zero above, which causes the :before + // child to end up at the end of continuation chain. + // See https://bugs.webkit.org/show_bug.cgi?id=78380. + if (!insertBefore && type == BEFORE && owner->virtualContinuation()) + owner->addChildIgnoringContinuation(generatedContentContainer, 0); + else + owner->addChild(generatedContentContainer, insertBefore); } if (generatedContentContainer->isChildAllowed(renderer, pseudoElementStyle)) generatedContentContainer->addChild(renderer); diff --git a/Source/WebCore/rendering/RenderProgress.h b/Source/WebCore/rendering/RenderProgress.h index 62436fdc0..fa92bb20b 100644 --- a/Source/WebCore/rendering/RenderProgress.h +++ b/Source/WebCore/rendering/RenderProgress.h @@ -45,7 +45,6 @@ private: virtual const char* renderName() const { return "RenderProgress"; } virtual bool isProgress() const { return true; } virtual bool requiresForcedStyleRecalcPropagation() const { return true; } - virtual bool canHaveChildren() const { return false; } virtual void updateFromElement(); void animationTimerFired(Timer<RenderProgress>*); diff --git a/Source/WebCore/rendering/RenderRegion.cpp b/Source/WebCore/rendering/RenderRegion.cpp index 8df1ced4c..42f7d2955 100644 --- a/Source/WebCore/rendering/RenderRegion.cpp +++ b/Source/WebCore/rendering/RenderRegion.cpp @@ -47,7 +47,9 @@ RenderRegion::RenderRegion(Node* node, RenderFlowThread* flowThread) , m_parentFlowThread(0) , m_isValid(false) , m_hasCustomRegionStyle(false) + , m_regionState(RegionUndefined) { + ASSERT(node->document()->cssRegionsEnabled()); } LayoutRect RenderRegion::regionOverflowRect() const @@ -157,7 +159,8 @@ bool RenderRegion::nodeAtPoint(const HitTestRequest& request, HitTestResult& res // Check our bounds next. For this purpose always assume that we can only be hit in the // foreground phase (which is true for replaced elements like images). - LayoutRect boundsRect(adjustedLocation, size()); + LayoutRect boundsRect = borderBoxRectInRegion(result.region()); + boundsRect.moveBy(adjustedLocation); if (visibleToHitTesting() && action == HitTestForeground && boundsRect.intersects(result.rectForPoint(pointInContainer))) { // Check the contents of the RenderFlowThread. if (m_flowThread && m_flowThread->hitTestRegion(this, request, result, pointInContainer, LayoutPoint(adjustedLocation.x() + borderLeft() + paddingLeft(), adjustedLocation.y() + borderTop() + paddingTop()))) diff --git a/Source/WebCore/rendering/RenderRegion.h b/Source/WebCore/rendering/RenderRegion.h index 6bdcdf672..d46d6da67 100644 --- a/Source/WebCore/rendering/RenderRegion.h +++ b/Source/WebCore/rendering/RenderRegion.h @@ -81,6 +81,16 @@ public: bool isLastRegion() const; void clearBoxStyleInRegion(const RenderBox*); + + enum RegionState { + RegionUndefined, + RegionEmpty, + RegionFit, + RegionOverflow + }; + + RegionState regionState() const { return isValid() ? m_regionState : RegionUndefined; } + void setRegionState(RegionState regionState) { m_regionState = regionState; } private: virtual const char* renderName() const { return "RenderRegion"; } @@ -109,6 +119,7 @@ private: bool m_isValid; bool m_hasCustomRegionStyle; + RegionState m_regionState; }; inline RenderRegion* toRenderRegion(RenderObject* object) diff --git a/Source/WebCore/rendering/RenderReplaced.cpp b/Source/WebCore/rendering/RenderReplaced.cpp index 82c344866..6bdb1831c 100644 --- a/Source/WebCore/rendering/RenderReplaced.cpp +++ b/Source/WebCore/rendering/RenderReplaced.cpp @@ -438,7 +438,7 @@ void RenderReplaced::computePreferredLogicalWidths() m_maxPreferredLogicalWidth = computeReplacedLogicalWidth(false) + borderAndPadding; if (style()->maxWidth().isFixed()) - m_maxPreferredLogicalWidth = min(m_maxPreferredLogicalWidth, style()->maxWidth().value() + (style()->boxSizing() == CONTENT_BOX ? borderAndPadding : 0)); + m_maxPreferredLogicalWidth = min(m_maxPreferredLogicalWidth, style()->maxWidth().value() + (style()->boxSizing() == CONTENT_BOX ? borderAndPadding : zeroLayoutUnit)); if (style()->width().isPercent() || style()->height().isPercent() || style()->maxWidth().isPercent() || style()->maxHeight().isPercent() diff --git a/Source/WebCore/rendering/RenderTable.cpp b/Source/WebCore/rendering/RenderTable.cpp index 5de2ddbda..1a42652db 100644 --- a/Source/WebCore/rendering/RenderTable.cpp +++ b/Source/WebCore/rendering/RenderTable.cpp @@ -232,14 +232,16 @@ void RenderTable::computeLogicalWidth() setLogicalWidth(convertStyleLogicalWidthToComputedWidth(styleLogicalWidth, containerWidthInInlineDirection)); else { // Subtract out any fixed margins from our available width for auto width tables. - LayoutUnit marginTotal = 0; - if (!style()->marginStart().isAuto()) - marginTotal += style()->marginStart().calcValue(availableLogicalWidth); - if (!style()->marginEnd().isAuto()) - marginTotal += style()->marginEnd().calcValue(availableLogicalWidth); - + LayoutUnit marginStart = style()->marginStart().calcMinValue(availableLogicalWidth); + LayoutUnit marginEnd = style()->marginEnd().calcMinValue(availableLogicalWidth); + LayoutUnit marginTotal = marginStart + marginEnd; + // Subtract out our margins to get the available content width. LayoutUnit availableContentLogicalWidth = max<LayoutUnit>(0, containerWidthInInlineDirection - marginTotal); + if (shrinkToAvoidFloats() && cb->containsFloats() && !hasPerpendicularContainingBlock) { + // FIXME: Work with regions someday. + availableContentLogicalWidth = shrinkLogicalWidthToAvoidFloats(marginStart, marginEnd, cb, 0, 0); + } // Ensure we aren't bigger than our available width. setLogicalWidth(min(availableContentLogicalWidth, maxPreferredLogicalWidth())); @@ -272,7 +274,7 @@ LayoutUnit RenderTable::convertStyleLogicalWidthToComputedWidth(const Length& st bool isCSSTable = !node() || !node()->hasTagName(tableTag); if (isCSSTable && styleLogicalWidth.isFixed() && styleLogicalWidth.isPositive()) { recalcBordersInRowDirection(); - borders = borderStart() + borderEnd() + (collapseBorders() ? 0 : paddingStart() + paddingEnd()); + borders = borderStart() + borderEnd() + (collapseBorders() ? zeroLayoutUnit : paddingStart() + paddingEnd()); } return styleLogicalWidth.calcMinValue(availableWidth) + borders; } @@ -370,8 +372,8 @@ void RenderTable::layout() } } - LayoutUnit borderAndPaddingBefore = borderBefore() + (collapsing ? 0 : paddingBefore()); - LayoutUnit borderAndPaddingAfter = borderAfter() + (collapsing ? 0 : paddingAfter()); + LayoutUnit borderAndPaddingBefore = borderBefore() + (collapsing ? zeroLayoutUnit : paddingBefore()); + LayoutUnit borderAndPaddingAfter = borderAfter() + (collapsing ? zeroLayoutUnit : paddingAfter()); setLogicalHeight(logicalHeight() + borderAndPaddingBefore); @@ -382,7 +384,7 @@ void RenderTable::layout() LayoutUnit computedLogicalHeight = 0; if (logicalHeightLength.isFixed()) { // HTML tables size as though CSS height includes border/padding, CSS tables do not. - LayoutUnit borders = node() && node()->hasTagName(tableTag) ? (borderAndPaddingBefore + borderAndPaddingAfter) : 0; + LayoutUnit borders = node() && node()->hasTagName(tableTag) ? (borderAndPaddingBefore + borderAndPaddingAfter) : zeroLayoutUnit; computedLogicalHeight = logicalHeightLength.value() - borders; } else if (logicalHeightLength.isPercent()) computedLogicalHeight = computePercentageLogicalHeight(logicalHeightLength); @@ -390,11 +392,11 @@ void RenderTable::layout() for (RenderObject* child = firstChild(); child; child = child->nextSibling()) { if (child->isTableSection()) - // FIXME: Distribute extra height between all table body sections instead of giving it all to the first one. - toRenderTableSection(child)->layoutRows(child == m_firstBody ? max<LayoutUnit>(0, computedLogicalHeight - totalSectionLogicalHeight) : 0); + // FIXME: Distribute the extra logical height between all table sections instead of giving it all to the first one. + toRenderTableSection(child)->layoutRows(child == topSection() ? max<LayoutUnit>(0, computedLogicalHeight - totalSectionLogicalHeight) : 0); } - if (!m_firstBody && computedLogicalHeight > totalSectionLogicalHeight && !document()->inQuirksMode()) { + if (!topSection() && computedLogicalHeight > totalSectionLogicalHeight && !document()->inQuirksMode()) { // Completely empty tables (with no sections or anything) should at least honor specified height // in strict mode. setLogicalHeight(logicalHeight() + computedLogicalHeight); @@ -617,7 +619,8 @@ void RenderTable::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint& p LayoutRect rect(paintOffset, size()); subtractCaptionRect(rect); - paintBoxShadow(paintInfo, rect, style(), Normal); + if (!boxShadowShouldBeAppliedToBackground(determineBackgroundBleedAvoidance(paintInfo.context))) + paintBoxShadow(paintInfo, rect, style(), Normal); paintBackground(paintInfo, rect); paintBoxShadow(paintInfo, rect, style(), Inset); diff --git a/Source/WebCore/rendering/RenderTable.h b/Source/WebCore/rendering/RenderTable.h index ba9fd3983..9a6557e03 100644 --- a/Source/WebCore/rendering/RenderTable.h +++ b/Source/WebCore/rendering/RenderTable.h @@ -172,7 +172,7 @@ public: LayoutUnit bordersPaddingAndSpacingInRowDirection() const { return borderStart() + borderEnd() + - (collapseBorders() ? 0 : (paddingStart() + paddingEnd() + (numEffCols() + 1) * hBorderSpacing())); + (collapseBorders() ? zeroLayoutUnit : (paddingStart() + paddingEnd() + (numEffCols() + 1) * hBorderSpacing())); } RenderTableCol* colElement(unsigned col, bool* startEdge = 0, bool* endEdge = 0) const; diff --git a/Source/WebCore/rendering/RenderTableCell.cpp b/Source/WebCore/rendering/RenderTableCell.cpp index 5b690f4c7..434ac0d69 100644 --- a/Source/WebCore/rendering/RenderTableCell.cpp +++ b/Source/WebCore/rendering/RenderTableCell.cpp @@ -91,6 +91,25 @@ void RenderTableCell::colSpanOrRowSpanChanged() section()->setNeedsCellRecalc(); } +LayoutUnit RenderTableCell::logicalHeightForRowSizing() const +{ + LayoutUnit adjustedLogicalHeight = logicalHeight() - (intrinsicPaddingBefore() + intrinsicPaddingAfter()); + + LayoutUnit styleLogicalHeight = style()->logicalHeight().calcValue(0); + if (document()->inQuirksMode() || style()->boxSizing() == BORDER_BOX) { + // Explicit heights use the border box in quirks mode. + // Don't adjust height. + } else { + // In strict mode, box-sizing: content-box do the right + // thing and actually add in the border and padding. + LayoutUnit adjustedPaddingBefore = paddingBefore() - intrinsicPaddingBefore(); + LayoutUnit adjustedPaddingAfter = paddingAfter() - intrinsicPaddingAfter(); + styleLogicalHeight += adjustedPaddingBefore + adjustedPaddingAfter + borderBefore() + borderAfter(); + } + + return max(styleLogicalHeight, adjustedLogicalHeight); +} + Length RenderTableCell::styleOrColLogicalWidth() const { Length w = style()->logicalWidth(); @@ -1068,6 +1087,11 @@ void RenderTableCell::paintMask(PaintInfo& paintInfo, const LayoutPoint& paintOf paintMaskImages(paintInfo, LayoutRect(paintOffset, size())); } +bool RenderTableCell::boxShadowShouldBeAppliedToBackground(BackgroundBleedAvoidance, InlineFlowBox*) const +{ + return false; +} + void RenderTableCell::scrollbarsChanged(bool horizontalScrollbarChanged, bool verticalScrollbarChanged) { LayoutUnit scrollbarHeight = scrollbarLogicalHeight(); diff --git a/Source/WebCore/rendering/RenderTableCell.h b/Source/WebCore/rendering/RenderTableCell.h index 2548b4713..e0b4a0558 100644 --- a/Source/WebCore/rendering/RenderTableCell.h +++ b/Source/WebCore/rendering/RenderTableCell.h @@ -85,6 +85,8 @@ public: Length styleOrColLogicalWidth() const; + LayoutUnit logicalHeightForRowSizing() const; + virtual void computePreferredLogicalWidths(); void updateLogicalWidth(LayoutUnit); @@ -151,6 +153,8 @@ private: virtual void paintBoxDecorations(PaintInfo&, const LayoutPoint&); virtual void paintMask(PaintInfo&, const LayoutPoint&); + virtual bool boxShadowShouldBeAppliedToBackground(BackgroundBleedAvoidance, InlineFlowBox*) const OVERRIDE; + virtual LayoutSize offsetFromContainer(RenderObject*, const LayoutPoint&) const; virtual LayoutRect clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer) const; virtual void computeRectForRepaint(RenderBoxModelObject* repaintContainer, LayoutRect&, bool fixed = false) const; diff --git a/Source/WebCore/rendering/RenderTableSection.cpp b/Source/WebCore/rendering/RenderTableSection.cpp index fd55a6321..844209c8d 100644 --- a/Source/WebCore/rendering/RenderTableSection.cpp +++ b/Source/WebCore/rendering/RenderTableSection.cpp @@ -334,14 +334,10 @@ int RenderTableSection::calcRowLogicalHeight() m_rowPos[0] = spacing; for (unsigned r = 0; r < m_grid.size(); r++) { - m_rowPos[r + 1] = 0; - m_grid[r].baseline = 0; - LayoutUnit baseline = 0; - int bdesc = 0; - int ch = m_grid[r].logicalHeight.calcMinValue(0); - int pos = m_rowPos[r] + ch + (m_grid[r].rowRenderer ? spacing : 0); + LayoutUnit baselineDescent = 0; - m_rowPos[r + 1] = max(m_rowPos[r + 1], pos); + // Our base size is the biggest logical height from our cells' styles (excluding row spanning cells). + m_rowPos[r + 1] = max(m_rowPos[r] + m_grid[r].logicalHeight.calcMinValue(0), 0); Row& row = m_grid[r].row; unsigned totalCols = row.size(); @@ -353,10 +349,13 @@ int RenderTableSection::calcRowLogicalHeight() if (!cell || current.inColSpan) continue; - if ((cell->row() + cell->rowSpan() - 1) > r) + // FIXME: We are always adding the height of a rowspan to the last rows which doesn't match + // other browsers. See webkit.org/b/52185 for example. + if ((cell->row() + cell->rowSpan() - 1) != r) continue; - unsigned indx = max(r - cell->rowSpan() + 1, 0u); + // For row spanning cells, |r| is the last row in the span. + unsigned cellStartRow = cell->row(); if (cell->hasOverrideHeight()) { if (!statePusher.didPush()) { @@ -370,43 +369,27 @@ int RenderTableSection::calcRowLogicalHeight() cell->layoutIfNeeded(); } - int adjustedLogicalHeight = cell->logicalHeight() - (cell->intrinsicPaddingBefore() + cell->intrinsicPaddingAfter()); - - ch = cell->style()->logicalHeight().calcValue(0); - if (document()->inQuirksMode() || cell->style()->boxSizing() == BORDER_BOX) { - // Explicit heights use the border box in quirks mode. - // Don't adjust height. - } else { - // In strict mode, box-sizing: content-box do the right - // thing and actually add in the border and padding. - int adjustedPaddingBefore = cell->paddingBefore() - cell->intrinsicPaddingBefore(); - int adjustedPaddingAfter = cell->paddingAfter() - cell->intrinsicPaddingAfter(); - ch += adjustedPaddingBefore + adjustedPaddingAfter + cell->borderBefore() + cell->borderAfter(); - } - ch = max(ch, adjustedLogicalHeight); - - pos = m_rowPos[indx] + ch + (m_grid[r].rowRenderer ? spacing : 0); - - m_rowPos[r + 1] = max(m_rowPos[r + 1], pos); + int cellLogicalHeight = cell->logicalHeightForRowSizing(); + m_rowPos[r + 1] = max(m_rowPos[r + 1], m_rowPos[cellStartRow] + cellLogicalHeight); // find out the baseline EVerticalAlign va = cell->style()->verticalAlign(); if (va == BASELINE || va == TEXT_BOTTOM || va == TEXT_TOP || va == SUPER || va == SUB) { - int b = cell->cellBaselinePosition(); - if (b > cell->borderBefore() + cell->paddingBefore()) { - baseline = max<LayoutUnit>(baseline, b - cell->intrinsicPaddingBefore()); - bdesc = max(bdesc, m_rowPos[indx] + ch - (b - cell->intrinsicPaddingBefore())); + int baselinePosition = cell->cellBaselinePosition(); + if (baselinePosition > cell->borderBefore() + cell->paddingBefore()) { + m_grid[r].baseline = max(m_grid[r].baseline, baselinePosition - cell->intrinsicPaddingBefore()); + baselineDescent = max(baselineDescent, m_rowPos[cellStartRow] + cellLogicalHeight - (baselinePosition - cell->intrinsicPaddingBefore())); } } } // do we have baseline aligned elements? - if (baseline) { + if (m_grid[r].baseline) // increase rowheight if baseline requires - m_rowPos[r + 1] = max(m_rowPos[r + 1], baseline + bdesc + (m_grid[r].rowRenderer ? spacing : 0)); - m_grid[r].baseline = baseline; - } + m_rowPos[r + 1] = max(m_rowPos[r + 1], m_grid[r].baseline + baselineDescent); + // Add the border-spacing to our final position. + m_rowPos[r + 1] += m_grid[r].rowRenderer ? spacing : 0; m_rowPos[r + 1] = max(m_rowPos[r + 1], m_rowPos[r]); } @@ -1306,6 +1289,9 @@ bool RenderTableSection::nodeAtPoint(const HitTestRequest& request, HitTestResul } LayoutUnit offsetInColumnDirection = style()->isHorizontalWritingMode() ? location.y() : location.x(); + + recalcCellsIfNeeded(); + // Find the first row that starts after offsetInColumnDirection. unsigned nextRow = std::upper_bound(m_rowPos.begin(), m_rowPos.end(), offsetInColumnDirection) - m_rowPos.begin(); if (nextRow == m_rowPos.size()) diff --git a/Source/WebCore/rendering/RenderText.cpp b/Source/WebCore/rendering/RenderText.cpp index f6c0373eb..f2408dbcc 100644 --- a/Source/WebCore/rendering/RenderText.cpp +++ b/Source/WebCore/rendering/RenderText.cpp @@ -300,7 +300,7 @@ void RenderText::deleteTextBoxes() PassRefPtr<StringImpl> RenderText::originalText() const { Node* e = node(); - return (e && e->isTextNode()) ? static_cast<Text*>(e)->dataImpl() : 0; + return (e && e->isTextNode()) ? toText(e)->dataImpl() : 0; } void RenderText::absoluteRects(Vector<LayoutRect>& rects, const LayoutPoint& accumulatedOffset) const diff --git a/Source/WebCore/rendering/RenderTextControl.h b/Source/WebCore/rendering/RenderTextControl.h index 744878af4..aa936e7a0 100644 --- a/Source/WebCore/rendering/RenderTextControl.h +++ b/Source/WebCore/rendering/RenderTextControl.h @@ -70,7 +70,6 @@ private: virtual bool isTextControl() const { return true; } virtual void computePreferredLogicalWidths(); virtual void removeLeftoverAnonymousBlock(RenderBlock*) { } - virtual bool canHaveChildren() const { return false; } virtual bool avoidsFloats() const { return true; } virtual void addFocusRingRects(Vector<LayoutRect>&, const LayoutPoint&); diff --git a/Source/WebCore/rendering/RenderTextControlSingleLine.cpp b/Source/WebCore/rendering/RenderTextControlSingleLine.cpp index a86850ce4..a44e2886c 100644 --- a/Source/WebCore/rendering/RenderTextControlSingleLine.cpp +++ b/Source/WebCore/rendering/RenderTextControlSingleLine.cpp @@ -60,7 +60,7 @@ VisiblePosition RenderTextControlInnerBlock::positionForPoint(const LayoutPoint& if (m_multiLine) { RenderTextControl* renderer = toRenderTextControl(node()->shadowAncestorNode()->renderer()); if (renderer->hasOverflowClip()) - contentsPoint += renderer->layer()->scrolledContentOffset(); + contentsPoint += renderer->scrolledContentOffset(); } return RenderBlock::positionForPoint(contentsPoint); @@ -175,7 +175,7 @@ void RenderTextControlSingleLine::showPopup() m_searchPopup->saveRecentSearches(name, m_recentSearches); } - m_searchPopup->popupMenu()->show(absoluteBoundingBoxRect(), document()->view(), -1); + m_searchPopup->popupMenu()->show(pixelSnappedIntRect(absoluteBoundingBoxRect()), document()->view(), -1); } void RenderTextControlSingleLine::hidePopup() @@ -196,7 +196,7 @@ void RenderTextControlSingleLine::paint(PaintInfo& paintInfo, const LayoutPoint& // Convert the rect into the coords used for painting the content contentsRect.moveBy(paintOffset + location()); - theme()->paintCapsLockIndicator(this, paintInfo, contentsRect); + theme()->paintCapsLockIndicator(this, paintInfo, pixelSnappedIntRect(contentsRect)); } } @@ -332,7 +332,7 @@ void RenderTextControlSingleLine::styleDidChange(StyleDifference diff, const Ren containerRenderer->style()->setWidth(Length()); } if (HTMLElement* placeholder = inputElement()->placeholderElement()) - placeholder->ensureInlineStyleDecl()->setProperty(CSSPropertyTextOverflow, textShouldBeTruncated() ? CSSValueEllipsis : CSSValueClip); + placeholder->setInlineStyleProperty(CSSPropertyTextOverflow, textShouldBeTruncated() ? CSSValueEllipsis : CSSValueClip); setHasOverflowClip(false); } diff --git a/Source/WebCore/rendering/RenderTextFragment.cpp b/Source/WebCore/rendering/RenderTextFragment.cpp index 17c9d7b77..ff4082422 100644 --- a/Source/WebCore/rendering/RenderTextFragment.cpp +++ b/Source/WebCore/rendering/RenderTextFragment.cpp @@ -52,7 +52,7 @@ RenderTextFragment::~RenderTextFragment() PassRefPtr<StringImpl> RenderTextFragment::originalText() const { Node* e = node(); - RefPtr<StringImpl> result = ((e && e->isTextNode()) ? static_cast<Text*>(e)->dataImpl() : contentString()); + RefPtr<StringImpl> result = ((e && e->isTextNode()) ? toText(e)->dataImpl() : contentString()); if (!result) return 0; return result->substring(start(), end()); @@ -95,7 +95,7 @@ UChar RenderTextFragment::previousCharacter() const { if (start()) { Node* e = node(); - StringImpl* original = ((e && e->isTextNode()) ? static_cast<Text*>(e)->dataImpl() : contentString()); + StringImpl* original = ((e && e->isTextNode()) ? toText(e)->dataImpl() : contentString()); if (original && start() <= original->length()) return (*original)[start() - 1]; } diff --git a/Source/WebCore/rendering/RenderTheme.cpp b/Source/WebCore/rendering/RenderTheme.cpp index d93a27e25..6be2f5efb 100644 --- a/Source/WebCore/rendering/RenderTheme.cpp +++ b/Source/WebCore/rendering/RenderTheme.cpp @@ -1,7 +1,7 @@ /** * This file is part of the theme implementation for form controls in WebCore. * - * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Apple Computer, Inc. + * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2012 Apple Computer, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -1125,18 +1125,21 @@ Color RenderTheme::focusRingColor() return customFocusRingColor().isValid() ? customFocusRingColor() : defaultTheme()->platformFocusRingColor(); } -String RenderTheme::fileListNameForWidth(const Vector<String>& filenames, const Font& font, int width, bool multipleFilesAllowed) +String RenderTheme::fileListDefaultLabel(bool multipleFilesAllowed) const +{ + if (multipleFilesAllowed) + return fileButtonNoFilesSelectedLabel(); + return fileButtonNoFileSelectedLabel(); +} + +String RenderTheme::fileListNameForWidth(const Vector<String>& filenames, const Font& font, int width, bool multipleFilesAllowed) const { if (width <= 0) return String(); String string; - if (filenames.isEmpty()) { - if (multipleFilesAllowed) - string = fileButtonNoFilesSelectedLabel(); - else - string = fileButtonNoFileSelectedLabel(); - } + if (filenames.isEmpty()) + string = fileListDefaultLabel(multipleFilesAllowed); else if (filenames.size() == 1) string = pathGetFileName(filenames[0]); else diff --git a/Source/WebCore/rendering/RenderTheme.h b/Source/WebCore/rendering/RenderTheme.h index c243b78a5..f65b8523f 100644 --- a/Source/WebCore/rendering/RenderTheme.h +++ b/Source/WebCore/rendering/RenderTheme.h @@ -1,7 +1,7 @@ /* * This file is part of the theme implementation for form controls in WebCore. * - * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Apple Computer, Inc. + * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2012 Apple Computer, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -214,7 +214,8 @@ public: virtual bool popsMenuByArrowKeys() const { return false; } virtual bool popsMenuBySpaceOrReturn() const { return false; } - virtual String fileListNameForWidth(const Vector<String>& filenames, const Font&, int width, bool multipleFilesAllowed); + virtual String fileListDefaultLabel(bool multipleFilesAllowed) const; + virtual String fileListNameForWidth(const Vector<String>& filenames, const Font&, int width, bool multipleFilesAllowed) const; protected: // The platform selection color. diff --git a/Source/WebCore/rendering/RenderThemeChromiumAndroid.cpp b/Source/WebCore/rendering/RenderThemeChromiumAndroid.cpp index c45fc2086..88ac3a8d6 100644 --- a/Source/WebCore/rendering/RenderThemeChromiumAndroid.cpp +++ b/Source/WebCore/rendering/RenderThemeChromiumAndroid.cpp @@ -63,6 +63,12 @@ Color RenderThemeChromiumAndroid::systemColor(int cssValueId) const return RenderTheme::systemColor(cssValueId); } +String RenderThemeChromiumAndroid::extraDefaultStyleSheet() +{ + return RenderThemeChromiumLinux::extraDefaultStyleSheet() + + String(themeChromiumAndroidUserAgentStyleSheet, sizeof(themeChromiumAndroidUserAgentStyleSheet)); +} + void RenderThemeChromiumAndroid::adjustInnerSpinButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const { if (PlatformSupport::layoutTestMode()) { diff --git a/Source/WebCore/rendering/RenderThemeChromiumAndroid.h b/Source/WebCore/rendering/RenderThemeChromiumAndroid.h index e7b9d9885..5fb12bc02 100644 --- a/Source/WebCore/rendering/RenderThemeChromiumAndroid.h +++ b/Source/WebCore/rendering/RenderThemeChromiumAndroid.h @@ -33,14 +33,25 @@ namespace WebCore { class RenderThemeChromiumAndroid : public RenderThemeChromiumLinux { public: static PassRefPtr<RenderTheme> create(); + virtual String extraDefaultStyleSheet() OVERRIDE; - virtual Color systemColor(int cssValidId) const; + virtual Color systemColor(int cssValidId) const OVERRIDE; - virtual void adjustInnerSpinButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const; + virtual void adjustInnerSpinButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const OVERRIDE; + + virtual bool delegatesMenuListRendering() const OVERRIDE { return true; } + +#if ENABLE(TOUCH_EVENTS) + virtual Color platformTapHighlightColor() const OVERRIDE + { + return RenderThemeChromiumAndroid::defaultTapHighlightColor; + } +#endif private: virtual ~RenderThemeChromiumAndroid(); + static const RGBA32 defaultTapHighlightColor = 0x6633b5e5; }; } // namespace WebCore diff --git a/Source/WebCore/rendering/RenderThemeMac.h b/Source/WebCore/rendering/RenderThemeMac.h index dc1af04d0..25065c422 100644 --- a/Source/WebCore/rendering/RenderThemeMac.h +++ b/Source/WebCore/rendering/RenderThemeMac.h @@ -1,7 +1,7 @@ /* * This file is part of the theme implementation for form controls in WebCore. * - * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Computer, Inc. + * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Computer, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -175,7 +175,7 @@ protected: virtual bool shouldShowPlaceholderWhenFocused() const; private: - virtual String fileListNameForWidth(const Vector<String>& filenames, const Font&, int width, bool multipleFilesAllowed); + virtual String fileListNameForWidth(const Vector<String>& filenames, const Font&, int width, bool multipleFilesAllowed) const; LayoutRect inflateRect(const LayoutRect&, const IntSize&, const int* margins, float zoomLevel = 1.0f) const; diff --git a/Source/WebCore/rendering/RenderThemeMac.mm b/Source/WebCore/rendering/RenderThemeMac.mm index e405f6ceb..cd566e859 100644 --- a/Source/WebCore/rendering/RenderThemeMac.mm +++ b/Source/WebCore/rendering/RenderThemeMac.mm @@ -2115,18 +2115,14 @@ NSTextFieldCell* RenderThemeMac::textField() const return m_textField.get(); } -String RenderThemeMac::fileListNameForWidth(const Vector<String>& filenames, const Font& font, int width, bool multipleFilesAllowed) +String RenderThemeMac::fileListNameForWidth(const Vector<String>& filenames, const Font& font, int width, bool multipleFilesAllowed) const { if (width <= 0) return String(); String strToTruncate; - if (filenames.isEmpty()) { - if (multipleFilesAllowed) - strToTruncate = fileButtonNoFilesSelectedLabel(); - else - strToTruncate = fileButtonNoFileSelectedLabel(); - } + if (filenames.isEmpty()) + strToTruncate = fileListDefaultLabel(multipleFilesAllowed); else if (filenames.size() == 1) strToTruncate = [[NSFileManager defaultManager] displayNameAtPath:(filenames[0])]; else diff --git a/Source/WebCore/rendering/RenderTreeAsText.cpp b/Source/WebCore/rendering/RenderTreeAsText.cpp index 06e0fe98e..4cb4c0e67 100644 --- a/Source/WebCore/rendering/RenderTreeAsText.cpp +++ b/Source/WebCore/rendering/RenderTreeAsText.cpp @@ -69,7 +69,7 @@ #endif #if PLATFORM(QT) -#include <QWidget> +#include <QVariant> #endif namespace WebCore { @@ -475,14 +475,13 @@ void RenderTreeAsText::writeRenderObject(TextStream& ts, const RenderObject& o, if (o.isRenderPart()) { const RenderPart* part = toRenderPart(const_cast<RenderObject*>(&o)); if (part->widget() && part->widget()->platformWidget()) { - QWidget* wid = part->widget()->platformWidget(); + QObject* wid = part->widget()->platformWidget(); ts << " [QT: "; - ts << "geometry: {" << wid->geometry() << "} "; - ts << "isHidden: " << wid->isHidden() << " "; + ts << "geometry: {" << wid->property("geometry").toRect() << "} "; + ts << "isHidden: " << !wid->property("isVisible").toBool() << " "; ts << "isSelfVisible: " << part->widget()->isSelfVisible() << " "; - ts << "isParentVisible: " << part->widget()->isParentVisible() << " "; - ts << "mask: {" << wid->mask().boundingRect() << "} ] "; + ts << "isParentVisible: " << part->widget()->isParentVisible() << " ] "; } } #endif diff --git a/Source/WebCore/rendering/RenderWidget.cpp b/Source/WebCore/rendering/RenderWidget.cpp index 2c9565134..ad5a03fd2 100644 --- a/Source/WebCore/rendering/RenderWidget.cpp +++ b/Source/WebCore/rendering/RenderWidget.cpp @@ -308,7 +308,7 @@ void RenderWidget::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset) // Paint a partially transparent wash over selected widgets. if (isSelected() && !document()->printing()) { // FIXME: selectionRect() is in absolute, not painting coordinates. - paintInfo.context->fillRect(selectionRect(), selectionBackgroundColor(), style()->colorSpace()); + paintInfo.context->fillRect(pixelSnappedIntRect(selectionRect()), selectionBackgroundColor(), style()->colorSpace()); } } diff --git a/Source/WebCore/rendering/RootInlineBox.cpp b/Source/WebCore/rendering/RootInlineBox.cpp index 2acfaf02c..8d84bfe61 100644 --- a/Source/WebCore/rendering/RootInlineBox.cpp +++ b/Source/WebCore/rendering/RootInlineBox.cpp @@ -286,7 +286,7 @@ LayoutUnit RootInlineBox::alignBoxesInBlockDirection(LayoutUnit heightOfBlock, G heightOfBlock += annotationsAdjustment; } - LayoutUnit gridSnapAdjustment = lineGridSnapAdjustment(); + LayoutUnit gridSnapAdjustment = lineSnapAdjustment(); if (gridSnapAdjustment) { adjustBlockDirectionPosition(gridSnapAdjustment); heightOfBlock += gridSnapAdjustment; @@ -326,11 +326,11 @@ int RootInlineBox::beforeAnnotationsAdjustment() const return result; } -LayoutUnit RootInlineBox::lineGridSnapAdjustment(LayoutUnit delta) const +LayoutUnit RootInlineBox::lineSnapAdjustment(LayoutUnit delta) const { // If our block doesn't have snapping turned on, do nothing. // FIXME: Implement bounds snapping. - if (block()->style()->lineGridSnap() == LineGridSnapNone) + if (block()->style()->lineSnap() == LineSnapNone) return 0; // Get the current line grid and offset. @@ -377,7 +377,7 @@ LayoutUnit RootInlineBox::lineGridSnapAdjustment(LayoutUnit delta) const firstTextTop = pageLogicalTop + lineGridBox->logicalTop() - lineGrid->borderBefore() - lineGrid->paddingBefore() + lineGridPaginationOrigin; } - if (block()->style()->lineGridSnap() == LineGridSnapContain) { + if (block()->style()->lineSnap() == LineSnapContain) { // Compute the desired offset from the text-top of a grid line. // Look at our height (logicalHeight()). // Look at the total available height. It's going to be (textBottom - textTop) + (n-1)*(multiple with leading) @@ -414,7 +414,7 @@ LayoutUnit RootInlineBox::lineGridSnapAdjustment(LayoutUnit delta) const return result; // Put ourselves at the top of the next page to force a snap onto the new grid established by that page. - return lineGridSnapAdjustment(newPageLogicalTop - (blockOffset + lineTopWithLeading())); + return lineSnapAdjustment(newPageLogicalTop - (blockOffset + lineTopWithLeading())); } GapRects RootInlineBox::lineSelectionGap(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock, diff --git a/Source/WebCore/rendering/RootInlineBox.h b/Source/WebCore/rendering/RootInlineBox.h index fef7ced22..901bcff24 100644 --- a/Source/WebCore/rendering/RootInlineBox.h +++ b/Source/WebCore/rendering/RootInlineBox.h @@ -183,7 +183,7 @@ public: private: void setHasEllipsisBox(bool hasEllipsisBox) { m_hasEllipsisBoxOrHyphen = hasEllipsisBox; } - LayoutUnit lineGridSnapAdjustment(LayoutUnit delta = 0) const; + LayoutUnit lineSnapAdjustment(LayoutUnit delta = 0) const; int beforeAnnotationsAdjustment() const; diff --git a/Source/WebCore/rendering/mathml/RenderMathMLBlock.cpp b/Source/WebCore/rendering/mathml/RenderMathMLBlock.cpp index 2bdccec2c..167eeb21a 100644 --- a/Source/WebCore/rendering/mathml/RenderMathMLBlock.cpp +++ b/Source/WebCore/rendering/mathml/RenderMathMLBlock.cpp @@ -49,7 +49,7 @@ bool RenderMathMLBlock::isChildAllowed(RenderObject* child, RenderStyle*) const return child->node() && child->node()->nodeType() == Node::ELEMENT_NODE; } -PassRefPtr<RenderStyle> RenderMathMLBlock::makeBlockStyle() +PassRefPtr<RenderStyle> RenderMathMLBlock::createBlockStyle() { RefPtr<RenderStyle> newStyle = RenderStyle::create(); newStyle->inheritFrom(style()); @@ -57,14 +57,6 @@ PassRefPtr<RenderStyle> RenderMathMLBlock::makeBlockStyle() return newStyle; } -int RenderMathMLBlock::nonOperatorHeight() const -{ - if (!isRenderMathMLOperator()) - return offsetHeight(); - - return 0; -} - void RenderMathMLBlock::stretchToHeight(int height) { for (RenderObject* current = firstChild(); current; current = current->nextSibling()) @@ -82,7 +74,7 @@ void RenderMathMLBlock::paint(PaintInfo& info, const LayoutPoint& paintOffset) if (info.context->paintingDisabled() || info.phase != PaintPhaseForeground) return; - LayoutPoint adjustedPaintOffset = paintOffset + location(); + IntPoint adjustedPaintOffset = roundedIntPoint(paintOffset + location()); GraphicsContextStateSaver stateSaver(*info.context); diff --git a/Source/WebCore/rendering/mathml/RenderMathMLBlock.h b/Source/WebCore/rendering/mathml/RenderMathMLBlock.h index 4d8184bcf..5d4d780ed 100644 --- a/Source/WebCore/rendering/mathml/RenderMathMLBlock.h +++ b/Source/WebCore/rendering/mathml/RenderMathMLBlock.h @@ -34,6 +34,8 @@ namespace WebCore { +class RenderMathMLOperator; + class RenderMathMLBlock : public RenderBlock { public: RenderMathMLBlock(Node* container); @@ -43,8 +45,15 @@ public: virtual bool isRenderMathMLOperator() const { return false; } virtual bool isRenderMathMLRow() const { return false; } virtual bool isRenderMathMLMath() const { return false; } - virtual bool hasBase() const { return false; } - virtual int nonOperatorHeight() const; + + // MathML defines an "embellished operator" as roughly an <mo> that may have subscripts, + // superscripts, underscripts, overscripts, or a denominator (as in d/dx, where "d" is some + // differential operator). The padding, precedence, and stretchiness of the base <mo> should + // apply to the embellished operator as a whole. unembellishedOperator() checks for being an + // embellished operator, and omits any embellishments. + // FIXME: We don't yet handle all the cases in the MathML spec. See + // https://bugs.webkit.org/show_bug.cgi?id=78617. + virtual RenderMathMLOperator* unembellishedOperator() { return 0; } virtual void stretchToHeight(int height); #if ENABLE(DEBUG_MATH_LAYOUT) @@ -70,7 +79,7 @@ protected: return 0; } - virtual PassRefPtr<RenderStyle> makeBlockStyle(); + virtual PassRefPtr<RenderStyle> createBlockStyle(); private: virtual const char* renderName() const { return isAnonymous() ? "RenderMathMLBlock (anonymous)" : "RenderMathMLBlock"; } diff --git a/Source/WebCore/rendering/mathml/RenderMathMLFenced.cpp b/Source/WebCore/rendering/mathml/RenderMathMLFenced.cpp index 55da1a5ec..c2f67ea93 100644 --- a/Source/WebCore/rendering/mathml/RenderMathMLFenced.cpp +++ b/Source/WebCore/rendering/mathml/RenderMathMLFenced.cpp @@ -44,8 +44,8 @@ enum Braces { OpeningBraceChar = 0x28, ClosingBraceChar = 0x29 }; static const float gOperatorPadding = 0.1f; -RenderMathMLFenced::RenderMathMLFenced(Node* fenced) - : RenderMathMLRow(fenced) +RenderMathMLFenced::RenderMathMLFenced(Element* element) + : RenderMathMLRow(element) , m_open(OpeningBraceChar) , m_close(ClosingBraceChar) { @@ -63,7 +63,7 @@ void RenderMathMLFenced::updateFromElement() if (closeValue.length() > 0) m_close = closeValue[0]; - AtomicString separators = static_cast<Element*>(fenced)->getAttribute(MathMLNames::separatorsAttr); + AtomicString separators = fenced->getAttribute(MathMLNames::separatorsAttr); if (!separators.isNull()) { StringBuilder characters; for (unsigned int i = 0; i < separators.length(); i++) { @@ -80,22 +80,22 @@ void RenderMathMLFenced::updateFromElement() makeFences(); } -RefPtr<RenderStyle> RenderMathMLFenced::makeOperatorStyle() +PassRefPtr<RenderStyle> RenderMathMLFenced::createOperatorStyle() { RefPtr<RenderStyle> newStyle = RenderStyle::create(); newStyle->inheritFrom(style()); newStyle->setDisplay(INLINE_BLOCK); newStyle->setPaddingRight(Length(static_cast<int>(gOperatorPadding * style()->fontSize()), Fixed)); - return newStyle; + return newStyle.release(); } void RenderMathMLFenced::makeFences() { RenderObject* openFence = new (renderArena()) RenderMathMLOperator(node(), m_open); - openFence->setStyle(makeOperatorStyle().release()); + openFence->setStyle(createOperatorStyle()); RenderBlock::addChild(openFence, firstChild()); RenderObject* closeFence = new (renderArena()) RenderMathMLOperator(node(), m_close); - closeFence->setStyle(makeOperatorStyle().release()); + closeFence->setStyle(createOperatorStyle()); RenderBlock::addChild(closeFence); } @@ -122,7 +122,7 @@ void RenderMathMLFenced::addChild(RenderObject* child, RenderObject*) separator = (*m_separators.get())[count - 2]; RenderObject* separatorObj = new (renderArena()) RenderMathMLOperator(node(), separator); - separatorObj->setStyle(makeOperatorStyle().release()); + separatorObj->setStyle(createOperatorStyle()); RenderBlock::addChild(separatorObj, lastChild()); } } diff --git a/Source/WebCore/rendering/mathml/RenderMathMLFenced.h b/Source/WebCore/rendering/mathml/RenderMathMLFenced.h index 9707b3ae6..b2bca9971 100644 --- a/Source/WebCore/rendering/mathml/RenderMathMLFenced.h +++ b/Source/WebCore/rendering/mathml/RenderMathMLFenced.h @@ -34,15 +34,16 @@ namespace WebCore { class RenderMathMLFenced : public RenderMathMLRow { public: - RenderMathMLFenced(Node *fraction); + RenderMathMLFenced(Element*); virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0); virtual void updateFromElement(); private: virtual const char* renderName() const { return "RenderMathMLFenced"; } + PassRefPtr<RenderStyle> createOperatorStyle(); void makeFences(); - RefPtr<RenderStyle> makeOperatorStyle(); + UChar m_open; UChar m_close; RefPtr<StringImpl> m_separators; diff --git a/Source/WebCore/rendering/mathml/RenderMathMLFraction.cpp b/Source/WebCore/rendering/mathml/RenderMathMLFraction.cpp index aeaab20f7..dd59bb998 100644 --- a/Source/WebCore/rendering/mathml/RenderMathMLFraction.cpp +++ b/Source/WebCore/rendering/mathml/RenderMathMLFraction.cpp @@ -46,8 +46,8 @@ static const float gLineThick = 3.f; static const float gFractionBarWidth = 0.05f; static const float gDenominatorPad = 0.1f; -RenderMathMLFraction::RenderMathMLFraction(Element* fraction) - : RenderMathMLBlock(fraction) +RenderMathMLFraction::RenderMathMLFraction(Element* element) + : RenderMathMLBlock(element) , m_lineThickness(gLineMedium) { setChildrenInline(false); @@ -101,7 +101,7 @@ void RenderMathMLFraction::updateFromElement() void RenderMathMLFraction::addChild(RenderObject* child, RenderObject* beforeChild) { RenderBlock* row = new (renderArena()) RenderMathMLBlock(node()); - RefPtr<RenderStyle> rowStyle = makeBlockStyle(); + RefPtr<RenderStyle> rowStyle = createBlockStyle(); rowStyle->setTextAlign(CENTER); Length pad(static_cast<int>(rowStyle->fontSize() * gHorizontalPad), Fixed); @@ -119,6 +119,17 @@ void RenderMathMLFraction::addChild(RenderObject* child, RenderObject* beforeChi updateFromElement(); } +RenderMathMLOperator* RenderMathMLFraction::unembellishedOperator() +{ + RenderObject* numeratorWrapper = firstChild(); + if (!numeratorWrapper) + return 0; + RenderObject* numerator = numeratorWrapper->firstChild(); + if (!numerator || !numerator->isRenderMathMLBlock()) + return 0; + return toRenderMathMLBlock(numerator)->unembellishedOperator(); +} + void RenderMathMLFraction::layout() { updateFromElement(); @@ -153,7 +164,7 @@ void RenderMathMLFraction::paint(PaintInfo& info, const LayoutPoint& paintOffset verticalOffset = numerator->offsetHeight(); } - LayoutPoint adjustedPaintOffset = paintOffset + location(); + IntPoint adjustedPaintOffset = roundedIntPoint(paintOffset + location()); adjustedPaintOffset.setY(adjustedPaintOffset.y() + verticalOffset); GraphicsContextStateSaver stateSaver(*info.context); diff --git a/Source/WebCore/rendering/mathml/RenderMathMLFraction.h b/Source/WebCore/rendering/mathml/RenderMathMLFraction.h index 3971a1e13..4756583b6 100644 --- a/Source/WebCore/rendering/mathml/RenderMathMLFraction.h +++ b/Source/WebCore/rendering/mathml/RenderMathMLFraction.h @@ -35,15 +35,20 @@ namespace WebCore { class RenderMathMLFraction : public RenderMathMLBlock { public: - RenderMathMLFraction(Element* fraction); + RenderMathMLFraction(Element*); virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0); virtual void updateFromElement(); + + virtual RenderMathMLOperator* unembellishedOperator(); + virtual LayoutUnit baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const; virtual void paint(PaintInfo&, const LayoutPoint&); protected: virtual void layout(); + private: virtual const char* renderName() const { return "RenderMathMLFraction"; } + float m_lineThickness; }; diff --git a/Source/WebCore/rendering/mathml/RenderMathMLMath.cpp b/Source/WebCore/rendering/mathml/RenderMathMLMath.cpp index 006fea31c..15e2bbdbe 100644 --- a/Source/WebCore/rendering/mathml/RenderMathMLMath.cpp +++ b/Source/WebCore/rendering/mathml/RenderMathMLMath.cpp @@ -35,8 +35,8 @@ namespace WebCore { using namespace MathMLNames; -RenderMathMLMath::RenderMathMLMath(Node* math) - : RenderMathMLRow(math) +RenderMathMLMath::RenderMathMLMath(Element* element) + : RenderMathMLRow(element) { } diff --git a/Source/WebCore/rendering/mathml/RenderMathMLMath.h b/Source/WebCore/rendering/mathml/RenderMathMLMath.h index a81d5a890..aaa2f4f12 100644 --- a/Source/WebCore/rendering/mathml/RenderMathMLMath.h +++ b/Source/WebCore/rendering/mathml/RenderMathMLMath.h @@ -34,7 +34,7 @@ namespace WebCore { class RenderMathMLMath : public RenderMathMLRow { public: - RenderMathMLMath(Node* container); + RenderMathMLMath(Element*); virtual bool isRenderMathMLMath() const { return true; } private: diff --git a/Source/WebCore/rendering/mathml/RenderMathMLOperator.cpp b/Source/WebCore/rendering/mathml/RenderMathMLOperator.cpp index 2702c0656..ad11d8bac 100644 --- a/Source/WebCore/rendering/mathml/RenderMathMLOperator.cpp +++ b/Source/WebCore/rendering/mathml/RenderMathMLOperator.cpp @@ -38,15 +38,15 @@ namespace WebCore { using namespace MathMLNames; -RenderMathMLOperator::RenderMathMLOperator(Node* container) - : RenderMathMLBlock(container) +RenderMathMLOperator::RenderMathMLOperator(Element* element) + : RenderMathMLBlock(element) , m_stretchHeight(0) , m_operator(0) { } -RenderMathMLOperator::RenderMathMLOperator(Node* container, UChar operatorChar) - : RenderMathMLBlock(container) +RenderMathMLOperator::RenderMathMLOperator(Node* node, UChar operatorChar) + : RenderMathMLBlock(node) , m_stretchHeight(0) , m_operator(convertHyphenMinusToMinusSign(operatorChar)) { @@ -139,7 +139,7 @@ void RenderMathMLOperator::updateFromElement() // This boolean indicates whether stretching is disabled via the markup. bool stretchDisabled = false; - // We made need the element later if we can't stretch. + // We may need the element later if we can't stretch. if (node()->nodeType() == Node::ELEMENT_NODE) { if (Element* mo = static_cast<Element*>(node())) { AtomicString stretchyAttr = mo->getAttribute(MathMLNames::stretchyAttr); @@ -282,7 +282,7 @@ void RenderMathMLOperator::updateFromElement() } } -RefPtr<RenderStyle> RenderMathMLOperator::createStackableStyle(int size, int topRelative) +PassRefPtr<RenderStyle> RenderMathMLOperator::createStackableStyle(int size, int topRelative) { RefPtr<RenderStyle> newStyle = RenderStyle::create(); newStyle->inheritFrom(style()); @@ -307,13 +307,13 @@ RefPtr<RenderStyle> RenderMathMLOperator::createStackableStyle(int size, int top newStyle->setPosition(RelativePosition); } - return newStyle; + return newStyle.release(); } RenderBlock* RenderMathMLOperator::createGlyph(UChar glyph, int size, int charRelative, int topRelative) { RenderBlock* container = new (renderArena()) RenderMathMLBlock(node()); - container->setStyle(createStackableStyle(size, topRelative).release()); + container->setStyle(createStackableStyle(size, topRelative)); addChild(container); RenderBlock* parent = container; if (charRelative) { diff --git a/Source/WebCore/rendering/mathml/RenderMathMLOperator.h b/Source/WebCore/rendering/mathml/RenderMathMLOperator.h index 5ee0660f5..42708724a 100644 --- a/Source/WebCore/rendering/mathml/RenderMathMLOperator.h +++ b/Source/WebCore/rendering/mathml/RenderMathMLOperator.h @@ -35,9 +35,10 @@ namespace WebCore { class RenderMathMLOperator : public RenderMathMLBlock { public: - RenderMathMLOperator(Node* container); - RenderMathMLOperator(Node* container, UChar operatorChar); + RenderMathMLOperator(Element*); + RenderMathMLOperator(Node*, UChar operatorChar); virtual bool isRenderMathMLOperator() const { return true; } + virtual RenderMathMLOperator* unembellishedOperator() { return this; } virtual void stretchToHeight(int pixelHeight); virtual void updateFromElement(); virtual bool isChildAllowed(RenderObject*, RenderStyle*) const; @@ -45,7 +46,7 @@ public: protected: virtual void layout(); - virtual RefPtr<RenderStyle> createStackableStyle(int size, int topRelative); + virtual PassRefPtr<RenderStyle> createStackableStyle(int size, int topRelative); virtual RenderBlock* createGlyph(UChar glyph, int size = 0, int charRelative = 0, int topRelative = 0); private: diff --git a/Source/WebCore/rendering/mathml/RenderMathMLRoot.cpp b/Source/WebCore/rendering/mathml/RenderMathMLRoot.cpp index 24e79ba7e..07e8ff911 100644 --- a/Source/WebCore/rendering/mathml/RenderMathMLRoot.cpp +++ b/Source/WebCore/rendering/mathml/RenderMathMLRoot.cpp @@ -64,8 +64,8 @@ const float gRadicalLineThickness = 0.02f; // Radical thick line thickness (%) const float gRadicalThickLineThickness = 0.1f; -RenderMathMLRoot::RenderMathMLRoot(Node *expression) -: RenderMathMLBlock(expression) +RenderMathMLRoot::RenderMathMLRoot(Element* element) + : RenderMathMLBlock(element) { } @@ -74,7 +74,7 @@ void RenderMathMLRoot::addChild(RenderObject* child, RenderObject* ) if (isEmpty()) { // Add a block for the index RenderBlock* block = new (renderArena()) RenderBlock(node()); - RefPtr<RenderStyle> indexStyle = makeBlockStyle(); + RefPtr<RenderStyle> indexStyle = createBlockStyle(); indexStyle->setDisplay(INLINE_BLOCK); block->setStyle(indexStyle.release()); RenderBlock::addChild(block); @@ -82,7 +82,7 @@ void RenderMathMLRoot::addChild(RenderObject* child, RenderObject* ) // FIXME: the wrapping does not seem to be needed anymore. // this is the base, so wrap it so we can pad it block = new (renderArena()) RenderBlock(node()); - RefPtr<RenderStyle> baseStyle = makeBlockStyle(); + RefPtr<RenderStyle> baseStyle = createBlockStyle(); baseStyle->setDisplay(INLINE_BLOCK); baseStyle->setPaddingLeft(Length(5 * gRadicalWidth , Percent)); block->setStyle(baseStyle.release()); @@ -104,7 +104,7 @@ void RenderMathMLRoot::paint(PaintInfo& info, const LayoutPoint& paintOffset) if (!firstChild() || !lastChild()) return; - LayoutPoint adjustedPaintOffset = paintOffset + location(); + IntPoint adjustedPaintOffset = roundedIntPoint(paintOffset + location()); RenderBoxModelObject* indexBox = toRenderBoxModelObject(lastChild()); @@ -232,7 +232,8 @@ void RenderMathMLRoot::layout() LayoutUnit indexShift = indexBox->offsetWidth() + topStartShift; LayoutUnit radicalHeight = static_cast<LayoutUnit>((1 - gRadicalTopLeftPointYPos) * maxHeight); - LayoutUnit rootMarginTop = radicalHeight + style()->paddingBottom().value() + indexBox->offsetHeight() - (maxHeight + static_cast<LayoutUnit>(gRootPadding * style()->fontSize())); + LayoutUnit rootMarginTop = radicalHeight + style()->paddingBottom().value() + indexBox->offsetHeight() + - (maxHeight + static_cast<LayoutUnit>(gRootPadding * style()->fontSize())); style()->setPaddingLeft(Length(indexShift, Fixed)); if (rootMarginTop > 0) diff --git a/Source/WebCore/rendering/mathml/RenderMathMLRoot.h b/Source/WebCore/rendering/mathml/RenderMathMLRoot.h index ab3e4f057..19b2ec6ec 100644 --- a/Source/WebCore/rendering/mathml/RenderMathMLRoot.h +++ b/Source/WebCore/rendering/mathml/RenderMathMLRoot.h @@ -34,7 +34,7 @@ namespace WebCore { class RenderMathMLRoot : public RenderMathMLBlock { public: - RenderMathMLRoot(Node* fraction); + RenderMathMLRoot(Element*); virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0); virtual void paint(PaintInfo&, const LayoutPoint&); protected: diff --git a/Source/WebCore/rendering/mathml/RenderMathMLRow.cpp b/Source/WebCore/rendering/mathml/RenderMathMLRow.cpp index 922fa9245..203d194de 100644 --- a/Source/WebCore/rendering/mathml/RenderMathMLRow.cpp +++ b/Source/WebCore/rendering/mathml/RenderMathMLRow.cpp @@ -36,57 +36,23 @@ namespace WebCore { using namespace MathMLNames; -RenderMathMLRow::RenderMathMLRow(Node* row) - : RenderMathMLBlock(row) +RenderMathMLRow::RenderMathMLRow(Element* element) + : RenderMathMLBlock(element) { } -int RenderMathMLRow::nonOperatorHeight() const -{ - int maxHeight = 0; - for (RenderObject* current = firstChild(); current; current = current->nextSibling()) { - if (current->isRenderMathMLBlock()) { - RenderMathMLBlock* block = toRenderMathMLBlock(current); - int blockHeight = block->nonOperatorHeight(); - // Check to see if this box has a larger height - if (blockHeight > maxHeight) - maxHeight = blockHeight; - } else if (current->isBoxModelObject()) { - RenderBoxModelObject* box = toRenderBoxModelObject(current); - // Check to see if this box has a larger height - if (box->offsetHeight() > maxHeight) - maxHeight = box->offsetHeight(); - } - - } - return maxHeight; -} - void RenderMathMLRow::layout() { RenderBlock::layout(); LayoutUnit maxHeight = 0; - int childCount = 0; - int operatorCount = 0; // Calculate the non-operator max height of the row. - LayoutUnit operatorHeight = 0; for (RenderObject* current = firstChild(); current; current = current->nextSibling()) { - childCount++; if (current->isRenderMathMLBlock()) { RenderMathMLBlock* block = toRenderMathMLBlock(current); - // Check to see if the non-operator block has a greater height. - if (!block->hasBase() && !block->isRenderMathMLOperator() && block->offsetHeight() > maxHeight) + if (!block->unembellishedOperator() && block->offsetHeight() > maxHeight) maxHeight = block->offsetHeight(); - if (block->hasBase() && block->nonOperatorHeight() > maxHeight) - maxHeight = block->nonOperatorHeight(); - // If the block is an operator, capture the maximum height and increment the count. - if (block->isRenderMathMLOperator()) { - if (block->offsetHeight() > operatorHeight) - operatorHeight = block->offsetHeight(); - operatorCount++; - } } else if (current->isBoxModelObject()) { RenderBoxModelObject* box = toRenderBoxModelObject(current); // Check to see if this box has a larger height. @@ -95,10 +61,8 @@ void RenderMathMLRow::layout() } } - if (childCount > 0 && childCount == operatorCount) { - // We have only operators and so set the max height to the operator height. - maxHeight = operatorHeight; - } + if (!maxHeight) + maxHeight = style()->fontSize(); // Stretch everything to the same height (blocks can ignore the request). if (maxHeight > 0) { @@ -118,17 +82,6 @@ void RenderMathMLRow::layout() } } - -LayoutUnit RenderMathMLRow::baselinePosition(FontBaseline, bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) const -{ - if (firstChild() && firstChild()->isRenderMathMLBlock()) { - RenderMathMLBlock* block = toRenderMathMLBlock(firstChild()); - if (block->isRenderMathMLOperator()) - return block->y() + block->baselinePosition(AlphabeticBaseline, firstLine, direction, linePositionMode); - } - - return RenderBlock::baselinePosition(AlphabeticBaseline, firstLine, direction, linePositionMode); -} } diff --git a/Source/WebCore/rendering/mathml/RenderMathMLRow.h b/Source/WebCore/rendering/mathml/RenderMathMLRow.h index 73c5a26e5..2a520d07b 100644 --- a/Source/WebCore/rendering/mathml/RenderMathMLRow.h +++ b/Source/WebCore/rendering/mathml/RenderMathMLRow.h @@ -34,10 +34,8 @@ namespace WebCore { class RenderMathMLRow : public RenderMathMLBlock { public: - RenderMathMLRow(Node* container); + RenderMathMLRow(Element*); virtual bool isRenderMathMLRow() const { return true; } - virtual int nonOperatorHeight() const; - virtual LayoutUnit baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const; virtual void stretchToHeight(int) {} protected: virtual void layout(); diff --git a/Source/WebCore/rendering/mathml/RenderMathMLSquareRoot.cpp b/Source/WebCore/rendering/mathml/RenderMathMLSquareRoot.cpp index 38ab1c1c0..206426a13 100644 --- a/Source/WebCore/rendering/mathml/RenderMathMLSquareRoot.cpp +++ b/Source/WebCore/rendering/mathml/RenderMathMLSquareRoot.cpp @@ -61,8 +61,8 @@ const float gRadicalLineThickness = 0.02f; // Radical thick line thickness (%) const float gRadicalThickLineThickness = 0.1f; -RenderMathMLSquareRoot::RenderMathMLSquareRoot(Node *expression) - : RenderMathMLBlock(expression) +RenderMathMLSquareRoot::RenderMathMLSquareRoot(Element* element) + : RenderMathMLBlock(element) { } @@ -73,7 +73,7 @@ void RenderMathMLSquareRoot::paint(PaintInfo& info, const LayoutPoint& paintOffs if (info.context->paintingDisabled()) return; - LayoutPoint adjustedPaintOffset = paintOffset + location(); + IntPoint adjustedPaintOffset = roundedIntPoint(paintOffset + location()); LayoutUnit maxHeight = 0; LayoutUnit width = 0; diff --git a/Source/WebCore/rendering/mathml/RenderMathMLSquareRoot.h b/Source/WebCore/rendering/mathml/RenderMathMLSquareRoot.h index c8e41cdfb..ad81fdc56 100644 --- a/Source/WebCore/rendering/mathml/RenderMathMLSquareRoot.h +++ b/Source/WebCore/rendering/mathml/RenderMathMLSquareRoot.h @@ -34,7 +34,7 @@ namespace WebCore { class RenderMathMLSquareRoot : public RenderMathMLBlock { public: - RenderMathMLSquareRoot(Node* fraction); + RenderMathMLSquareRoot(Element*); virtual void paint(PaintInfo&, const LayoutPoint&); protected: virtual void layout(); diff --git a/Source/WebCore/rendering/mathml/RenderMathMLSubSup.cpp b/Source/WebCore/rendering/mathml/RenderMathMLSubSup.cpp index 9a06b0236..631266258 100644 --- a/Source/WebCore/rendering/mathml/RenderMathMLSubSup.cpp +++ b/Source/WebCore/rendering/mathml/RenderMathMLSubSup.cpp @@ -43,20 +43,30 @@ RenderMathMLSubSup::RenderMathMLSubSup(Element* element) : RenderMathMLBlock(element) , m_scripts(0) { - // Determine what kind of under/over expression we have by element name + // Determine what kind of sub/sup expression we have by element name if (element->hasLocalName(MathMLNames::msubTag)) m_kind = Sub; else if (element->hasLocalName(MathMLNames::msupTag)) m_kind = Sup; - else if (element->hasLocalName(MathMLNames::msubsupTag)) - m_kind = SubSup; - else + else { + ASSERT(element->hasLocalName(MathMLNames::msubsupTag)); m_kind = SubSup; + } +} + +RenderBoxModelObject* RenderMathMLSubSup::base() const +{ + RenderObject* baseWrapper = firstChild(); + if (!baseWrapper) + return 0; + RenderObject* base = baseWrapper->firstChild(); + if (!base || !base->isBoxModelObject()) + return 0; + return toRenderBoxModelObject(base); } void RenderMathMLSubSup::addChild(RenderObject* child, RenderObject* beforeChild) { - // Note: The RenderMathMLBlock only allows element children to be added. Element* childElement = toElement(child->node()); @@ -105,72 +115,49 @@ void RenderMathMLSubSup::addChild(RenderObject* child, RenderObject* beforeChild } } +RenderMathMLOperator* RenderMathMLSubSup::unembellishedOperator() +{ + RenderBoxModelObject* base = this->base(); + if (!base || !base->isRenderMathMLBlock()) + return 0; + return toRenderMathMLBlock(base)->unembellishedOperator(); +} + void RenderMathMLSubSup::stretchToHeight(int height) { - RenderObject* base = firstChild(); - if (!base || !base->firstChild()) - return; - - if (base->firstChild() && base->firstChild()->isRenderMathMLBlock()) { - RenderMathMLBlock* block = toRenderMathMLBlock(base->firstChild()); - block->stretchToHeight(static_cast<int>(gSubSupStretch * height)); + RenderBoxModelObject* base = this->base(); + if (base && base->isRenderMathMLBlock()) { + toRenderMathMLBlock(base)->stretchToHeight(static_cast<int>(gSubSupStretch * height)); // Adjust the script placement after we stretch if (height > 0 && m_kind == SubSup && m_scripts) { - RenderObject* script = m_scripts->firstChild(); - if (script) { + RenderObject* supWrapper = m_scripts->firstChild(); + if (supWrapper) { // Calculate the script height without the container margins. - RenderObject* top = script; - int topHeight = getBoxModelObjectHeight(top->firstChild()); - int topAdjust = topHeight / gTopAdjustDivisor; - top->style()->setMarginTop(Length(-topAdjust, Fixed)); - top->style()->setMarginBottom(Length(height - topHeight + topAdjust, Fixed)); - if (top->isBoxModelObject()) { - RenderBoxModelObject* topBox = toRenderBoxModelObject(top); - topBox->updateBoxModelInfoFromStyle(); - } - m_scripts->setNeedsLayout(true); - setNeedsLayout(true); + int supHeight = getBoxModelObjectHeight(supWrapper->firstChild()); + int supTopAdjust = supHeight / gTopAdjustDivisor; + supWrapper->style()->setMarginTop(Length(-supTopAdjust, Fixed)); + supWrapper->style()->setMarginBottom(Length(height - supHeight + supTopAdjust, Fixed)); + supWrapper->setNeedsLayout(true); } } - } } -int RenderMathMLSubSup::nonOperatorHeight() const -{ - if (m_kind == SubSup) - return static_cast<int>(style()->fontSize()*gSubSupStretch); - return static_cast<int>(style()->fontSize()); -} - -void RenderMathMLSubSup::layout() +void RenderMathMLSubSup::layout() { - if (firstChild()) - firstChild()->setNeedsLayout(true); - if (m_scripts) - m_scripts->setNeedsLayout(true); - RenderBlock::layout(); - if (m_kind == SubSup) { - if (RenderObject* base = firstChild()) { - LayoutUnit maxHeight = 0; - RenderObject* current = base->firstChild(); - while (current) { - LayoutUnit height = getBoxModelObjectHeight(current); - if (height > maxHeight) - maxHeight = height; - current = current->nextSibling(); - } - LayoutUnit heightDiff = m_scripts ? (m_scripts->offsetHeight() - maxHeight) / 2 : 0; + if (m_kind == SubSup && m_scripts) { + if (RenderBoxModelObject* base = this->base()) { + LayoutUnit heightDiff = (m_scripts->offsetHeight() - base->offsetHeight()) / 2; if (heightDiff < 0) heightDiff = 0; - base->style()->setPaddingTop(Length(heightDiff, Fixed)); - base->setNeedsLayout(true); + RenderObject* baseWrapper = firstChild(); + baseWrapper->style()->setPaddingTop(Length(heightDiff, Fixed)); + baseWrapper->setNeedsLayout(true); + RenderBlock::layout(); } - setNeedsLayout(true); - RenderBlock::layout(); } } diff --git a/Source/WebCore/rendering/mathml/RenderMathMLSubSup.h b/Source/WebCore/rendering/mathml/RenderMathMLSubSup.h index 2ba466cb4..9c7d02c89 100644 --- a/Source/WebCore/rendering/mathml/RenderMathMLSubSup.h +++ b/Source/WebCore/rendering/mathml/RenderMathMLSubSup.h @@ -34,10 +34,10 @@ namespace WebCore { class RenderMathMLSubSup : public RenderMathMLBlock { public: - RenderMathMLSubSup(Element* fraction); + RenderMathMLSubSup(Element*); virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0); - virtual bool hasBase() const { return true; } - virtual int nonOperatorHeight() const; + + virtual RenderMathMLOperator* unembellishedOperator(); virtual void stretchToHeight(int pixelHeight); virtual LayoutUnit baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const; @@ -47,6 +47,10 @@ protected: private: virtual const char* renderName() const { return "RenderMathMLSubSup"; } + // Omit our subscript and/or superscript. This may return 0 for a non-MathML base (which + // won't occur in valid MathML). + RenderBoxModelObject* base() const; + enum SubSupType { Sub, Sup, SubSup }; SubSupType m_kind; RenderBlock* m_scripts; @@ -57,4 +61,3 @@ private: #endif // ENABLE(MATHML) #endif // RenderMathMLSubSup_h - diff --git a/Source/WebCore/rendering/mathml/RenderMathMLUnderOver.cpp b/Source/WebCore/rendering/mathml/RenderMathMLUnderOver.cpp index 75911036a..0621cd6dd 100644 --- a/Source/WebCore/rendering/mathml/RenderMathMLUnderOver.cpp +++ b/Source/WebCore/rendering/mathml/RenderMathMLUnderOver.cpp @@ -38,27 +38,37 @@ using namespace MathMLNames; static const double gOverSpacingAdjustment = 0.5; -RenderMathMLUnderOver::RenderMathMLUnderOver(Node* expression) - : RenderMathMLBlock(expression) +RenderMathMLUnderOver::RenderMathMLUnderOver(Element* element) + : RenderMathMLBlock(element) { - Element* element = static_cast<Element*>(expression); // Determine what kind of under/over expression we have by element name - if (element->hasLocalName(MathMLNames::munderTag)) m_kind = Under; else if (element->hasLocalName(MathMLNames::moverTag)) m_kind = Over; - else if (element->hasLocalName(MathMLNames::munderoverTag)) + else { + ASSERT(element->hasLocalName(MathMLNames::munderoverTag)); m_kind = UnderOver; - else - m_kind = Under; - + } +} + +RenderBoxModelObject* RenderMathMLUnderOver::base() const +{ + RenderObject* baseWrapper = firstChild(); + if ((m_kind == Over || m_kind == UnderOver) && baseWrapper) + baseWrapper = baseWrapper->nextSibling(); + if (!baseWrapper) + return 0; + RenderObject* base = baseWrapper->firstChild(); + if (!base || !base->isBoxModelObject()) + return 0; + return toRenderBoxModelObject(base); } void RenderMathMLUnderOver::addChild(RenderObject* child, RenderObject* beforeChild) { RenderMathMLBlock* row = new (renderArena()) RenderMathMLBlock(node()); - RefPtr<RenderStyle> rowStyle = makeBlockStyle(); + RefPtr<RenderStyle> rowStyle = createBlockStyle(); row->setStyle(rowStyle.release()); row->setIsAnonymous(true); @@ -109,6 +119,14 @@ void RenderMathMLUnderOver::addChild(RenderObject* child, RenderObject* beforeCh row->addChild(child); } +RenderMathMLOperator* RenderMathMLUnderOver::unembellishedOperator() +{ + RenderBoxModelObject* base = this->base(); + if (!base || !base->isRenderMathMLBlock()) + return 0; + return toRenderMathMLBlock(base)->unembellishedOperator(); +} + inline int getOffsetHeight(RenderObject* obj) { if (obj->isBoxModelObject()) { @@ -121,21 +139,7 @@ inline int getOffsetHeight(RenderObject* obj) void RenderMathMLUnderOver::stretchToHeight(int height) { - - RenderObject* base = firstChild(); - if (!base) - return; - - // For over or underover, the base is the sibling of the first child - if (m_kind != Under) - base = base->nextSibling(); - - if (!base) - return; - - // use the child of the row which is the actual base - base = base->firstChild(); - + RenderBoxModelObject* base = this->base(); if (base && base->isRenderMathMLBlock()) { RenderMathMLBlock* block = toRenderMathMLBlock(base); block->stretchToHeight(height); @@ -275,21 +279,6 @@ LayoutUnit RenderMathMLUnderOver::baselinePosition(FontBaseline, bool firstLine, return baseline; } - -int RenderMathMLUnderOver::nonOperatorHeight() const -{ - int nonOperators = 0; - for (RenderObject* current = firstChild(); current; current = current->nextSibling()) { - if (current->firstChild() && current->firstChild()->isRenderMathMLBlock()) { - RenderMathMLBlock* block = toRenderMathMLBlock(current->firstChild()); - if (!block->isRenderMathMLOperator()) - nonOperators += getOffsetHeight(current); - } else - nonOperators += getOffsetHeight(current); - } - return nonOperators; -} - } #endif // ENABLE(MATHML) diff --git a/Source/WebCore/rendering/mathml/RenderMathMLUnderOver.h b/Source/WebCore/rendering/mathml/RenderMathMLUnderOver.h index 2fe619821..e25e94768 100644 --- a/Source/WebCore/rendering/mathml/RenderMathMLUnderOver.h +++ b/Source/WebCore/rendering/mathml/RenderMathMLUnderOver.h @@ -34,16 +34,21 @@ namespace WebCore { class RenderMathMLUnderOver : public RenderMathMLBlock { public: - RenderMathMLUnderOver(Node* expression); + RenderMathMLUnderOver(Element*); virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0); + + virtual RenderMathMLOperator* unembellishedOperator(); virtual void layout(); - virtual bool hasBase() const { return true; } - virtual int nonOperatorHeight() const; virtual LayoutUnit baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const; virtual void stretchToHeight(int pixelHeight); + private: virtual const char* renderName() const { return "RenderMathMLUnderOver"; } + // Omit our underscript and/or overscript. This may return 0 for a non-MathML base (which + // won't occur in valid MathML). + RenderBoxModelObject* base() const; + enum UnderOverType { Under, Over, UnderOver }; UnderOverType m_kind; }; diff --git a/Source/WebCore/rendering/style/RenderStyle.cpp b/Source/WebCore/rendering/style/RenderStyle.cpp index 08bfbf90f..c62b3b198 100644 --- a/Source/WebCore/rendering/style/RenderStyle.cpp +++ b/Source/WebCore/rendering/style/RenderStyle.cpp @@ -466,7 +466,8 @@ StyleDifference RenderStyle::diff(const RenderStyle* other, unsigned& changedCon || rareInheritedData->textEmphasisCustomMark != other->rareInheritedData->textEmphasisCustomMark || rareInheritedData->m_lineBoxContain != other->rareInheritedData->m_lineBoxContain || rareInheritedData->m_lineGrid != other->rareInheritedData->m_lineGrid - || rareInheritedData->m_lineGridSnap != other->rareInheritedData->m_lineGridSnap) + || rareInheritedData->m_lineSnap != other->rareInheritedData->m_lineSnap + || rareInheritedData->m_lineAlign != other->rareInheritedData->m_lineAlign) return StyleDifferenceLayout; if (!rareInheritedData->shadowDataEquivalent(*other->rareInheritedData.get())) @@ -886,7 +887,7 @@ static float calcConstraintScaleFor(const IntRect& rect, const RoundedRect::Radi RoundedRect RenderStyle::getRoundedBorderFor(const LayoutRect& borderRect, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const { - RoundedRect roundedRect(borderRect); + RoundedRect roundedRect(pixelSnappedIntRect(borderRect)); if (hasBorderRadius()) { RoundedRect::Radii radii = calcRadiiFor(surround->border, borderRect.size()); radii.scale(calcConstraintScaleFor(borderRect, radii)); @@ -915,7 +916,7 @@ RoundedRect RenderStyle::getRoundedInnerBorderFor(const LayoutRect& borderRect, borderRect.width() - leftWidth - rightWidth, borderRect.height() - topWidth - bottomWidth); - RoundedRect roundedRect(innerRect); + RoundedRect roundedRect(pixelSnappedIntRect(innerRect)); if (hasBorderRadius()) { RoundedRect::Radii radii = getRoundedBorderFor(borderRect).radii(); diff --git a/Source/WebCore/rendering/style/RenderStyle.h b/Source/WebCore/rendering/style/RenderStyle.h index 74fae1daf..647d3e9fc 100644 --- a/Source/WebCore/rendering/style/RenderStyle.h +++ b/Source/WebCore/rendering/style/RenderStyle.h @@ -791,9 +791,9 @@ public: float aspectRatioNumerator() const { return rareNonInheritedData->m_aspectRatioNumerator; } EBoxAlignment boxAlign() const { return static_cast<EBoxAlignment>(rareNonInheritedData->m_deprecatedFlexibleBox->align); } EBoxDirection boxDirection() const { return static_cast<EBoxDirection>(inherited_flags._box_direction); } - float boxFlex() { return rareNonInheritedData->m_deprecatedFlexibleBox->flex; } + float boxFlex() const { return rareNonInheritedData->m_deprecatedFlexibleBox->flex; } unsigned int boxFlexGroup() const { return rareNonInheritedData->m_deprecatedFlexibleBox->flex_group; } - EBoxLines boxLines() { return static_cast<EBoxLines>(rareNonInheritedData->m_deprecatedFlexibleBox->lines); } + EBoxLines boxLines() const { return static_cast<EBoxLines>(rareNonInheritedData->m_deprecatedFlexibleBox->lines); } unsigned int boxOrdinalGroup() const { return rareNonInheritedData->m_deprecatedFlexibleBox->ordinal_group; } EBoxOrient boxOrient() const { return static_cast<EBoxOrient>(rareNonInheritedData->m_deprecatedFlexibleBox->orient); } EBoxPack boxPack() const { return static_cast<EBoxPack>(rareNonInheritedData->m_deprecatedFlexibleBox->pack); } @@ -903,7 +903,8 @@ public: RegionOverflow regionOverflow() const { return static_cast<RegionOverflow>(rareNonInheritedData->m_regionOverflow); } const AtomicString& lineGrid() const { return rareInheritedData->m_lineGrid; } - LineGridSnap lineGridSnap() const { return static_cast<LineGridSnap>(rareInheritedData->m_lineGridSnap); } + LineSnap lineSnap() const { return static_cast<LineSnap>(rareInheritedData->m_lineSnap); } + LineAlign lineAlign() const { return static_cast<LineAlign>(rareInheritedData->m_lineAlign); } WrapFlow wrapFlow() const { return static_cast<WrapFlow>(rareNonInheritedData->m_wrapFlow); } WrapThrough wrapThrough() const { return static_cast<WrapThrough>(rareNonInheritedData->m_wrapThrough); } @@ -943,6 +944,9 @@ public: #if ENABLE(TOUCH_EVENTS) Color tapHighlightColor() const { return rareInheritedData->tapHighlightColor; } #endif +#if ENABLE(OVERFLOW_SCROLLING) + bool useTouchOverflowScrolling() const { return rareInheritedData->useTouchOverflowScrolling; } +#endif bool textSizeAdjust() const { return rareInheritedData->textSizeAdjust; } ETextSecurity textSecurity() const { return static_cast<ETextSecurity>(rareInheritedData->textSecurity); } @@ -1302,7 +1306,8 @@ public: // End CSS3 Setters void setLineGrid(const AtomicString& lineGrid) { SET_VAR(rareInheritedData, m_lineGrid, lineGrid); } - void setLineGridSnap(LineGridSnap lineGridSnap) { SET_VAR(rareInheritedData, m_lineGridSnap, lineGridSnap); } + void setLineSnap(LineSnap lineSnap) { SET_VAR(rareInheritedData, m_lineSnap, lineSnap); } + void setLineAlign(LineAlign lineAlign) { SET_VAR(rareInheritedData, m_lineAlign, lineAlign); } void setFlowThread(const AtomicString& flowThread) { SET_VAR(rareNonInheritedData, m_flowThread, flowThread); } void setRegionThread(const AtomicString& regionThread) { SET_VAR(rareNonInheritedData, m_regionThread, regionThread); } @@ -1347,6 +1352,9 @@ public: #if ENABLE(TOUCH_EVENTS) void setTapHighlightColor(const Color& c) { SET_VAR(rareInheritedData, tapHighlightColor, c); } #endif +#if ENABLE(OVERFLOW_SCROLLING) + void setUseTouchOverflowScrolling(bool v) { SET_VAR(rareInheritedData, useTouchOverflowScrolling, v); } +#endif bool setTextSizeAdjust(bool); void setTextSecurity(ETextSecurity aTextSecurity) { SET_VAR(rareInheritedData, textSecurity, aTextSecurity); } @@ -1532,8 +1540,8 @@ public: static Length initialPadding() { return Length(Fixed); } static Length initialTextIndent() { return Length(Fixed); } static EVerticalAlign initialVerticalAlign() { return BASELINE; } - static int initialWidows() { return 2; } - static int initialOrphans() { return 2; } + static short initialWidows() { return 2; } + static short initialOrphans() { return 2; } static Length initialLineHeight() { return Length(-100.0, Percent); } static ETextAlign initialTextAlign() { return TAAUTO; } static ETextDecoration initialTextDecoration() { return TDNONE; } @@ -1546,8 +1554,8 @@ public: static EBoxOrient initialBoxOrient() { return HORIZONTAL; } static EBoxPack initialBoxPack() { return Start; } static float initialBoxFlex() { return 0.0f; } - static int initialBoxFlexGroup() { return 1; } - static int initialBoxOrdinalGroup() { return 1; } + static unsigned int initialBoxFlexGroup() { return 1; } + static unsigned int initialBoxOrdinalGroup() { return 1; } static EBoxSizing initialBoxSizing() { return CONTENT_BOX; } static StyleReflection* initialBoxReflect() { return 0; } static float initialFlexboxWidthPositiveFlex() { return 0; } @@ -1559,7 +1567,7 @@ public: static EFlexAlign initialFlexAlign() { return AlignStretch; } static EFlexAlign initialFlexItemAlign() { return AlignAuto; } static EFlexDirection initialFlexDirection() { return FlowRow; } - static EFlexWrap initialFlexWrap() { return FlexNoWrap; } + static EFlexWrap initialFlexWrap() { return FlexWrapNone; } static int initialMarqueeLoopCount() { return -1; } static int initialMarqueeSpeed() { return 85; } static Length initialMarqueeIncrement() { return Length(6, Fixed); } @@ -1631,7 +1639,8 @@ public: #endif static const AtomicString& initialLineGrid() { return nullAtom; } - static LineGridSnap initialLineGridSnap() { return LineGridSnapNone; } + static LineSnap initialLineSnap() { return LineSnapNone; } + static LineAlign initialLineAlign() { return LineAlignNone; } static const AtomicString& initialFlowThread() { return nullAtom; } static const AtomicString& initialRegionThread() { return nullAtom; } @@ -1647,6 +1656,9 @@ public: #if ENABLE(TOUCH_EVENTS) static Color initialTapHighlightColor(); #endif +#if ENABLE(OVERFLOW_SCROLLING) + static bool initialUseTouchOverflowScrolling() { return false; } +#endif #if ENABLE(DASHBOARD_SUPPORT) static const Vector<StyleDashboardRegion>& initialDashboardRegions(); static const Vector<StyleDashboardRegion>& noneDashboardRegions(); diff --git a/Source/WebCore/rendering/style/RenderStyleConstants.h b/Source/WebCore/rendering/style/RenderStyleConstants.h index 0ce3d8886..aee10813a 100644 --- a/Source/WebCore/rendering/style/RenderStyleConstants.h +++ b/Source/WebCore/rendering/style/RenderStyleConstants.h @@ -171,7 +171,7 @@ enum EBoxDirection { BNORMAL, BREVERSE }; enum EFlexPack { PackStart, PackEnd, PackCenter, PackJustify, PackDistribute }; enum EFlexAlign { AlignAuto, AlignStart, AlignEnd, AlignCenter, AlignStretch, AlignBaseline }; enum EFlexDirection { FlowRow, FlowRowReverse, FlowColumn, FlowColumnReverse }; -enum EFlexWrap { FlexNoWrap, FlexWrap, FlexWrapReverse }; +enum EFlexWrap { FlexWrapNone, FlexWrap, FlexWrapReverse }; enum ETextSecurity { TSNONE, TSDISC, TSCIRCLE, TSSQUARE @@ -454,7 +454,9 @@ enum RegionOverflow { AutoRegionOverflow, BreakRegionOverflow }; enum ColumnAxis { HorizontalColumnAxis, VerticalColumnAxis, AutoColumnAxis }; -enum LineGridSnap { LineGridSnapNone, LineGridSnapBaseline, LineGridSnapContain }; +enum LineSnap { LineSnapNone, LineSnapBaseline, LineSnapContain }; + +enum LineAlign { LineAlignNone, LineAlignEdges }; enum WrapFlow { WrapFlowAuto, WrapFlowBoth, WrapFlowLeft, WrapFlowRight, WrapFlowMaximum, WrapFlowClear }; diff --git a/Source/WebCore/rendering/style/StyleCachedImage.cpp b/Source/WebCore/rendering/style/StyleCachedImage.cpp index 1a7d9ef10..a7a1996fa 100644 --- a/Source/WebCore/rendering/style/StyleCachedImage.cpp +++ b/Source/WebCore/rendering/style/StyleCachedImage.cpp @@ -24,11 +24,22 @@ #include "config.h" #include "StyleCachedImage.h" -#include "CachedImage.h" #include "RenderObject.h" namespace WebCore { +StyleCachedImage::StyleCachedImage(CachedImage* image) + : m_image(image) +{ + m_isCachedImage = true; + m_image->addClient(this); +} + +StyleCachedImage::~StyleCachedImage() +{ + m_image->removeClient(this); +} + PassRefPtr<CSSValue> StyleCachedImage::cssValue() const { return CSSPrimitiveValue::create(m_image->url(), CSSPrimitiveValue::CSS_URI); diff --git a/Source/WebCore/rendering/style/StyleCachedImage.h b/Source/WebCore/rendering/style/StyleCachedImage.h index 06dfb25a6..c9913fd82 100644 --- a/Source/WebCore/rendering/style/StyleCachedImage.h +++ b/Source/WebCore/rendering/style/StyleCachedImage.h @@ -24,16 +24,18 @@ #ifndef StyleCachedImage_h #define StyleCachedImage_h +#include "CachedImage.h" #include "CachedResourceHandle.h" #include "StyleImage.h" namespace WebCore { -class CachedImage; - -class StyleCachedImage : public StyleImage { +class StyleCachedImage : public StyleImage, private CachedImageClient { + WTF_MAKE_FAST_ALLOCATED; public: static PassRefPtr<StyleCachedImage> create(CachedImage* image) { return adoptRef(new StyleCachedImage(image)); } + virtual ~StyleCachedImage(); + virtual WrappedImagePtr data() const { return m_image.get(); } virtual PassRefPtr<CSSValue> cssValue() const; @@ -54,11 +56,7 @@ public: virtual PassRefPtr<Image> image(RenderObject*, const IntSize&) const; private: - StyleCachedImage(CachedImage* image) - : m_image(image) - { - m_isCachedImage = true; - } + explicit StyleCachedImage(CachedImage*); CachedResourceHandle<CachedImage> m_image; }; diff --git a/Source/WebCore/rendering/style/StyleRareInheritedData.cpp b/Source/WebCore/rendering/style/StyleRareInheritedData.cpp index 9dda82d8b..5d73793ce 100644 --- a/Source/WebCore/rendering/style/StyleRareInheritedData.cpp +++ b/Source/WebCore/rendering/style/StyleRareInheritedData.cpp @@ -53,7 +53,11 @@ StyleRareInheritedData::StyleRareInheritedData() , textEmphasisPosition(TextEmphasisPositionOver) , m_lineBoxContain(RenderStyle::initialLineBoxContain()) , m_imageRendering(RenderStyle::initialImageRendering()) - , m_lineGridSnap(RenderStyle::initialLineGridSnap()) + , m_lineSnap(RenderStyle::initialLineSnap()) + , m_lineAlign(RenderStyle::initialLineAlign()) +#if ENABLE(OVERFLOW_SCROLLING) + , useTouchOverflowScrolling(RenderStyle::initialUseTouchOverflowScrolling()) +#endif , hyphenationLimitBefore(-1) , hyphenationLimitAfter(-1) , hyphenationLimitLines(-1) @@ -97,7 +101,11 @@ StyleRareInheritedData::StyleRareInheritedData(const StyleRareInheritedData& o) , textEmphasisPosition(o.textEmphasisPosition) , m_lineBoxContain(o.m_lineBoxContain) , m_imageRendering(o.m_imageRendering) - , m_lineGridSnap(o.m_lineGridSnap) + , m_lineSnap(o.m_lineSnap) + , m_lineAlign(o.m_lineAlign) +#if ENABLE(OVERFLOW_SCROLLING) + , useTouchOverflowScrolling(o.useTouchOverflowScrolling) +#endif , hyphenationString(o.hyphenationString) , hyphenationLimitBefore(o.hyphenationLimitBefore) , hyphenationLimitAfter(o.hyphenationLimitAfter) @@ -149,6 +157,9 @@ bool StyleRareInheritedData::operator==(const StyleRareInheritedData& o) const && wordWrap == o.wordWrap && nbspMode == o.nbspMode && khtmlLineBreak == o.khtmlLineBreak +#if ENABLE(OVERFLOW_SCROLLING) + && useTouchOverflowScrolling == o.useTouchOverflowScrolling +#endif && textSizeAdjust == o.textSizeAdjust && resize == o.resize && userSelect == o.userSelect @@ -168,7 +179,8 @@ bool StyleRareInheritedData::operator==(const StyleRareInheritedData& o) const && QuotesData::equal(quotes.get(), o.quotes.get()) && m_lineGrid == o.m_lineGrid && m_imageRendering == o.m_imageRendering - && m_lineGridSnap == o.m_lineGridSnap; + && m_lineSnap == o.m_lineSnap + && m_lineAlign == o.m_lineAlign; } bool StyleRareInheritedData::shadowDataEquivalent(const StyleRareInheritedData& o) const diff --git a/Source/WebCore/rendering/style/StyleRareInheritedData.h b/Source/WebCore/rendering/style/StyleRareInheritedData.h index fd5796936..570dbb573 100644 --- a/Source/WebCore/rendering/style/StyleRareInheritedData.h +++ b/Source/WebCore/rendering/style/StyleRareInheritedData.h @@ -91,7 +91,11 @@ public: unsigned m_lineBoxContain: 7; // LineBoxContain // CSS Image Values Level 3 unsigned m_imageRendering : 2; // EImageRendering - unsigned m_lineGridSnap : 2; // LineGridSnap + unsigned m_lineSnap : 2; // LineSnap + unsigned m_lineAlign : 1; // LineAlign +#if ENABLE(OVERFLOW_SCROLLING) + unsigned useTouchOverflowScrolling: 1; +#endif AtomicString hyphenationString; short hyphenationLimitBefore; diff --git a/Source/WebCore/rendering/svg/RenderSVGContainer.h b/Source/WebCore/rendering/svg/RenderSVGContainer.h index c7d9f205f..b3324703c 100644 --- a/Source/WebCore/rendering/svg/RenderSVGContainer.h +++ b/Source/WebCore/rendering/svg/RenderSVGContainer.h @@ -41,6 +41,7 @@ public: virtual void paint(PaintInfo&, const LayoutPoint&); virtual void setNeedsBoundariesUpdate() { m_needsBoundariesUpdate = true; } + virtual bool didTransformToRootUpdate() { return false; } protected: virtual RenderObjectChildList* virtualChildren() { return children(); } diff --git a/Source/WebCore/rendering/svg/RenderSVGInlineText.cpp b/Source/WebCore/rendering/svg/RenderSVGInlineText.cpp index 74facc3cf..591316291 100644 --- a/Source/WebCore/rendering/svg/RenderSVGInlineText.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGInlineText.cpp @@ -267,6 +267,8 @@ void RenderSVGInlineText::computeNewScaledFontForStyle(RenderObject* renderer, c } FontDescription fontDescription(style->fontDescription()); + + // FIXME: We need to better handle the case when we compute very small fonts below (below 1pt). fontDescription.setComputedSize(CSSStyleSelector::getComputedSizeFromSpecifiedSize(document, scalingFactor, fontDescription.isAbsoluteSize(), fontDescription.computedSize(), DoNotUseSmartMinimumForFontSize)); scaledFont = Font(fontDescription, 0, 0); diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceContainer.cpp b/Source/WebCore/rendering/svg/RenderSVGResourceContainer.cpp index 5adb29950..2e03e9f59 100644 --- a/Source/WebCore/rendering/svg/RenderSVGResourceContainer.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGResourceContainer.cpp @@ -38,7 +38,7 @@ static inline SVGDocumentExtensions* svgExtensionsFromNode(Node* node) RenderSVGResourceContainer::RenderSVGResourceContainer(SVGStyledElement* node) : RenderSVGHiddenContainer(node) - , m_id(node->hasID() ? node->getIdAttribute() : nullAtom) + , m_id(node->getIdAttribute()) , m_registered(false) , m_isInvalidating(false) { diff --git a/Source/WebCore/rendering/svg/RenderSVGRoot.cpp b/Source/WebCore/rendering/svg/RenderSVGRoot.cpp index ba821cca2..7baa4fc38 100644 --- a/Source/WebCore/rendering/svg/RenderSVGRoot.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGRoot.cpp @@ -306,7 +306,7 @@ void RenderSVGRoot::buildLocalToBorderBoxTransform() float scale = style()->effectiveZoom(); FloatPoint translate = svg->currentTranslate(); LayoutSize borderAndPadding(borderLeft() + paddingLeft(), borderTop() + paddingTop()); - m_localToBorderBoxTransform = svg->viewBoxToViewTransform(width() / scale, height() / scale); + m_localToBorderBoxTransform = svg->viewBoxToViewTransform(contentWidth() / scale, contentHeight() / scale); if (borderAndPadding.isEmpty() && scale == 1 && translate == FloatPoint::zero()) return; m_localToBorderBoxTransform = AffineTransform(scale, 0, 0, scale, borderAndPadding.width() + translate.x(), borderAndPadding.height() + translate.y()) * m_localToBorderBoxTransform; diff --git a/Source/WebCore/rendering/svg/RenderSVGRoot.h b/Source/WebCore/rendering/svg/RenderSVGRoot.h index cb7a1b2e0..701137f44 100644 --- a/Source/WebCore/rendering/svg/RenderSVGRoot.h +++ b/Source/WebCore/rendering/svg/RenderSVGRoot.h @@ -56,7 +56,6 @@ public: private: virtual RenderObjectChildList* virtualChildren() { return children(); } virtual const RenderObjectChildList* virtualChildren() const { return children(); } - virtual bool canHaveChildren() const { return true; } virtual bool isSVGRoot() const { return true; } virtual const char* renderName() const { return "RenderSVGRoot"; } @@ -87,6 +86,7 @@ private: virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool useTransforms, bool fixed, TransformState&, bool* wasFixed = 0) const; virtual bool canBeSelectionLeaf() const { return false; } + virtual bool canHaveChildren() const { return true; } void updateCachedBoundaries(); void buildLocalToBorderBoxTransform(); diff --git a/Source/WebCore/rendering/svg/RenderSVGText.cpp b/Source/WebCore/rendering/svg/RenderSVGText.cpp index ebf92e569..d9cdeccdf 100644 --- a/Source/WebCore/rendering/svg/RenderSVGText.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGText.cpp @@ -58,6 +58,7 @@ RenderSVGText::RenderSVGText(SVGTextElement* node) , m_needsReordering(false) , m_needsPositioningValuesUpdate(true) , m_needsTransformUpdate(true) + , m_needsTextMetricsUpdate(true) { } @@ -208,11 +209,13 @@ void RenderSVGText::layout() updateCachedBoundariesInParents = true; } - // If the root layout size changed (eg. window size changes) or the positioning values change, recompute the on-screen font size. - if (SVGRenderSupport::findTreeRootObject(this)->isLayoutSizeChanged()) { + // If the root layout size changed (eg. window size changes) or the positioning values change + // or the transform to the root context has changed then recompute the on-screen font size. + if (m_needsTextMetricsUpdate || SVGRenderSupport::findTreeRootObject(this)->isLayoutSizeChanged()) { recursiveUpdateScaledFont(this); rebuildLayoutAttributes(true); updateCachedBoundariesInParents = true; + m_needsTextMetricsUpdate = false; } if (m_needsPositioningValuesUpdate) { diff --git a/Source/WebCore/rendering/svg/RenderSVGText.h b/Source/WebCore/rendering/svg/RenderSVGText.h index 864101695..7b0b5efa8 100644 --- a/Source/WebCore/rendering/svg/RenderSVGText.h +++ b/Source/WebCore/rendering/svg/RenderSVGText.h @@ -41,6 +41,7 @@ public: void setNeedsPositioningValuesUpdate() { m_needsPositioningValuesUpdate = true; } virtual void setNeedsTransformUpdate() { m_needsTransformUpdate = true; } + void setNeedsTextMetricsUpdate() { m_needsTextMetricsUpdate = true; } virtual FloatRect repaintRectInLocalCoordinates() const; static RenderSVGText* locateRenderSVGTextAncestor(RenderObject*); @@ -90,6 +91,7 @@ private: bool m_needsReordering : 1; bool m_needsPositioningValuesUpdate : 1; bool m_needsTransformUpdate : 1; + bool m_needsTextMetricsUpdate : 1; AffineTransform m_localTransform; SVGTextLayoutAttributesBuilder m_layoutAttributesBuilder; Vector<SVGTextLayoutAttributes*> m_layoutAttributes; diff --git a/Source/WebCore/rendering/svg/RenderSVGTransformableContainer.cpp b/Source/WebCore/rendering/svg/RenderSVGTransformableContainer.cpp index 1db6365b2..0a62f6885 100644 --- a/Source/WebCore/rendering/svg/RenderSVGTransformableContainer.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGTransformableContainer.cpp @@ -25,6 +25,7 @@ #include "RenderSVGTransformableContainer.h" #include "SVGNames.h" +#include "SVGRenderSupport.h" #include "SVGShadowTreeElements.h" #include "SVGStyledTransformableElement.h" @@ -33,6 +34,7 @@ namespace WebCore { RenderSVGTransformableContainer::RenderSVGTransformableContainer(SVGStyledTransformableElement* node) : RenderSVGContainer(node) , m_needsTransformUpdate(true) + , m_didTransformToRootUpdate(false) { } @@ -41,6 +43,7 @@ bool RenderSVGTransformableContainer::calculateLocalTransform() SVGStyledTransformableElement* element = static_cast<SVGStyledTransformableElement*>(node()); bool needsUpdate = m_needsTransformUpdate; + m_didTransformToRootUpdate = m_needsTransformUpdate || SVGRenderSupport::transformToRootChanged(parent()); if (needsUpdate) { m_localTransform = element->animatedLocalTransform(); m_needsTransformUpdate = false; diff --git a/Source/WebCore/rendering/svg/RenderSVGTransformableContainer.h b/Source/WebCore/rendering/svg/RenderSVGTransformableContainer.h index 401bfa858..c9c607ba2 100644 --- a/Source/WebCore/rendering/svg/RenderSVGTransformableContainer.h +++ b/Source/WebCore/rendering/svg/RenderSVGTransformableContainer.h @@ -31,14 +31,17 @@ class RenderSVGTransformableContainer : public RenderSVGContainer { public: explicit RenderSVGTransformableContainer(SVGStyledTransformableElement*); + virtual bool isSVGTransformableContainer() const { return true; } virtual const AffineTransform& localToParentTransform() const { return m_localTransform; } virtual void setNeedsTransformUpdate() { m_needsTransformUpdate = true; } + virtual bool didTransformToRootUpdate() { return m_didTransformToRootUpdate; } private: virtual bool calculateLocalTransform(); virtual AffineTransform localTransform() const { return m_localTransform; } bool m_needsTransformUpdate : 1; + bool m_didTransformToRootUpdate : 1; AffineTransform m_localTransform; }; } diff --git a/Source/WebCore/rendering/svg/RenderSVGViewportContainer.cpp b/Source/WebCore/rendering/svg/RenderSVGViewportContainer.cpp index 1021aff00..3e0e3e4d9 100644 --- a/Source/WebCore/rendering/svg/RenderSVGViewportContainer.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGViewportContainer.cpp @@ -34,7 +34,9 @@ namespace WebCore { RenderSVGViewportContainer::RenderSVGViewportContainer(SVGStyledElement* node) : RenderSVGContainer(node) + , m_didTransformToRootUpdate(false) , m_isLayoutSizeChanged(false) + , m_needsTransformUpdate(true) { } @@ -63,8 +65,21 @@ void RenderSVGViewportContainer::calcViewport() SVGLengthContext lengthContext(element); m_viewport = FloatRect(svg->x().value(lengthContext), svg->y().value(lengthContext), svg->width().value(lengthContext), svg->height().value(lengthContext)); - if (oldViewport != m_viewport) + if (oldViewport != m_viewport) { + m_didTransformToRootUpdate = true; setNeedsBoundariesUpdate(); + setNeedsTransformUpdate(); + } +} + +bool RenderSVGViewportContainer::calculateLocalTransform() +{ + if (!m_needsTransformUpdate) + return false; + + m_localToParentTransform = AffineTransform::translation(m_viewport.x(), m_viewport.y()) * viewportTransform(); + m_needsTransformUpdate = false; + return true; } AffineTransform RenderSVGViewportContainer::viewportTransform() const @@ -77,14 +92,6 @@ AffineTransform RenderSVGViewportContainer::viewportTransform() const return AffineTransform(); } -const AffineTransform& RenderSVGViewportContainer::localToParentTransform() const -{ - m_localToParentTransform = AffineTransform::translation(m_viewport.x(), m_viewport.y()) * viewportTransform(); - return m_localToParentTransform; - // If this class were ever given a localTransform(), then the above would read: - // return viewportTranslation * localTransform() * viewportTransform() -} - bool RenderSVGViewportContainer::pointIsInsideViewportClip(const FloatPoint& pointInParent) { // Respect the viewport clip (which is in parent coords) diff --git a/Source/WebCore/rendering/svg/RenderSVGViewportContainer.h b/Source/WebCore/rendering/svg/RenderSVGViewportContainer.h index 808d6727b..b748fe6f0 100644 --- a/Source/WebCore/rendering/svg/RenderSVGViewportContainer.h +++ b/Source/WebCore/rendering/svg/RenderSVGViewportContainer.h @@ -36,8 +36,10 @@ public: FloatRect viewport() const { return m_viewport; } bool isLayoutSizeChanged() const { return m_isLayoutSizeChanged; } + virtual bool didTransformToRootUpdate() { return m_didTransformToRootUpdate; } virtual void determineIfLayoutSizeChanged(); + virtual void setNeedsTransformUpdate() { m_needsTransformUpdate = true; } private: virtual bool isSVGContainer() const { return true; } @@ -45,16 +47,19 @@ private: virtual const char* renderName() const { return "RenderSVGViewportContainer"; } AffineTransform viewportTransform() const; - virtual const AffineTransform& localToParentTransform() const; + virtual const AffineTransform& localToParentTransform() const { return m_localToParentTransform; } virtual void calcViewport(); + virtual bool calculateLocalTransform(); virtual void applyViewportClip(PaintInfo&); virtual bool pointIsInsideViewportClip(const FloatPoint& pointInParent); FloatRect m_viewport; mutable AffineTransform m_localToParentTransform; + bool m_didTransformToRootUpdate : 1; bool m_isLayoutSizeChanged : 1; + bool m_needsTransformUpdate : 1; }; inline RenderSVGViewportContainer* toRenderSVGViewportContainer(RenderObject* object) diff --git a/Source/WebCore/rendering/svg/SVGRenderSupport.cpp b/Source/WebCore/rendering/svg/SVGRenderSupport.cpp index 6457ac006..7feb88fec 100644 --- a/Source/WebCore/rendering/svg/SVGRenderSupport.cpp +++ b/Source/WebCore/rendering/svg/SVGRenderSupport.cpp @@ -39,6 +39,7 @@ #include "RenderSVGResourceMarker.h" #include "RenderSVGResourceMasker.h" #include "RenderSVGRoot.h" +#include "RenderSVGText.h" #include "RenderSVGViewportContainer.h" #include "SVGResources.h" #include "SVGResourcesCache.h" @@ -79,6 +80,13 @@ void SVGRenderSupport::mapLocalToContainer(const RenderObject* object, RenderBox object->parent()->mapLocalToContainer(repaintContainer, false, true, transformState, wasFixed); } +static inline bool isRenderingMaskImage(RenderObject* object) +{ + if (object->frame() && object->frame()->view()) + return object->frame()->view()->paintBehavior() & PaintBehaviorRenderingSVGMask; + return false; +} + bool SVGRenderSupport::prepareToRenderSVGContent(RenderObject* object, PaintInfo& paintInfo) { ASSERT(object); @@ -89,11 +97,8 @@ bool SVGRenderSupport::prepareToRenderSVGContent(RenderObject* object, PaintInfo const SVGRenderStyle* svgStyle = style->svgStyle(); ASSERT(svgStyle); - bool isRenderingMask = false; - if (object->frame() && object->frame()->view()) - isRenderingMask = object->frame()->view()->paintBehavior() & PaintBehaviorRenderingSVGMask; - // Setup transparency layers before setting up SVG resources! + bool isRenderingMask = isRenderingMaskImage(object); float opacity = isRenderingMask ? 1 : style->opacity(); const ShadowData* shadow = svgStyle->shadow(); if (opacity < 1 || shadow) { @@ -168,7 +173,7 @@ void SVGRenderSupport::finishRenderSVGContent(RenderObject* object, PaintInfo& p } #endif - if (style->opacity() < 1) + if (style->opacity() < 1 && !isRenderingMaskImage(object)) paintInfo.context->endTransparencyLayer(); if (svgStyle->shadow()) @@ -245,14 +250,35 @@ static inline bool layoutSizeOfNearestViewportChanged(const RenderObject* start) return toRenderSVGRoot(start)->isLayoutSizeChanged(); } +bool SVGRenderSupport::transformToRootChanged(RenderObject* ancestor) +{ + while (ancestor && !ancestor->isSVGRoot()) { + if (ancestor->isSVGTransformableContainer()) + return toRenderSVGContainer(ancestor)->didTransformToRootUpdate(); + if (ancestor->isSVGViewportContainer()) + return toRenderSVGViewportContainer(ancestor)->didTransformToRootUpdate(); + ancestor = ancestor->parent(); + } + + return false; +} + void SVGRenderSupport::layoutChildren(RenderObject* start, bool selfNeedsLayout) { bool layoutSizeChanged = layoutSizeOfNearestViewportChanged(start); + bool transformChanged = transformToRootChanged(start); HashSet<RenderObject*> notlayoutedObjects; for (RenderObject* child = start->firstChild(); child; child = child->nextSibling()) { bool needsLayout = selfNeedsLayout; + if (transformChanged) { + // If the transform changed we need to update the text metrics (note: this also happens for layoutSizeChanged=true). + if (child->isSVGText()) + toRenderSVGText(child)->setNeedsTextMetricsUpdate(); + needsLayout = true; + } + if (layoutSizeChanged) { // When selfNeedsLayout is false and the layout size changed, we have to check whether this child uses relative lengths if (SVGElement* element = child->node()->isSVGElement() ? static_cast<SVGElement*>(child->node()) : 0) { @@ -260,6 +286,8 @@ void SVGRenderSupport::layoutChildren(RenderObject* start, bool selfNeedsLayout) // When the layout size changed and when using relative values tell the RenderSVGShape to update its shape object if (child->isSVGShape()) toRenderSVGShape(child)->setNeedsShapeUpdate(); + else if (child->isSVGText()) + toRenderSVGText(child)->setNeedsPositioningValuesUpdate(); needsLayout = true; } diff --git a/Source/WebCore/rendering/svg/SVGRenderSupport.h b/Source/WebCore/rendering/svg/SVGRenderSupport.h index f5280ff24..c7b2fdcbf 100644 --- a/Source/WebCore/rendering/svg/SVGRenderSupport.h +++ b/Source/WebCore/rendering/svg/SVGRenderSupport.h @@ -72,6 +72,9 @@ public: // Shared between SVG renderers and resources. static void applyStrokeStyleToContext(GraphicsContext*, const RenderStyle*, const RenderObject*); + // Determines if any ancestor's transform has changed. + static bool transformToRootChanged(RenderObject*); + // FIXME: These methods do not belong here. static const RenderSVGRoot* findTreeRootObject(const RenderObject*); diff --git a/Source/WebCore/rendering/svg/SVGTextLayoutAttributesBuilder.cpp b/Source/WebCore/rendering/svg/SVGTextLayoutAttributesBuilder.cpp index a27f68cd7..02a2123eb 100644 --- a/Source/WebCore/rendering/svg/SVGTextLayoutAttributesBuilder.cpp +++ b/Source/WebCore/rendering/svg/SVGTextLayoutAttributesBuilder.cpp @@ -79,12 +79,12 @@ void SVGTextLayoutAttributesBuilder::rebuildMetricsForWholeTree(RenderSVGText* t bool SVGTextLayoutAttributesBuilder::buildLayoutAttributesIfNeeded(RenderSVGText* textRoot) { ASSERT(textRoot); - if (!m_textPositions.isEmpty()) - return m_textLength; - m_textLength = 0; - const UChar* lastCharacter = 0; - collectTextPositioningElements(textRoot, lastCharacter); + if (m_textPositions.isEmpty()) { + m_textLength = 0; + const UChar* lastCharacter = 0; + collectTextPositioningElements(textRoot, lastCharacter); + } m_characterDataMap.clear(); if (!m_textLength) |
