diff options
Diffstat (limited to 'Source/WebCore/rendering')
103 files changed, 1196 insertions, 1057 deletions
diff --git a/Source/WebCore/rendering/HitTestResult.cpp b/Source/WebCore/rendering/HitTestResult.cpp index 0f6e4b916..44b17478f 100644 --- a/Source/WebCore/rendering/HitTestResult.cpp +++ b/Source/WebCore/rendering/HitTestResult.cpp @@ -67,7 +67,7 @@ HitTestPoint::HitTestPoint(const LayoutPoint& point) } HitTestPoint::HitTestPoint(const FloatPoint& point) - : m_point(roundedLayoutPoint(point)) + : m_point(flooredLayoutPoint(point)) , m_boundingBox(rectForPoint(m_point, 0, 0, 0, 0)) , m_transformedPoint(point) , m_transformedRect(m_boundingBox) @@ -83,7 +83,7 @@ HitTestPoint::HitTestPoint(const FloatPoint& point, const FloatQuad& quad) , m_region(0) , m_isRectBased(true) { - m_point = roundedLayoutPoint(point); + m_point = flooredLayoutPoint(point); m_boundingBox = enclosingIntRect(quad.boundingBox()); m_isRectilinear = quad.isRectilinear(); } @@ -181,7 +181,7 @@ bool HitTestPoint::intersects(const FloatRect& rect) const IntRect HitTestPoint::rectForPoint(const LayoutPoint& point, unsigned topPadding, unsigned rightPadding, unsigned bottomPadding, unsigned leftPadding) { - IntPoint actualPoint(roundedIntPoint(point)); + IntPoint actualPoint(flooredIntPoint(point)); actualPoint -= IntSize(leftPadding, topPadding); IntSize actualPadding(leftPadding + rightPadding, topPadding + bottomPadding); diff --git a/Source/WebCore/rendering/HitTestingTransformState.cpp b/Source/WebCore/rendering/HitTestingTransformState.cpp index b089336ab..6d9cc7629 100644 --- a/Source/WebCore/rendering/HitTestingTransformState.cpp +++ b/Source/WebCore/rendering/HitTestingTransformState.cpp @@ -79,7 +79,7 @@ FloatQuad HitTestingTransformState::mappedArea() const return m_accumulatedTransform.inverse().projectQuad(m_lastPlanarArea); } -LayoutRect HitTestingTransformState::boundsOfMappedArea() const +FractionalLayoutRect HitTestingTransformState::boundsOfMappedArea() const { return m_accumulatedTransform.inverse().clampedBoundsOfProjectedQuad(m_lastPlanarArea); } diff --git a/Source/WebCore/rendering/HitTestingTransformState.h b/Source/WebCore/rendering/HitTestingTransformState.h index 95ec25b5f..b58303850 100644 --- a/Source/WebCore/rendering/HitTestingTransformState.h +++ b/Source/WebCore/rendering/HitTestingTransformState.h @@ -59,7 +59,7 @@ public: FloatPoint mappedPoint() const; FloatQuad mappedQuad() const; FloatQuad mappedArea() const; - LayoutRect boundsOfMappedArea() const; + FractionalLayoutRect boundsOfMappedArea() const; void flatten(); FloatPoint m_lastPlanarPoint; diff --git a/Source/WebCore/rendering/LayoutTypes.h b/Source/WebCore/rendering/LayoutTypes.h index 95055f8eb..51967f8e9 100644 --- a/Source/WebCore/rendering/LayoutTypes.h +++ b/Source/WebCore/rendering/LayoutTypes.h @@ -91,17 +91,12 @@ inline LayoutPoint roundedLayoutPoint(const FloatPoint& p) inline LayoutPoint flooredLayoutPoint(const FloatPoint& p) { - return LayoutPoint(p.x(), p.y()); + return flooredFractionalLayoutPoint(p); } inline LayoutPoint flooredLayoutPoint(const FloatSize& s) { - return LayoutPoint(s.width(), s.height()); -} - -inline LayoutSize flooredLayoutSize(const FloatPoint& p) -{ - return LayoutSize(p.x(), p.y()); + return flooredLayoutPoint(FloatPoint(s)); } inline int roundToInt(LayoutUnit value) @@ -111,7 +106,7 @@ inline int roundToInt(LayoutUnit value) inline int floorToInt(LayoutUnit value) { - return value.toInt(); + return value.floor(); } inline LayoutUnit roundedLayoutUnit(float value) @@ -149,12 +144,7 @@ inline LayoutPoint toLayoutPoint(const LayoutSize& p) inline LayoutUnit layoutMod(const LayoutUnit& numerator, const LayoutUnit& denominator) { - return numerator.toInt() % denominator.toInt(); -} - -inline LayoutUnit clampToLayoutUnit(double value) -{ - return clampTo<FractionalLayoutUnit>(value, FractionalLayoutUnit::min(), FractionalLayoutUnit::max()); + return numerator % denominator; } inline IntSize pixelSnappedIntSize(const FractionalLayoutSize& s, const FractionalLayoutPoint& p) @@ -169,7 +159,7 @@ inline IntRect pixelSnappedIntRect(LayoutPoint location, LayoutSize size) inline bool isIntegerValue(const LayoutUnit value) { - return value.floor() == value; + return value.toInt() == value; } } // namespace WebCore diff --git a/Source/WebCore/rendering/RenderBlock.cpp b/Source/WebCore/rendering/RenderBlock.cpp index 0e4a77a78..c2509065e 100755 --- a/Source/WebCore/rendering/RenderBlock.cpp +++ b/Source/WebCore/rendering/RenderBlock.cpp @@ -71,7 +71,7 @@ namespace WebCore { using namespace HTMLNames; struct SameSizeAsRenderBlock : public RenderBox { - void* pointers[3]; + void* pointers[2]; RenderObjectChildList children; RenderLineBoxList lineBoxes; uint32_t bitfields; @@ -96,11 +96,11 @@ struct SameSizeAsMarginInfo { typedef WTF::HashMap<const RenderBox*, ColumnInfo*> ColumnInfoMap; static ColumnInfoMap* gColumnInfoMap = 0; -typedef WTF::HashMap<const RenderBlock*, HashSet<RenderBox*>*> PercentHeightDescendantsMap; -static PercentHeightDescendantsMap* gPercentHeightDescendantsMap = 0; +static TrackedDescendantsMap* gPositionedDescendantsMap = 0; +static TrackedDescendantsMap* gPercentHeightDescendantsMap = 0; -typedef WTF::HashMap<const RenderBox*, HashSet<RenderBlock*>*> PercentHeightContainerMap; -static PercentHeightContainerMap* gPercentHeightContainerMap = 0; +static TrackedContainerMap* gPositionedContainerMap = 0; +static TrackedContainerMap* gPercentHeightContainerMap = 0; typedef WTF::HashMap<RenderBlock*, ListHashSet<RenderInline*>*> ContinuationOutlineTableMap; @@ -196,6 +196,26 @@ RenderBlock::RenderBlock(Node* node) COMPILE_ASSERT(sizeof(RenderBlock::MarginInfo) == sizeof(SameSizeAsMarginInfo), MarginInfo_should_stay_small); } +static void removeBlockFromDescendantAndContainerMaps(RenderBlock* block, TrackedDescendantsMap*& descendantMap, TrackedContainerMap*& containerMap) +{ + if (TrackedRendererListHashSet* descendantSet = descendantMap->take(block)) { + TrackedRendererListHashSet::iterator end = descendantSet->end(); + for (TrackedRendererListHashSet::iterator descendant = descendantSet->begin(); descendant != end; ++descendant) { + HashSet<RenderBlock*>* containerSet = containerMap->get(*descendant); + ASSERT(containerSet); + if (!containerSet) + continue; + ASSERT(containerSet->contains(block)); + containerSet->remove(block); + if (containerSet->isEmpty()) { + containerMap->remove(*descendant); + delete containerSet; + } + } + delete descendantSet; + } +} + RenderBlock::~RenderBlock() { if (m_floatingObjects) @@ -204,24 +224,10 @@ RenderBlock::~RenderBlock() if (hasColumns()) delete gColumnInfoMap->take(this); - if (gPercentHeightDescendantsMap) { - if (HashSet<RenderBox*>* descendantSet = gPercentHeightDescendantsMap->take(this)) { - HashSet<RenderBox*>::iterator end = descendantSet->end(); - for (HashSet<RenderBox*>::iterator descendant = descendantSet->begin(); descendant != end; ++descendant) { - HashSet<RenderBlock*>* containerSet = gPercentHeightContainerMap->get(*descendant); - ASSERT(containerSet); - if (!containerSet) - continue; - ASSERT(containerSet->contains(this)); - containerSet->remove(this); - if (containerSet->isEmpty()) { - gPercentHeightContainerMap->remove(*descendant); - delete containerSet; - } - } - delete descendantSet; - } - } + if (gPercentHeightDescendantsMap) + removeBlockFromDescendantAndContainerMaps(this, gPercentHeightDescendantsMap, gPercentHeightContainerMap); + if (gPositionedDescendantsMap) + removeBlockFromDescendantAndContainerMaps(this, gPositionedDescendantsMap, gPositionedContainerMap); } void RenderBlock::willBeDestroyed() @@ -1139,15 +1145,21 @@ void RenderBlock::collapseAnonymousBoxChild(RenderBlock* parent, RenderObject* c 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 (!parent->documentBeingDestroyed() && childFlowThread && childFlowThread->isRenderNamedFlowThread()) + anonBlock->deleteLineBoxTree(); + if (childFlowThread && childFlowThread->isRenderNamedFlowThread()) toRenderNamedFlowThread(childFlowThread)->removeFlowChildInfo(anonBlock); anonBlock->destroy(); } void RenderBlock::removeChild(RenderObject* oldChild) { + // No need to waste time in merging or removing empty anonymous blocks. + // We can just bail out if our document is getting destroyed. + if (documentBeingDestroyed()) { + RenderBox::removeChild(oldChild); + return; + } + // If this child is a block, and if our previous and next siblings are // both anonymous blocks with inline content, then we can go ahead and // fold the inline content back together. @@ -1169,12 +1181,14 @@ void RenderBlock::removeChild(RenderObject* oldChild) // column span flag if it is set. ASSERT(!inlineChildrenBlock->continuation()); RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(style(), BLOCK); - children()->removeChildNode(this, inlineChildrenBlock, inlineChildrenBlock->hasLayer()); + // Cache this value as it might get changed in setStyle() call. + bool inlineChildrenBlockHasLayer = inlineChildrenBlock->hasLayer(); inlineChildrenBlock->setStyle(newStyle); + children()->removeChildNode(this, inlineChildrenBlock, inlineChildrenBlockHasLayer); // Now just put the inlineChildrenBlock inside the blockChildrenBlock. blockChildrenBlock->children()->insertChildNode(blockChildrenBlock, inlineChildrenBlock, prev == inlineChildrenBlock ? blockChildrenBlock->firstChild() : 0, - inlineChildrenBlock->hasLayer() || blockChildrenBlock->hasLayer()); + inlineChildrenBlockHasLayer || blockChildrenBlock->hasLayer()); next->setNeedsLayoutAndPrefWidthsRecalc(); // inlineChildrenBlock got reparented to blockChildrenBlock, so it is no longer a child @@ -1215,14 +1229,14 @@ void RenderBlock::removeChild(RenderObject* oldChild) } } - if (!firstChild() && !documentBeingDestroyed()) { + if (!firstChild()) { // If this was our last child be sure to clear out our line boxes. if (childrenInline()) deleteLineBoxTree(); // If we are an empty anonymous block in the continuation chain, // we need to remove ourself and fix the continuation chain. - if (!beingDestroyed() && isAnonymousBlockContinuation()) { + if (!beingDestroyed() && isAnonymousBlockContinuation() && !oldChild->isListMarker()) { RenderObject* containingBlockIgnoringAnonymous = containingBlock(); while (containingBlockIgnoringAnonymous && containingBlockIgnoringAnonymous->isAnonymousBlock()) containingBlockIgnoringAnonymous = containingBlockIgnoringAnonymous->containingBlock(); @@ -1418,7 +1432,7 @@ void RenderBlock::layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeigh if (!relayoutChildren && simplifiedLayout()) return; - LayoutRepainter repainter(*this, everHadLayout() && checkForRepaintDuringLayout()); + LayoutRepainter repainter(*this, checkForRepaintDuringLayout()); if (recomputeLogicalWidth()) relayoutChildren = true; @@ -1472,14 +1486,6 @@ void RenderBlock::layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeigh setPaginationStrut(0); } - // For overflow:scroll blocks, ensure we have both scrollbars in place always. - if (scrollsOverflow() && style()->appearance() != ListboxPart) { - if (styleToUse->overflowX() == OSCROLL) - layer()->setHasHorizontalScrollbar(true); - if (styleToUse->overflowY() == OSCROLL) - layer()->setHasVerticalScrollbar(true); - } - LayoutUnit repaintLogicalTop = ZERO_LAYOUT_UNIT; LayoutUnit repaintLogicalBottom = ZERO_LAYOUT_UNIT; LayoutUnit maxFloatLogicalBottom = ZERO_LAYOUT_UNIT; @@ -1660,17 +1666,22 @@ void RenderBlock::addOverflowFromFloats() void RenderBlock::addOverflowFromPositionedObjects() { - if (!m_positionedObjects) + TrackedRendererListHashSet* positionedDescendants = positionedObjects(); + if (!positionedDescendants) return; RenderBox* positionedObject; - Iterator end = m_positionedObjects->end(); - for (Iterator it = m_positionedObjects->begin(); it != end; ++it) { + TrackedRendererListHashSet::iterator end = positionedDescendants->end(); + for (TrackedRendererListHashSet::iterator it = positionedDescendants->begin(); it != end; ++it) { positionedObject = *it; // Fixed positioned elements don't contribute to layout overflow, since they don't scroll with the content. - if (positionedObject->style()->position() != FixedPosition) - addOverflowFromChild(positionedObject, IntSize(positionedObject->x(), positionedObject->y())); + if (positionedObject->style()->position() != FixedPosition) { + LayoutUnit x = positionedObject->x(); + if (style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft()) + x -= verticalScrollbarWidth(); + addOverflowFromChild(positionedObject, LayoutSize(x, positionedObject->y())); + } } } @@ -1699,18 +1710,11 @@ void RenderBlock::adjustPositionedBlock(RenderBox* child, const MarginInfo& marg setStaticInlinePositionForChild(child, logicalTop, startOffsetForContent(logicalTop)); if (!marginInfo.canCollapseWithMarginBefore()) { - child->computeBlockDirectionMargins(this); - LayoutUnit marginBefore = marginBeforeForChild(child); + // Positioned blocks don't collapse margins, so add the margin provided by + // the container now. The child's own margin is added later when calculating its logical top. LayoutUnit collapsedBeforePos = marginInfo.positiveMargin(); LayoutUnit collapsedBeforeNeg = marginInfo.negativeMargin(); - if (marginBefore > 0) { - if (marginBefore > collapsedBeforePos) - collapsedBeforePos = marginBefore; - } else { - if (-marginBefore > collapsedBeforeNeg) - collapsedBeforeNeg = -marginBefore; - } - logicalTop += (collapsedBeforePos - collapsedBeforeNeg) - marginBefore; + logicalTop += collapsedBeforePos - collapsedBeforeNeg; } RenderLayer* childLayer = child->layer(); @@ -1849,11 +1853,7 @@ void RenderBlock::moveRunInUnderSiblingBlockIfNeeded(RenderObject* runIn) // Check if this node is allowed to run-in. E.g. <select> expects its renderer to // be a RenderListBox or RenderMenuList, and hence cannot be a RenderInline run-in. - Node* runInNode = runIn->node(); - if (runInNode && runInNode->hasTagName(selectTag)) - return; - - if (runInNode && runInNode->hasTagName(progressTag)) + if (!runIn->canBeReplacedWithInlineRunIn()) return; RenderObject* curr = runIn->nextSibling(); @@ -2204,6 +2204,8 @@ LayoutUnit RenderBlock::computeStartPositionDeltaForChildAvoidingFloats(const Re void RenderBlock::determineLogicalLeftPositionForChild(RenderBox* child) { LayoutUnit startPosition = borderStart() + paddingStart(); + if (style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft()) + startPosition -= verticalScrollbarWidth(); LayoutUnit totalAvailableLogicalWidth = borderAndPaddingLogicalWidth() + availableLogicalWidth(); // Add in our start margin. @@ -2285,9 +2287,9 @@ void RenderBlock::setLogicalTopForChild(RenderBox* child, LayoutUnit logicalTop, void RenderBlock::layoutBlockChildren(bool relayoutChildren, LayoutUnit& maxFloatLogicalBottom) { if (gPercentHeightDescendantsMap) { - if (HashSet<RenderBox*>* descendants = gPercentHeightDescendantsMap->get(this)) { - HashSet<RenderBox*>::iterator end = descendants->end(); - for (HashSet<RenderBox*>::iterator it = descendants->begin(); it != end; ++it) { + if (TrackedRendererListHashSet* descendants = gPercentHeightDescendantsMap->get(this)) { + TrackedRendererListHashSet::iterator end = descendants->end(); + for (TrackedRendererListHashSet::iterator it = descendants->begin(); it != end; ++it) { RenderBox* box = *it; while (box != this) { if (box->normalChildNeedsLayout()) @@ -2566,15 +2568,16 @@ bool RenderBlock::simplifiedLayout() void RenderBlock::layoutPositionedObjects(bool relayoutChildren) { - if (!m_positionedObjects) + TrackedRendererListHashSet* positionedDescendants = positionedObjects(); + if (!positionedDescendants) return; if (hasColumns()) view()->layoutState()->clearPaginationInformation(); // Positioned objects are not part of the column flow, so they don't paginate with the columns. RenderBox* r; - Iterator end = m_positionedObjects->end(); - for (Iterator it = m_positionedObjects->begin(); it != end; ++it) { + TrackedRendererListHashSet::iterator end = positionedDescendants->end(); + for (TrackedRendererListHashSet::iterator it = positionedDescendants->begin(); it != end; ++it) { r = *it; // When a non-positioned block element moves, it may have positioned children that are implicitly positioned relative to the // non-positioned block. Rather than trying to detect all of these movement cases, we just always lay out positioned @@ -2630,10 +2633,11 @@ void RenderBlock::layoutPositionedObjects(bool relayoutChildren) void RenderBlock::markPositionedObjectsForLayout() { - if (m_positionedObjects) { + TrackedRendererListHashSet* positionedDescendants = positionedObjects(); + if (positionedDescendants) { RenderBox* r; - Iterator end = m_positionedObjects->end(); - for (Iterator it = m_positionedObjects->begin(); it != end; ++it) { + TrackedRendererListHashSet::iterator end = positionedDescendants->end(); + for (TrackedRendererListHashSet::iterator it = positionedDescendants->begin(); it != end; ++it) { r = *it; r->setChildNeedsLayout(true); } @@ -2969,11 +2973,8 @@ 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()) { + if (hasOverflowClip()) scrolledOffset.move(-scrolledContentOffset()); - if (style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft()) - scrolledOffset.move(verticalScrollbarWidth(), 0); - } // 2. paint contents if (paintPhase != PaintPhaseSelfOutline) { @@ -3220,7 +3221,7 @@ GapRects RenderBlock::selectionGapRectsForRepaint(RenderBoxModelObject* repaintC // FIXME: this is broken with transforms TransformState transformState(TransformState::ApplyTransformDirection, FloatPoint()); - mapLocalToContainer(repaintContainer, false, false, transformState); + mapLocalToContainer(repaintContainer, transformState); LayoutPoint offsetFromRepaintContainer = roundedLayoutPoint(transformState.mappedPoint()); if (hasOverflowClip()) @@ -3258,13 +3259,13 @@ void RenderBlock::paintSelection(PaintInfo& paintInfo, const LayoutPoint& paintO } } -static void clipOutPositionedObjects(const PaintInfo* paintInfo, const LayoutPoint& offset, RenderBlock::PositionedObjectsListHashSet* positionedObjects) +static void clipOutPositionedObjects(const PaintInfo* paintInfo, const LayoutPoint& offset, TrackedRendererListHashSet* positionedObjects) { if (!positionedObjects) return; - RenderBlock::PositionedObjectsListHashSet::const_iterator end = positionedObjects->end(); - for (RenderBlock::PositionedObjectsListHashSet::const_iterator it = positionedObjects->begin(); it != end; ++it) { + TrackedRendererListHashSet::const_iterator end = positionedObjects->end(); + for (TrackedRendererListHashSet::const_iterator it = positionedObjects->begin(); it != end; ++it) { RenderBox* r = *it; paintInfo->context->clipOut(IntRect(offset.x() + r->x(), offset.y() + r->y(), r->width(), r->height())); } @@ -3302,10 +3303,10 @@ GapRects RenderBlock::selectionGaps(RenderBlock* rootBlock, const LayoutPoint& r LayoutRect flippedBlockRect(offsetFromRootBlock.width(), offsetFromRootBlock.height(), width(), height()); rootBlock->flipForWritingMode(flippedBlockRect); flippedBlockRect.moveBy(rootBlockPhysicalPosition); - clipOutPositionedObjects(paintInfo, flippedBlockRect.location(), m_positionedObjects.get()); + clipOutPositionedObjects(paintInfo, flippedBlockRect.location(), positionedObjects()); if (isBody() || isRoot()) // The <body> must make sure to examine its containingBlock's positioned objects. for (RenderBlock* cb = containingBlock(); cb && !cb->isRenderView(); cb = cb->containingBlock()) - clipOutPositionedObjects(paintInfo, LayoutPoint(cb->x(), cb->y()), cb->m_positionedObjects.get()); // FIXME: Not right for flipped writing modes. + clipOutPositionedObjects(paintInfo, LayoutPoint(cb->x(), cb->y()), cb->positionedObjects()); // FIXME: Not right for flipped writing modes. if (m_floatingObjects) { const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); FloatingObjectSetIterator end = floatingObjectSet.end(); @@ -3596,6 +3597,74 @@ RenderBlock* RenderBlock::blockBeforeWithinSelectionRoot(LayoutSize& offset) con return beforeBlock; } +void RenderBlock::insertIntoTrackedRendererMaps(RenderBox* descendant, TrackedDescendantsMap*& descendantsMap, TrackedContainerMap*& containerMap) +{ + if (!descendantsMap) { + descendantsMap = new TrackedDescendantsMap; + containerMap = new TrackedContainerMap; + } + + TrackedRendererListHashSet* descendantSet = descendantsMap->get(this); + if (!descendantSet) { + descendantSet = new TrackedRendererListHashSet; + descendantsMap->set(this, descendantSet); + } + bool added = descendantSet->add(descendant).isNewEntry; + if (!added) { + ASSERT(containerMap->get(descendant)); + ASSERT(containerMap->get(descendant)->contains(this)); + return; + } + + HashSet<RenderBlock*>* containerSet = containerMap->get(descendant); + if (!containerSet) { + containerSet = new HashSet<RenderBlock*>; + containerMap->set(descendant, containerSet); + } + ASSERT(!containerSet->contains(this)); + containerSet->add(this); +} + +void RenderBlock::removeFromTrackedRendererMaps(RenderBox* descendant, TrackedDescendantsMap*& descendantsMap, TrackedContainerMap*& containerMap) +{ + if (!descendantsMap) + return; + + HashSet<RenderBlock*>* containerSet = containerMap->take(descendant); + if (!containerSet) + return; + + HashSet<RenderBlock*>::iterator end = containerSet->end(); + for (HashSet<RenderBlock*>::iterator it = containerSet->begin(); it != end; ++it) { + RenderBlock* container = *it; + + // FIXME: Disabling this assert temporarily until we fix the layout + // bugs associated with positioned objects not properly cleared from + // their ancestor chain before being moved. See webkit bug 93766. + // ASSERT(descendant->isDescendantOf(container)); + + TrackedRendererListHashSet* descendantSet = descendantsMap->get(container); + ASSERT(descendantSet); + if (!descendantSet) + continue; + ASSERT(descendantSet->contains(descendant)); + descendantSet->remove(descendant); + if (descendantSet->isEmpty()) { + descendantsMap->remove(container); + delete descendantSet; + } + } + + delete containerSet; +} + +TrackedRendererListHashSet* RenderBlock::positionedObjects() const +{ + if (gPositionedDescendantsMap) + return gPositionedDescendantsMap->get(this); + return 0; +} + void RenderBlock::insertPositionedObject(RenderBox* o) { ASSERT(!isAnonymousBlock()); @@ -3603,31 +3672,27 @@ void RenderBlock::insertPositionedObject(RenderBox* o) if (o->isRenderFlowThread()) return; - // Create the list of special objects if we don't aleady have one - if (!m_positionedObjects) - m_positionedObjects = adoptPtr(new PositionedObjectsListHashSet); - - m_positionedObjects->add(o); + insertIntoTrackedRendererMaps(o, gPositionedDescendantsMap, gPositionedContainerMap); } void RenderBlock::removePositionedObject(RenderBox* o) { - if (m_positionedObjects) - m_positionedObjects->remove(o); + removeFromTrackedRendererMaps(o, gPositionedDescendantsMap, gPositionedContainerMap); } void RenderBlock::removePositionedObjects(RenderBlock* o) { - if (!m_positionedObjects) + TrackedRendererListHashSet* positionedDescendants = positionedObjects(); + if (!positionedDescendants) return; RenderBox* r; - Iterator end = m_positionedObjects->end(); + TrackedRendererListHashSet::iterator end = positionedDescendants->end(); Vector<RenderBox*, 16> deadObjects; - for (Iterator it = m_positionedObjects->begin(); it != end; ++it) { + for (TrackedRendererListHashSet::iterator it = positionedDescendants->begin(); it != end; ++it) { r = *it; if (!o || r->isDescendantOf(o)) { if (o) @@ -3646,7 +3711,7 @@ void RenderBlock::removePositionedObjects(RenderBlock* o) } for (unsigned i = 0; i < deadObjects.size(); i++) - m_positionedObjects->remove(deadObjects.at(i)); + removePositionedObject(deadObjects.at(i)); } RenderBlock::FloatingObject* RenderBlock::insertFloatingObject(RenderBox* o) @@ -3924,60 +3989,15 @@ void RenderBlock::newLine(EClear clear) void RenderBlock::addPercentHeightDescendant(RenderBox* descendant) { - if (!gPercentHeightDescendantsMap) { - gPercentHeightDescendantsMap = new PercentHeightDescendantsMap; - gPercentHeightContainerMap = new PercentHeightContainerMap; - } - - HashSet<RenderBox*>* descendantSet = gPercentHeightDescendantsMap->get(this); - if (!descendantSet) { - descendantSet = new HashSet<RenderBox*>; - gPercentHeightDescendantsMap->set(this, descendantSet); - } - bool added = descendantSet->add(descendant).isNewEntry; - if (!added) { - ASSERT(gPercentHeightContainerMap->get(descendant)); - ASSERT(gPercentHeightContainerMap->get(descendant)->contains(this)); - return; - } - - HashSet<RenderBlock*>* containerSet = gPercentHeightContainerMap->get(descendant); - if (!containerSet) { - containerSet = new HashSet<RenderBlock*>; - gPercentHeightContainerMap->set(descendant, containerSet); - } - ASSERT(!containerSet->contains(this)); - containerSet->add(this); + insertIntoTrackedRendererMaps(descendant, gPercentHeightDescendantsMap, gPercentHeightContainerMap); } void RenderBlock::removePercentHeightDescendant(RenderBox* descendant) { - if (!gPercentHeightContainerMap) - return; - - HashSet<RenderBlock*>* containerSet = gPercentHeightContainerMap->take(descendant); - if (!containerSet) - return; - - HashSet<RenderBlock*>::iterator end = containerSet->end(); - for (HashSet<RenderBlock*>::iterator it = containerSet->begin(); it != end; ++it) { - RenderBlock* container = *it; - HashSet<RenderBox*>* descendantSet = gPercentHeightDescendantsMap->get(container); - ASSERT(descendantSet); - if (!descendantSet) - continue; - ASSERT(descendantSet->contains(descendant)); - descendantSet->remove(descendant); - if (descendantSet->isEmpty()) { - gPercentHeightDescendantsMap->remove(container); - delete descendantSet; - } - } - - delete containerSet; + removeFromTrackedRendererMaps(descendant, gPercentHeightDescendantsMap, gPercentHeightContainerMap); } -HashSet<RenderBox*>* RenderBlock::percentHeightDescendants() const +TrackedRendererListHashSet* RenderBlock::percentHeightDescendants() const { return gPercentHeightDescendantsMap ? gPercentHeightDescendantsMap->get(this) : 0; } @@ -6902,11 +6922,11 @@ LayoutUnit RenderBlock::pageRemainingLogicalHeightForOffset(LayoutUnit offset, P if (!inRenderFlowThread()) { LayoutUnit pageLogicalHeight = renderView->layoutState()->m_pageLogicalHeight; - LayoutUnit remainingHeight = pageLogicalHeight - layoutMod(offset, pageLogicalHeight); + LayoutUnit remainingHeight = pageLogicalHeight - intMod(offset, pageLogicalHeight); if (pageBoundaryRule == IncludePageBoundary) { // If includeBoundaryPoint is true the line exactly on the top edge of a // column will act as being part of the previous column. - remainingHeight = layoutMod(remainingHeight, pageLogicalHeight); + remainingHeight = intMod(remainingHeight, pageLogicalHeight); } return remainingHeight; } @@ -7438,9 +7458,12 @@ RenderBlock* RenderBlock::createAnonymousColumnSpanWithParentRenderer(const Rend #ifndef NDEBUG void RenderBlock::checkPositionedObjectsNeedLayout() { - if (PositionedObjectsListHashSet* positionedObjects = this->positionedObjects()) { - PositionedObjectsListHashSet::const_iterator end = positionedObjects->end(); - for (PositionedObjectsListHashSet::const_iterator it = positionedObjects->begin(); it != end; ++it) { + if (!gPositionedDescendantsMap) + return; + + if (TrackedRendererListHashSet* positionedDescendantSet = positionedObjects()) { + TrackedRendererListHashSet::const_iterator end = positionedDescendantSet->end(); + for (TrackedRendererListHashSet::const_iterator it = positionedDescendantSet->begin(); it != end; ++it) { RenderBox* currBox = *it; ASSERT(!currBox->needsLayout()); } diff --git a/Source/WebCore/rendering/RenderBlock.h b/Source/WebCore/rendering/RenderBlock.h index 53a1f202c..2c7fe3628 100644 --- a/Source/WebCore/rendering/RenderBlock.h +++ b/Source/WebCore/rendering/RenderBlock.h @@ -54,6 +54,9 @@ template <class Run> class BidiRunList; template <class Iterator> struct MidpointState; typedef BidiResolver<InlineIterator, BidiRun> InlineBidiResolver; typedef MidpointState<InlineIterator> LineMidpointState; +typedef WTF::ListHashSet<RenderBox*> TrackedRendererListHashSet; +typedef WTF::HashMap<const RenderBlock*, TrackedRendererListHashSet*> TrackedDescendantsMap; +typedef WTF::HashMap<const RenderBox*, HashSet<RenderBlock*>*> TrackedContainerMap; enum CaretType { CursorCaret, DragCaret }; @@ -99,16 +102,19 @@ public: virtual void layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeight = 0); void insertPositionedObject(RenderBox*); - void removePositionedObject(RenderBox*); + static void removePositionedObject(RenderBox*); void removePositionedObjects(RenderBlock*); - typedef ListHashSet<RenderBox*, 4> PositionedObjectsListHashSet; - PositionedObjectsListHashSet* positionedObjects() const { return m_positionedObjects.get(); } - bool hasPositionedObjects() const { return m_positionedObjects && !m_positionedObjects->isEmpty(); } + TrackedRendererListHashSet* positionedObjects() const; + bool hasPositionedObjects() const + { + TrackedRendererListHashSet* objects = positionedObjects(); + return objects && !objects->isEmpty(); + } void addPercentHeightDescendant(RenderBox*); static void removePercentHeightDescendant(RenderBox*); - HashSet<RenderBox*>* percentHeightDescendants() const; + TrackedRendererListHashSet* percentHeightDescendants() const; static bool hasPercentHeightContainerMap(); static bool hasPercentHeightDescendant(RenderBox*); static void clearPercentHeightDescendantsFrom(RenderBox*); @@ -510,6 +516,9 @@ private: void layoutInlineChildren(bool relayoutChildren, LayoutUnit& repaintLogicalTop, LayoutUnit& repaintLogicalBottom); BidiRun* handleTrailingSpaces(BidiRunList<BidiRun>&, BidiContext*); + void insertIntoTrackedRendererMaps(RenderBox* descendant, TrackedDescendantsMap*&, TrackedContainerMap*&); + static void removeFromTrackedRendererMaps(RenderBox* descendant, TrackedDescendantsMap*&, TrackedContainerMap*&); + virtual void borderFitAdjust(LayoutRect&) const; // Shrink the box in which the border paints if border-fit is set. virtual void updateBeforeAfterContent(PseudoId); @@ -1068,9 +1077,6 @@ protected: const RenderBlock* m_renderer; }; OwnPtr<FloatingObjects> m_floatingObjects; - - typedef PositionedObjectsListHashSet::const_iterator Iterator; - OwnPtr<PositionedObjectsListHashSet> m_positionedObjects; // Allocated only when some of these fields have non-default values struct RenderBlockRareData { diff --git a/Source/WebCore/rendering/RenderBlockLineLayout.cpp b/Source/WebCore/rendering/RenderBlockLineLayout.cpp index 088c14cbb..6b904b2cb 100755 --- a/Source/WebCore/rendering/RenderBlockLineLayout.cpp +++ b/Source/WebCore/rendering/RenderBlockLineLayout.cpp @@ -75,8 +75,13 @@ public: ASSERT(block); updateAvailableWidth(); } +#if ENABLE(SUBPIXEL_LAYOUT) + bool fitsOnLine() const { return currentWidth() <= m_availableWidth + LayoutUnit::epsilon(); } + bool fitsOnLine(float extra) const { return currentWidth() + extra <= m_availableWidth + LayoutUnit::epsilon(); } +#else bool fitsOnLine() const { return currentWidth() <= m_availableWidth; } bool fitsOnLine(float extra) const { return currentWidth() + extra <= m_availableWidth; } +#endif float currentWidth() const { return m_committedWidth + m_uncommittedWidth; } // FIXME: We should eventually replace these three functions by ones that work on a higher abstraction. @@ -768,8 +773,11 @@ void RenderBlock::computeInlineDirectionPositionsForLine(RootInlineBox* lineBox, ETextAlign textAlign = textAlignmentForLine(!reachedEnd && !lineBox->endsWithBreak()); LayoutUnit lineLogicalHeight = logicalHeightForLine(this); - float logicalLeft = pixelSnappedLogicalLeftOffsetForLine(logicalHeight(), lineInfo.isFirstLine(), lineLogicalHeight); - float availableLogicalWidth = pixelSnappedLogicalRightOffsetForLine(logicalHeight(), lineInfo.isFirstLine(), lineLogicalHeight) - logicalLeft; + // CSS 2.1: "'Text-indent' only affects a line if it is the first formatted line of an element. For example, the first line of an anonymous block + // box is only affected if it is the first child of its parent element." + bool firstLine = lineInfo.isFirstLine() && !(isAnonymousBlock() && parent()->firstChild() != this); + float logicalLeft = pixelSnappedLogicalLeftOffsetForLine(logicalHeight(), firstLine, lineLogicalHeight); + float availableLogicalWidth = pixelSnappedLogicalRightOffsetForLine(logicalHeight(), firstLine, lineLogicalHeight) - logicalLeft; bool needsWordSpacing = false; float totalLogicalWidth = lineBox->getFlowSpacingLogicalWidth(); diff --git a/Source/WebCore/rendering/RenderBox.cpp b/Source/WebCore/rendering/RenderBox.cpp index 9b3b7de86..faf9102e1 100644 --- a/Source/WebCore/rendering/RenderBox.cpp +++ b/Source/WebCore/rendering/RenderBox.cpp @@ -175,12 +175,8 @@ void RenderBox::removeFloatingOrPositionedChildFromBlockLists() } } - if (isOutOfFlowPositioned()) { - for (RenderObject* curr = parent(); curr; curr = curr->parent()) { - if (curr->isRenderBlock()) - toRenderBlock(curr)->removePositionedObject(this); - } - } + if (isOutOfFlowPositioned()) + RenderBlock::removePositionedObject(this); } void RenderBox::styleWillChange(StyleDifference diff, const RenderStyle* newStyle) @@ -309,7 +305,7 @@ void RenderBox::updateBoxModelInfoFromStyle() setFloating(!isOutOfFlowPositioned() && styleToUse->isFloating()); // We also handle <body> and <html>, whose overflow applies to the viewport. - if (styleToUse->overflowX() != OVISIBLE && !isRootObject && (isRenderBlock() || isTableRow() || isTableSection())) { + if (styleToUse->overflowX() != OVISIBLE && !isRootObject && isRenderBlock()) { bool boxHasOverflowClip = true; if (isBody()) { // Overflow on the body can propagate to the viewport under the following conditions. @@ -1252,7 +1248,7 @@ LayoutUnit RenderBox::perpendicularContainingBlockLogicalHeight() const return cb->computeContentBoxLogicalHeight(logicalHeightLength.value()); } -void RenderBox::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed, bool useTransforms, TransformState& transformState, ApplyContainerFlipOrNot, bool* wasFixed) const +void RenderBox::mapLocalToContainer(RenderBoxModelObject* repaintContainer, TransformState& transformState, MapLocalToContainerFlags mode, bool* wasFixed) const { if (repaintContainer == this) return; @@ -1278,17 +1274,17 @@ void RenderBox::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool // If this box has a transform, it acts as a fixed position container for fixed descendants, // and may itself also be fixed position. So propagate 'fixed' up only if this box is fixed position. if (hasTransform && !isFixedPos) - fixed = false; + mode &= ~IsFixed; else if (isFixedPos) - fixed = true; + mode |= IsFixed; if (wasFixed) - *wasFixed = fixed; + *wasFixed = mode & IsFixed; LayoutSize containerOffset = offsetFromContainer(o, roundedLayoutPoint(transformState.mappedPoint())); - bool preserve3D = useTransforms && (o->style()->preserves3D() || style()->preserves3D()); - if (useTransforms && shouldUseTransformFromContainer(o)) { + bool preserve3D = mode & UseTransforms && (o->style()->preserves3D() || style()->preserves3D()); + if (mode & UseTransforms && shouldUseTransformFromContainer(o)) { TransformationMatrix t; getTransformFromContainer(o, containerOffset, t); transformState.applyTransform(t, preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform); @@ -1303,15 +1299,16 @@ void RenderBox::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool return; } + mode &= ~ApplyContainerFlip; if (o->isRenderFlowThread()) { // Transform from render flow coordinates into region coordinates. RenderRegion* region = toRenderFlowThread(o)->mapFromFlowToRegion(transformState); if (region) - region->mapLocalToContainer(region->containerForRepaint(), fixed, useTransforms, transformState, DoNotApplyContainerFlip, wasFixed); + region->mapLocalToContainer(region->containerForRepaint(), transformState, mode, wasFixed); return; } - o->mapLocalToContainer(repaintContainer, fixed, useTransforms, transformState, DoNotApplyContainerFlip, wasFixed); + o->mapLocalToContainer(repaintContainer, transformState, mode, wasFixed); } const RenderObject* RenderBox::pushMappingToContainer(const RenderBoxModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap) const @@ -2060,6 +2057,14 @@ LayoutUnit RenderBox::computeLogicalHeightUsing(SizeType heightType, const Lengt return logicalHeight; } +LayoutUnit RenderBox::computeLogicalClientHeight(SizeType heightType, const Length& height) +{ + LayoutUnit heightIncludingScrollbar = computeContentLogicalHeightUsing(heightType, height); + if (heightIncludingScrollbar == -1) + return -1; + return std::max(LayoutUnit(0), computeContentBoxLogicalHeight(heightIncludingScrollbar) - scrollbarLogicalHeight()); +} + LayoutUnit RenderBox::computeContentLogicalHeightUsing(SizeType heightType, const Length& height) { if (height.isAuto()) @@ -3951,8 +3956,6 @@ LayoutSize RenderBox::topLeftLocationOffset() const return locationOffset(); LayoutRect rect(frameRect()); - if (containerBlock->style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft()) - rect.move(containerBlock->verticalScrollbarWidth(), 0); containerBlock->flipForWritingMode(rect); // FIXME: This is wrong if we are an absolutely positioned object enclosed by a relative-positioned inline. return LayoutSize(rect.x(), rect.y()); } @@ -3999,6 +4002,10 @@ RenderObject* RenderBox::splitAnonymousBoxesAroundChild(RenderObject* beforeChil RenderBox* postBox = boxToSplit->createAnonymousBoxWithSameTypeAs(this); postBox->setChildrenInline(boxToSplit->childrenInline()); RenderBox* parentBox = toRenderBox(boxToSplit->parent()); + // We need to invalidate the |parentBox| before inserting the new node + // so that the table repainting logic knows the structure is dirty. + // See for example RenderTableCell:clippedOverflowRectForRepaint. + markBoxForRelayoutAfterSplit(parentBox); parentBox->virtualChildren()->insertChildNode(parentBox, postBox, boxToSplit->nextSibling()); boxToSplit->moveChildrenTo(postBox, beforeChild, 0, true); diff --git a/Source/WebCore/rendering/RenderBox.h b/Source/WebCore/rendering/RenderBox.h index bbb034451..2dcc3cdc7 100644 --- a/Source/WebCore/rendering/RenderBox.h +++ b/Source/WebCore/rendering/RenderBox.h @@ -342,6 +342,7 @@ public: LayoutUnit computeLogicalWidthInRegionUsing(SizeType, LayoutUnit availableLogicalWidth, const RenderBlock* containingBlock, RenderRegion*, LayoutUnit offsetFromLogicalTopOfFirstPage); LayoutUnit computeLogicalHeightUsing(SizeType, const Length& height); + LayoutUnit computeLogicalClientHeight(SizeType, const Length& height); LayoutUnit computeContentLogicalHeightUsing(SizeType, const Length& height); LayoutUnit computeReplacedLogicalWidthUsing(SizeType, Length width) const; LayoutUnit computeReplacedLogicalWidthRespectingMinMaxWidth(LayoutUnit logicalWidth, bool includeMaxWidth = true) const; @@ -518,7 +519,7 @@ protected: virtual bool shouldComputeSizeAsReplaced() const { return isReplaced() && !isInlineBlockOrInlineTable(); } - virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed, bool useTransforms, TransformState&, ApplyContainerFlipOrNot = ApplyContainerFlip, bool* wasFixed = 0) const; + virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, TransformState&, MapLocalToContainerFlags mode = ApplyContainerFlip, bool* wasFixed = 0) const OVERRIDE; virtual const RenderObject* pushMappingToContainer(const RenderBoxModelObject*, RenderGeometryMap&) const; virtual void mapAbsoluteToLocalPoint(bool fixed, bool useTransforms, TransformState&) const; diff --git a/Source/WebCore/rendering/RenderBoxModelObject.cpp b/Source/WebCore/rendering/RenderBoxModelObject.cpp index 5eef3ccac..caf327b13 100644 --- a/Source/WebCore/rendering/RenderBoxModelObject.cpp +++ b/Source/WebCore/rendering/RenderBoxModelObject.cpp @@ -2526,6 +2526,8 @@ void RenderBoxModelObject::paintBoxShadow(const PaintInfo& info, const LayoutRec context->fillRect(fillRect.rect(), Color::black, s->colorSpace()); else { fillRect.expandRadii(shadowSpread); + if (!fillRect.isRenderable()) + fillRect.adjustRadii(); context->fillRoundedRect(fillRect, Color::black, s->colorSpace()); } } else { @@ -2749,9 +2751,8 @@ void RenderBoxModelObject::mapAbsoluteToLocalPoint(bool fixed, bool useTransform void RenderBoxModelObject::moveChildTo(RenderBoxModelObject* toBoxModelObject, RenderObject* child, RenderObject* beforeChild, bool fullRemoveInsert) { - // FIXME: We need a performant way to handle clearing positioned objects from our list that are - // in |child|'s subtree so we could just clear them here. Because of this, we assume that callers - // have cleared their positioned objects list for child moves (!fullRemoveInsert) to avoid any badness. + // We assume that callers have cleared their positioned objects list for child moves (!fullRemoveInsert) so the + // positioned renderer maps don't become stale. It would be too slow to do the map lookup on each call. ASSERT(!fullRemoveInsert || !isRenderBlock() || !toRenderBlock(this)->hasPositionedObjects()); ASSERT(this == child->parent()); diff --git a/Source/WebCore/rendering/RenderDeprecatedFlexibleBox.cpp b/Source/WebCore/rendering/RenderDeprecatedFlexibleBox.cpp index 4ae42bc7d..830efb2b0 100644 --- a/Source/WebCore/rendering/RenderDeprecatedFlexibleBox.cpp +++ b/Source/WebCore/rendering/RenderDeprecatedFlexibleBox.cpp @@ -122,7 +122,7 @@ RenderDeprecatedFlexibleBox::RenderDeprecatedFlexibleBox(Node* node) : RenderBlock(node) { setChildrenInline(false); // All of our children must be block-level - m_flexingChildren = m_stretchingChildren = false; + m_stretchingChildren = false; } RenderDeprecatedFlexibleBox::~RenderDeprecatedFlexibleBox() @@ -258,18 +258,10 @@ void RenderDeprecatedFlexibleBox::layoutBlock(bool relayoutChildren, LayoutUnit) setHeight(0); - m_flexingChildren = m_stretchingChildren = false; + m_stretchingChildren = false; initMaxMarginValues(); - // For overflow:scroll blocks, ensure we have both scrollbars in place always. - if (scrollsOverflow()) { - if (style()->overflowX() == OSCROLL) - layer()->setHasHorizontalScrollbar(true); - if (style()->overflowY() == OSCROLL) - layer()->setHasVerticalScrollbar(true); - } - if (isHorizontal()) layoutHorizontalBox(relayoutChildren); else @@ -360,7 +352,7 @@ void RenderDeprecatedFlexibleBox::layoutHorizontalBox(bool relayoutChildren) FlexBoxIterator iterator(this); unsigned int highestFlexGroup = 0; unsigned int lowestFlexGroup = 0; - bool haveFlex = false; + bool haveFlex = false, flexingChildren = false; gatherFlexChildrenInfo(iterator, relayoutChildren, highestFlexGroup, lowestFlexGroup, haveFlex); RenderBlock::startDelayUpdateScrollInfo(); @@ -494,7 +486,7 @@ void RenderDeprecatedFlexibleBox::layoutHorizontalBox(bool relayoutChildren) remainingSpace = borderLeft() + paddingLeft() + contentWidth() - xPos; m_stretchingChildren = false; - if (m_flexingChildren) + if (flexingChildren) haveFlex = false; // We're done. else if (haveFlex) { // We have some flexible objects. See if we need to grow/shrink them at all. @@ -546,7 +538,7 @@ void RenderDeprecatedFlexibleBox::layoutHorizontalBox(bool relayoutChildren) LayoutUnit spaceAdd = LayoutUnit(spaceAvailableThisPass * (child->style()->boxFlex() / totalFlex)); if (spaceAdd) { child->setOverrideLogicalContentWidth(child->overrideLogicalContentWidth() + spaceAdd); - m_flexingChildren = true; + flexingChildren = true; relayoutChildren = true; } @@ -563,7 +555,7 @@ void RenderDeprecatedFlexibleBox::layoutHorizontalBox(bool relayoutChildren) for (RenderBox* child = iterator.first(); child && groupRemainingSpace; child = iterator.next()) { if (allowedChildFlex(child, expanding, i)) { child->setOverrideLogicalContentWidth(child->overrideLogicalContentWidth() + spaceAdd); - m_flexingChildren = true; + flexingChildren = true; relayoutChildren = true; remainingSpace -= spaceAdd; groupRemainingSpace -= spaceAdd; @@ -574,13 +566,11 @@ void RenderDeprecatedFlexibleBox::layoutHorizontalBox(bool relayoutChildren) } // We didn't find any children that could grow. - if (haveFlex && !m_flexingChildren) + if (haveFlex && !flexingChildren) haveFlex = false; } } while (haveFlex); - m_flexingChildren = false; - RenderBlock::finishDelayUpdateScrollInfo(); if (remainingSpace > 0 && ((style()->isLeftToRightDirection() && style()->boxPack() != Start) @@ -649,7 +639,7 @@ void RenderDeprecatedFlexibleBox::layoutVerticalBox(bool relayoutChildren) FlexBoxIterator iterator(this); unsigned int highestFlexGroup = 0; unsigned int lowestFlexGroup = 0; - bool haveFlex = false; + bool haveFlex = false, flexingChildren = false; gatherFlexChildrenInfo(iterator, relayoutChildren, highestFlexGroup, lowestFlexGroup, haveFlex); // We confine the line clamp ugliness to vertical flexible boxes (thus keeping it out of @@ -750,7 +740,7 @@ void RenderDeprecatedFlexibleBox::layoutVerticalBox(bool relayoutChildren) remainingSpace = borderTop() + paddingTop() + contentHeight() - yPos; - if (m_flexingChildren) + if (flexingChildren) haveFlex = false; // We're done. else if (haveFlex) { // We have some flexible objects. See if we need to grow/shrink them at all. @@ -799,7 +789,7 @@ void RenderDeprecatedFlexibleBox::layoutVerticalBox(bool relayoutChildren) LayoutUnit spaceAdd = static_cast<LayoutUnit>(spaceAvailableThisPass * (child->style()->boxFlex() / totalFlex)); if (spaceAdd) { child->setOverrideLogicalContentHeight(child->overrideLogicalContentHeight() + spaceAdd); - m_flexingChildren = true; + flexingChildren = true; relayoutChildren = true; } @@ -816,7 +806,7 @@ void RenderDeprecatedFlexibleBox::layoutVerticalBox(bool relayoutChildren) for (RenderBox* child = iterator.first(); child && groupRemainingSpace; child = iterator.next()) { if (allowedChildFlex(child, expanding, i)) { child->setOverrideLogicalContentHeight(child->overrideLogicalContentHeight() + spaceAdd); - m_flexingChildren = true; + flexingChildren = true; relayoutChildren = true; remainingSpace -= spaceAdd; groupRemainingSpace -= spaceAdd; @@ -827,7 +817,7 @@ void RenderDeprecatedFlexibleBox::layoutVerticalBox(bool relayoutChildren) } // We didn't find any children that could grow. - if (haveFlex && !m_flexingChildren) + if (haveFlex && !flexingChildren) haveFlex = false; } } while (haveFlex); @@ -930,9 +920,7 @@ void RenderDeprecatedFlexibleBox::applyLineClamp(FlexBoxIterator& iterator, bool child->setChildNeedsLayout(true, MarkOnlyThis); child->setOverrideLogicalContentHeight(newHeight - child->borderAndPaddingHeight()); - m_flexingChildren = true; child->layoutIfNeeded(); - m_flexingChildren = false; child->clearOverrideSize(); // FIXME: For now don't support RTL. diff --git a/Source/WebCore/rendering/RenderDeprecatedFlexibleBox.h b/Source/WebCore/rendering/RenderDeprecatedFlexibleBox.h index 32f518199..958bdf32f 100644 --- a/Source/WebCore/rendering/RenderDeprecatedFlexibleBox.h +++ b/Source/WebCore/rendering/RenderDeprecatedFlexibleBox.h @@ -49,7 +49,6 @@ public: virtual bool avoidsFloats() const { return true; } virtual bool isDeprecatedFlexibleBox() const { return true; } - virtual bool isFlexingChildren() const { return m_flexingChildren; } virtual bool isStretchingChildren() const { return m_stretchingChildren; } void placeChild(RenderBox* child, const LayoutPoint& location); @@ -61,8 +60,7 @@ protected: bool isVertical() const { return style()->boxOrient() == VERTICAL; } bool isHorizontal() const { return style()->boxOrient() == HORIZONTAL; } - bool m_flexingChildren : 1; - bool m_stretchingChildren : 1; + bool m_stretchingChildren; private: void applyLineClamp(FlexBoxIterator&, bool relayoutChildren); diff --git a/Source/WebCore/rendering/RenderEmbeddedObject.cpp b/Source/WebCore/rendering/RenderEmbeddedObject.cpp index a3657fae3..135959420 100644 --- a/Source/WebCore/rendering/RenderEmbeddedObject.cpp +++ b/Source/WebCore/rendering/RenderEmbeddedObject.cpp @@ -109,6 +109,8 @@ static String unavailablePluginReplacementText(RenderEmbeddedObject::PluginUnava return missingPluginText(); case RenderEmbeddedObject::PluginCrashed: return crashedPluginText(); + case RenderEmbeddedObject::PluginBlockedByContentSecurityPolicy: + return blockedPluginByContentSecurityPolicyText(); case RenderEmbeddedObject::InsecurePluginVersion: return insecurePluginVersionText(); } diff --git a/Source/WebCore/rendering/RenderEmbeddedObject.h b/Source/WebCore/rendering/RenderEmbeddedObject.h index fd44e080f..be854c1ed 100644 --- a/Source/WebCore/rendering/RenderEmbeddedObject.h +++ b/Source/WebCore/rendering/RenderEmbeddedObject.h @@ -39,6 +39,7 @@ public: enum PluginUnavailabilityReason { PluginMissing, PluginCrashed, + PluginBlockedByContentSecurityPolicy, InsecurePluginVersion }; void setPluginUnavailabilityReason(PluginUnavailabilityReason); diff --git a/Source/WebCore/rendering/RenderFileUploadControl.cpp b/Source/WebCore/rendering/RenderFileUploadControl.cpp index 3b880ccf1..bac5b59c7 100644 --- a/Source/WebCore/rendering/RenderFileUploadControl.cpp +++ b/Source/WebCore/rendering/RenderFileUploadControl.cpp @@ -60,6 +60,11 @@ RenderFileUploadControl::~RenderFileUploadControl() { } +bool RenderFileUploadControl::canBeReplacedWithInlineRunIn() const +{ + return false; +} + void RenderFileUploadControl::updateFromElement() { HTMLInputElement* input = static_cast<HTMLInputElement*>(node()); @@ -141,8 +146,7 @@ void RenderFileUploadControl::paintObject(PaintInfo& paintInfo, const LayoutPoin // We want to match the button's baseline RenderButton* buttonRenderer = toRenderButton(button->renderer()); // FIXME: Make this work with transforms. - LayoutUnit textY = buttonRenderer->absoluteBoundingBoxRectIgnoringTransforms().y() - + buttonRenderer->baselinePosition(AlphabeticBaseline, true, HorizontalLine, PositionOnContainingLine); + LayoutUnit textY = paintOffset.y() + buttonRenderer->baselinePosition(AlphabeticBaseline, true, HorizontalLine, PositionOnContainingLine); paintInfo.context->setFillColor(style()->visitedDependentColor(CSSPropertyColor), style()->colorSpace()); @@ -190,7 +194,8 @@ void RenderFileUploadControl::computePreferredLogicalWidths() 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; + if (RenderObject* buttonRenderer = button->renderer()) + defaultLabelWidth += buttonRenderer->maxPreferredLogicalWidth() + afterButtonSpacing; m_maxPreferredLogicalWidth = static_cast<int>(ceilf(max(minDefaultLabelWidth, defaultLabelWidth))); } diff --git a/Source/WebCore/rendering/RenderFileUploadControl.h b/Source/WebCore/rendering/RenderFileUploadControl.h index 11015eb90..2ce4ca6f2 100644 --- a/Source/WebCore/rendering/RenderFileUploadControl.h +++ b/Source/WebCore/rendering/RenderFileUploadControl.h @@ -44,6 +44,7 @@ public: private: virtual const char* renderName() const { return "RenderFileUploadControl"; } + virtual bool canBeReplacedWithInlineRunIn() const OVERRIDE; virtual void updateFromElement(); virtual void computePreferredLogicalWidths(); virtual void paintObject(PaintInfo&, const LayoutPoint&); diff --git a/Source/WebCore/rendering/RenderFlexibleBox.cpp b/Source/WebCore/rendering/RenderFlexibleBox.cpp index 3b1d4737c..5de6425f2 100644 --- a/Source/WebCore/rendering/RenderFlexibleBox.cpp +++ b/Source/WebCore/rendering/RenderFlexibleBox.cpp @@ -39,6 +39,16 @@ namespace WebCore { +// Normally, -1 and 0 are not valid in a HashSet, but these are relatively likely order: values. Instead, +// we make the two smallest int values invalid order: values (in the css parser code we clamp them to +// int min + 2). +struct RenderFlexibleBox::OrderHashTraits : 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; } +}; + class RenderFlexibleBox::OrderIterator { public: OrderIterator(RenderFlexibleBox* flexibleBox, const OrderHashSet& orderValues) @@ -89,8 +99,8 @@ public: private: RenderFlexibleBox* m_flexibleBox; RenderBox* m_currentChild; - Vector<float> m_orderValues; - Vector<float>::const_iterator m_orderValuesIterator; + Vector<int> m_orderValues; + Vector<int>::const_iterator m_orderValuesIterator; }; struct RenderFlexibleBox::LineContext { @@ -194,10 +204,10 @@ void RenderFlexibleBox::computePreferredLogicalWidths() LayoutUnit scrollbarWidth = 0; if (hasOverflowClip()) { if (isHorizontalWritingMode() && styleToUse->overflowY() == OSCROLL) { - layer()->setHasVerticalScrollbar(true); + ASSERT(layer()->hasVerticalScrollbar()); scrollbarWidth = verticalScrollbarWidth(); } else if (!isHorizontalWritingMode() && styleToUse->overflowX() == OSCROLL) { - layer()->setHasHorizontalScrollbar(true); + ASSERT(layer()->hasHorizontalScrollbar()); scrollbarWidth = horizontalScrollbarHeight(); } } @@ -248,14 +258,6 @@ void RenderFlexibleBox::layoutBlock(bool relayoutChildren, LayoutUnit) m_overflow.clear(); - // For overflow:scroll blocks, ensure we have both scrollbars in place always. - if (scrollsOverflow()) { - if (style()->overflowX() == OSCROLL) - layer()->setHasHorizontalScrollbar(true); - if (style()->overflowY() == OSCROLL) - layer()->setHasVerticalScrollbar(true); - } - WTF::Vector<LineContext> lineContexts; OrderHashSet orderValues; computeMainAxisPreferredSizes(relayoutChildren, orderValues); @@ -358,11 +360,6 @@ Length RenderFlexibleBox::flexBasisForChild(RenderBox* child) const return flexLength; } -Length RenderFlexibleBox::crossAxisLength() const -{ - return isHorizontalFlow() ? style()->height() : style()->width(); -} - void RenderFlexibleBox::setCrossAxisExtent(LayoutUnit extent) { if (isHorizontalFlow()) @@ -399,10 +396,19 @@ LayoutUnit RenderFlexibleBox::crossAxisContentExtent() const LayoutUnit RenderFlexibleBox::mainAxisContentExtent() { if (isColumnFlow()) - return std::max(LayoutUnit(0), computeContentLogicalHeightUsing(MainOrPreferredSize, style()->logicalHeight())); + return std::max(LayoutUnit(0), computeLogicalClientHeight(MainOrPreferredSize, style()->logicalHeight())); return contentLogicalWidth(); } +LayoutUnit RenderFlexibleBox::computeMainAxisExtentForChild(RenderBox* child, SizeType sizeType, const Length& size, LayoutUnit maximumValue) +{ + // FIXME: This is wrong for orthogonal flows. It should use the flexbox's writing-mode, not the child's in order + // to figure out the logical height/width. + if (isColumnFlow()) + return child->computeLogicalClientHeight(sizeType, size); + return child->computeContentBoxLogicalWidth(valueForLength(size, maximumValue, view())); +} + WritingMode RenderFlexibleBox::transformedWritingMode() const { WritingMode mode = style()->writingMode(); @@ -599,7 +605,7 @@ LayoutUnit RenderFlexibleBox::preferredMainAxisContentExtentForChild(RenderBox* LayoutUnit mainAxisExtent = hasOrthogonalFlow(child) ? child->logicalHeight() : child->maxPreferredLogicalWidth(); return mainAxisExtent - mainAxisBorderAndPaddingExtentForChild(child); } - return std::max(LayoutUnit(0), minimumValueForLength(flexBasis, mainAxisContentExtent(), view())); + return std::max(LayoutUnit(0), computeMainAxisExtentForChild(child, MainOrPreferredSize, flexBasis, mainAxisContentExtent())); } LayoutUnit RenderFlexibleBox::computeAvailableFreeSpace(LayoutUnit preferredMainAxisExtent) @@ -610,11 +616,11 @@ LayoutUnit RenderFlexibleBox::computeAvailableFreeSpace(LayoutUnit preferredMain else if (hasOverrideHeight()) contentExtent = overrideLogicalContentHeight(); else { - LayoutUnit heightResult = computeContentLogicalHeightUsing(MainOrPreferredSize, style()->logicalHeight()); + LayoutUnit heightResult = computeLogicalClientHeight(MainOrPreferredSize, style()->logicalHeight()); if (heightResult == -1) heightResult = preferredMainAxisExtent; - LayoutUnit minHeight = computeContentLogicalHeightUsing(MinSize, style()->logicalMinHeight()); // Leave as -1 if unset. - LayoutUnit maxHeight = style()->logicalMaxHeight().isUndefined() ? heightResult : computeContentLogicalHeightUsing(MaxSize, style()->logicalMaxHeight()); + LayoutUnit minHeight = computeLogicalClientHeight(MinSize, style()->logicalMinHeight()); // Leave as -1 if unset. + LayoutUnit maxHeight = style()->logicalMaxHeight().isUndefined() ? heightResult : computeLogicalClientHeight(MaxSize, style()->logicalMaxHeight()); if (maxHeight == -1) maxHeight = heightResult; heightResult = std::min(maxHeight, heightResult); @@ -751,6 +757,14 @@ LayoutUnit RenderFlexibleBox::marginBoxAscentForChild(RenderBox* child) return ascent + flowAwareMarginBeforeForChild(child); } +LayoutUnit RenderFlexibleBox::computeMarginValue(Length margin, LayoutUnit availableSize, RenderView* view) +{ + // CSS always computes percent margins with respect to the containing block's width, even for margin-top/margin-bottom. + if (margin.isPercent()) + availableSize = logicalWidth(); + return minimumValueForLength(margin, availableSize, view); +} + void RenderFlexibleBox::computeMainAxisPreferredSizes(bool relayoutChildren, OrderHashSet& orderValues) { LayoutUnit flexboxAvailableContentExtent = mainAxisContentExtent(); @@ -766,18 +780,18 @@ void RenderFlexibleBox::computeMainAxisPreferredSizes(bool relayoutChildren, Ord Length childMainAxisMin = isHorizontalFlow() ? child->style()->minWidth() : child->style()->minHeight(); if (hasOrthogonalFlow(child) && (flexBasisForChild(child).isAuto() || childMainAxisMin.isAuto())) { if (!relayoutChildren) - child->setChildNeedsLayout(true); + child->setChildNeedsLayout(true, MarkOnlyThis); child->layoutIfNeeded(); } // Before running the flex algorithm, 'auto' has a margin of 0. // Also, if we're not auto sizing, we don't do a layout that computes the start/end margins. if (isHorizontalFlow()) { - child->setMarginLeft(minimumValueForLength(child->style()->marginLeft(), flexboxAvailableContentExtent, renderView)); - child->setMarginRight(minimumValueForLength(child->style()->marginRight(), flexboxAvailableContentExtent, renderView)); + child->setMarginLeft(computeMarginValue(child->style()->marginLeft(), flexboxAvailableContentExtent, renderView)); + child->setMarginRight(computeMarginValue(child->style()->marginRight(), flexboxAvailableContentExtent, renderView)); } else { - child->setMarginTop(minimumValueForLength(child->style()->marginTop(), flexboxAvailableContentExtent, renderView)); - child->setMarginBottom(minimumValueForLength(child->style()->marginBottom(), flexboxAvailableContentExtent, renderView)); + child->setMarginTop(computeMarginValue(child->style()->marginTop(), flexboxAvailableContentExtent, renderView)); + child->setMarginBottom(computeMarginValue(child->style()->marginBottom(), flexboxAvailableContentExtent, renderView)); } } } @@ -787,10 +801,10 @@ LayoutUnit RenderFlexibleBox::lineBreakLength() if (!isColumnFlow()) return mainAxisContentExtent(); - LayoutUnit height = computeContentLogicalHeightUsing(MainOrPreferredSize, style()->logicalHeight()); + LayoutUnit height = computeLogicalClientHeight(MainOrPreferredSize, style()->logicalHeight()); if (height == -1) height = MAX_LAYOUT_UNIT; - LayoutUnit maxHeight = computeContentLogicalHeightUsing(MaxSize, style()->logicalMaxHeight()); + LayoutUnit maxHeight = computeLogicalClientHeight(MaxSize, style()->logicalMaxHeight()); if (maxHeight != -1) height = std::min(height, maxHeight); return height; @@ -798,25 +812,23 @@ LayoutUnit RenderFlexibleBox::lineBreakLength() LayoutUnit RenderFlexibleBox::adjustChildSizeForMinAndMax(RenderBox* child, LayoutUnit childSize, LayoutUnit flexboxAvailableContentExtent) { + // FIXME: Support intrinsic min/max lengths. Length max = isHorizontalFlow() ? child->style()->maxWidth() : child->style()->maxHeight(); - Length min = isHorizontalFlow() ? child->style()->minWidth() : child->style()->minHeight(); - RenderView* renderView = view(); - // FIXME: valueForLength isn't quite right in quirks mode: percentage heights should check parents until a value is found. - // https://bugs.webkit.org/show_bug.cgi?id=81809 - if (max.isSpecified() && childSize > valueForLength(max, flexboxAvailableContentExtent, renderView)) - childSize = valueForLength(max, flexboxAvailableContentExtent, renderView); - - if (min.isSpecified() && childSize < valueForLength(min, flexboxAvailableContentExtent, renderView)) - return valueForLength(min, flexboxAvailableContentExtent, renderView); - - // FIXME: Support min/max sizes of fit-content, max-content and fill-available. - if (min.isAuto()) { - LayoutUnit minContent = hasOrthogonalFlow(child) ? child->logicalHeight() : child->minPreferredLogicalWidth(); - minContent -= mainAxisBorderAndPaddingExtentForChild(child); - return std::max(childSize, minContent); + if (max.isSpecified()) { + LayoutUnit maxExtent = computeMainAxisExtentForChild(child, MaxSize, max, flexboxAvailableContentExtent); + if (maxExtent != -1 && childSize > maxExtent) + childSize = maxExtent; } - return childSize; + Length min = isHorizontalFlow() ? child->style()->minWidth() : child->style()->minHeight(); + LayoutUnit minExtent = 0; + if (min.isSpecified()) + minExtent = computeMainAxisExtentForChild(child, MinSize, min, flexboxAvailableContentExtent); + else if (min.isAuto()) { + minExtent = hasOrthogonalFlow(child) ? child->logicalHeight() : child->minPreferredLogicalWidth(); + minExtent -= mainAxisBorderAndPaddingExtentForChild(child); + } + return std::max(childSize, minExtent); } bool RenderFlexibleBox::computeNextFlexLine(OrderIterator& iterator, OrderedFlexItemList& orderedChildren, LayoutUnit& preferredMainAxisExtent, float& totalFlexGrow, float& totalWeightedFlexShrink, LayoutUnit& minMaxAppliedMainAxisExtent) @@ -1007,7 +1019,7 @@ void RenderFlexibleBox::layoutAndPlaceChildren(LayoutUnit& crossAxisOffset, cons LayoutUnit childPreferredSize = childSizes[i] + mainAxisBorderAndPaddingExtentForChild(child); setLogicalOverrideSize(child, childPreferredSize); // FIXME: Can avoid laying out here in some cases. See https://webkit.org/b/87905. - child->setChildNeedsLayout(true); + child->setChildNeedsLayout(true, MarkOnlyThis); child->layoutIfNeeded(); updateAutoMarginsInMainAxis(child, autoMarginOffset); @@ -1231,14 +1243,14 @@ void RenderFlexibleBox::applyStretchAlignmentToChild(RenderBox* child, LayoutUni if (child->logicalHeight() != logicalHeightBefore) { child->setOverrideLogicalContentHeight(child->logicalHeight() - child->borderAndPaddingLogicalHeight()); child->setLogicalHeight(0); - child->setChildNeedsLayout(true); + child->setChildNeedsLayout(true, MarkOnlyThis); child->layoutIfNeeded(); } } else if (isColumnFlow() && child->style()->logicalWidth().isAuto() && isMultiline()) { // FIXME: Handle min-width and max-width. LayoutUnit childWidth = lineCrossAxisExtent - crossAxisMarginExtentForChild(child); child->setOverrideLogicalContentWidth(std::max(ZERO_LAYOUT_UNIT, childWidth)); - child->setChildNeedsLayout(true); + child->setChildNeedsLayout(true, MarkOnlyThis); child->layoutIfNeeded(); } } diff --git a/Source/WebCore/rendering/RenderFlexibleBox.h b/Source/WebCore/rendering/RenderFlexibleBox.h index 1a9ebc982..bd05b450c 100644 --- a/Source/WebCore/rendering/RenderFlexibleBox.h +++ b/Source/WebCore/rendering/RenderFlexibleBox.h @@ -44,6 +44,7 @@ public: virtual const char* renderName() const OVERRIDE; virtual bool isFlexibleBox() const OVERRIDE { return true; } + virtual bool avoidsFloats() const OVERRIDE { return true; } virtual void computePreferredLogicalWidths() OVERRIDE; virtual void layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeight = 0) OVERRIDE; @@ -62,7 +63,8 @@ private: NoFlipForRowReverse, }; - typedef HashSet<float> OrderHashSet; + struct OrderHashTraits; + typedef HashSet<int, DefaultHash<int>::Hash, OrderHashTraits> OrderHashSet; class OrderIterator; typedef WTF::HashMap<const RenderBox*, LayoutUnit> InflexibleFlexItemSize; @@ -75,7 +77,6 @@ private: bool isColumnFlow() const; bool isLeftToRightFlow() const; bool isMultiline() const; - Length crossAxisLength() const; Length flexBasisForChild(RenderBox* child) const; void setCrossAxisExtent(LayoutUnit); LayoutUnit crossAxisExtentForChild(RenderBox* child); @@ -84,6 +85,7 @@ private: LayoutUnit mainAxisExtent() const; LayoutUnit crossAxisContentExtent() const; LayoutUnit mainAxisContentExtent(); + LayoutUnit computeMainAxisExtentForChild(RenderBox* child, SizeType, const Length& size, LayoutUnit maximumValue); WritingMode transformedWritingMode() const; LayoutUnit flowAwareBorderStart() const; LayoutUnit flowAwareBorderEnd() const; @@ -117,6 +119,7 @@ private: LayoutUnit availableAlignmentSpaceForChild(LayoutUnit lineCrossAxisExtent, RenderBox*); LayoutUnit marginBoxAscentForChild(RenderBox*); + LayoutUnit computeMarginValue(Length margin, LayoutUnit availableSize, RenderView*); void computeMainAxisPreferredSizes(bool relayoutChildren, OrderHashSet&); LayoutUnit lineBreakLength(); LayoutUnit adjustChildSizeForMinAndMax(RenderBox*, LayoutUnit childSize, LayoutUnit flexboxAvailableContentExtent); diff --git a/Source/WebCore/rendering/RenderFlowThread.cpp b/Source/WebCore/rendering/RenderFlowThread.cpp index 1b09cbb8d..1c805c027 100644 --- a/Source/WebCore/rendering/RenderFlowThread.cpp +++ b/Source/WebCore/rendering/RenderFlowThread.cpp @@ -52,7 +52,6 @@ RenderFlowThread::RenderFlowThread(Node* node) , m_regionsHaveUniformLogicalWidth(true) , m_regionsHaveUniformLogicalHeight(true) , m_overset(true) - , m_regionLayoutUpdateEventTimer(this, &RenderFlowThread::regionLayoutUpdateEventTimerFired) { ASSERT(node->document()->cssRegionsEnabled()); setIsAnonymous(false); @@ -206,15 +205,9 @@ void RenderFlowThread::layout() LayoutStateMaintainer statePusher(view(), this, regionsChanged); RenderBlock::layout(); statePusher.pop(); - if (document()->hasListenerType(Document::REGIONLAYOUTUPDATE_LISTENER) && !m_regionLayoutUpdateEventTimer.isActive()) - for (RenderRegionList::iterator iter = m_regionList.begin(); iter != m_regionList.end(); ++iter) { - RenderRegion* region = *iter; - if (region->shouldDispatchRegionLayoutUpdateEvent()) { - // at least one region needs to dispatch the event - m_regionLayoutUpdateEventTimer.startOneShot(0); - break; - } - } + + if (shouldDispatchRegionLayoutUpdateEvent()) + dispatchRegionLayoutUpdateEvent(); } void RenderFlowThread::computeLogicalWidth() @@ -268,8 +261,8 @@ void RenderFlowThread::paintIntoRegion(PaintInfo& paintInfo, RenderRegion* regio // paintOffset contains the offset where the painting should occur // adjusted with the region padding and border. LayoutRect regionRect(region->regionRect()); - LayoutRect regionOverflowRect(region->regionOverflowRect()); - LayoutRect regionClippingRect(paintOffset + (regionOverflowRect.location() - regionRect.location()), regionOverflowRect.size()); + LayoutRect regionOversetRect(region->regionOversetRect()); + LayoutRect regionClippingRect(paintOffset + (regionOversetRect.location() - regionRect.location()), regionOversetRect.size()); PaintInfo info(paintInfo); info.rect.intersect(pixelSnappedIntRect(regionClippingRect)); @@ -302,8 +295,8 @@ void RenderFlowThread::paintIntoRegion(PaintInfo& paintInfo, RenderRegion* regio bool RenderFlowThread::hitTestRegion(RenderRegion* region, const HitTestRequest& request, HitTestResult& result, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset) { LayoutRect regionRect(region->regionRect()); - LayoutRect regionOverflowRect = region->regionOverflowRect(); - LayoutRect regionClippingRect(accumulatedOffset + (regionOverflowRect.location() - regionRect.location()), regionOverflowRect.size()); + LayoutRect regionOversetRect = region->regionOversetRect(); + LayoutRect regionClippingRect(accumulatedOffset + (regionOversetRect.location() - regionRect.location()), regionOversetRect.size()); if (!regionClippingRect.contains(pointInContainer.point())) return false; @@ -349,12 +342,12 @@ void RenderFlowThread::repaintRectangleInRegions(const LayoutRect& repaintRect, // We only have to issue a repaint in this region if the region rect intersects the repaint rect. LayoutRect flippedRegionRect(region->regionRect()); - LayoutRect flippedRegionOverflowRect(region->regionOverflowRect()); + LayoutRect flippedRegionOversetRect(region->regionOversetRect()); flipForWritingMode(flippedRegionRect); // Put the region rects into physical coordinates. - flipForWritingMode(flippedRegionOverflowRect); + flipForWritingMode(flippedRegionOversetRect); LayoutRect clippedRect(repaintRect); - clippedRect.intersect(flippedRegionOverflowRect); + clippedRect.intersect(flippedRegionOversetRect); if (clippedRect.isEmpty()) continue; @@ -438,7 +431,7 @@ LayoutUnit RenderFlowThread::regionRemainingLogicalHeightForLine(LayoutUnit posi // If IncludePageBoundary is set, the line exactly on the top edge of a // region will act as being part of the previous region. LayoutUnit regionHeight = isHorizontalWritingMode() ? region->regionRect().height() : region->regionRect().width(); - remainingHeight = layoutMod(remainingHeight, regionHeight); + remainingHeight = intMod(remainingHeight, regionHeight); } return remainingHeight; } @@ -701,50 +694,21 @@ void RenderFlowThread::computeOverflowStateForRegions(LayoutUnit oldClientAfterE if (flowMin <= 0) state = RenderRegion::RegionEmpty; if (flowMax > 0) - state = RenderRegion::RegionOverflow; + state = RenderRegion::RegionOverset; region->setRegionState(state); - // determine whether this region should dispatch a regionLayoutUpdate event - // FIXME: currently it cannot determine whether a region whose regionOverflow state remained either "fit" or "overflow" has actually - // changed, so it just assumes that those region should dispatch the event + // determine whether the NamedFlow object should dispatch a regionLayoutUpdate event + // FIXME: currently it cannot determine whether a region whose regionOverset state remained either "fit" or "overset" has actually + // changed, so it just assumes that the NamedFlow should dispatch the event if (previousState != state || state == RenderRegion::RegionFit - || state == RenderRegion::RegionOverflow) - region->setDispatchRegionLayoutUpdateEvent(true); + || state == RenderRegion::RegionOverset) + setDispatchRegionLayoutUpdateEvent(true); } // With the regions overflow state computed we can also set the overset flag for the named flow. // If there are no valid regions in the chain, overset is true RenderRegion* lastReg = lastRegion(); - m_overset = lastReg ? lastReg->regionState() == RenderRegion::RegionOverflow : true; -} - -void RenderFlowThread::regionLayoutUpdateEventTimerFired(Timer<RenderFlowThread>*) -{ - // Create a copy of region nodes, to protect them for being destroyed in the event listener - Vector<RefPtr<Node> > regionNodes; - regionNodes.reserveCapacity(m_regionList.size()); - for (RenderRegionList::iterator iter = m_regionList.begin(); iter != m_regionList.end(); ++iter) { - RenderRegion* region = *iter; - ASSERT(region->node() && region->node()->isElementNode()); - // dispatch the event only for marked regions and only for those who have a listener - if (region->shouldDispatchRegionLayoutUpdateEvent()) { - regionNodes.append(region->node()); - // clear the dispatch flag here, as it is possible to be set again due to event listeners - region->setDispatchRegionLayoutUpdateEvent(false); - } - } - for (Vector<RefPtr<Node> >::const_iterator it = regionNodes.begin(); it != regionNodes.end(); ++it) { - RefPtr<Node> node = *it; - RefPtr<Document> document = node->document(); - if (!document) - continue; - RenderObject* renderer = node->renderer(); - if (renderer && renderer->isRenderRegion()) { - node->dispatchRegionLayoutUpdateEvent(); - // Layout needs to be uptodate after each event listener - document->updateLayoutIgnorePendingStylesheets(); - } - } + m_overset = lastReg ? lastReg->regionState() == RenderRegion::RegionOverset : true; } bool RenderFlowThread::regionInRange(const RenderRegion* targetRegion, const RenderRegion* startRegion, const RenderRegion* endRegion) const diff --git a/Source/WebCore/rendering/RenderFlowThread.h b/Source/WebCore/rendering/RenderFlowThread.h index c76ee0870..4730be8dc 100644 --- a/Source/WebCore/rendering/RenderFlowThread.h +++ b/Source/WebCore/rendering/RenderFlowThread.h @@ -133,8 +133,13 @@ protected: virtual const char* renderName() const = 0; bool shouldRepaint(const LayoutRect&) const; - void regionLayoutUpdateEventTimerFired(Timer<RenderFlowThread>*); bool regionInRange(const RenderRegion* targetRegion, const RenderRegion* startRegion, const RenderRegion* endRegion) const; + + void setDispatchRegionLayoutUpdateEvent(bool value) { m_dispatchRegionLayoutUpdateEvent = value; } + bool shouldDispatchRegionLayoutUpdateEvent() { return m_dispatchRegionLayoutUpdateEvent; } + + // Override if the flow thread implementation supports dispatching events when the flow layout is updated (e.g. for named flows) + virtual void dispatchRegionLayoutUpdateEvent() { m_dispatchRegionLayoutUpdateEvent = false; } RenderRegionList m_regionList; @@ -174,7 +179,7 @@ protected: bool m_regionsHaveUniformLogicalHeight; bool m_overset; bool m_hasRegionsWithStyling; - Timer<RenderFlowThread> m_regionLayoutUpdateEventTimer; + bool m_dispatchRegionLayoutUpdateEvent; }; inline RenderFlowThread* toRenderFlowThread(RenderObject* object) diff --git a/Source/WebCore/rendering/RenderFullScreen.cpp b/Source/WebCore/rendering/RenderFullScreen.cpp index e0507388d..2f1c311b1 100644 --- a/Source/WebCore/rendering/RenderFullScreen.cpp +++ b/Source/WebCore/rendering/RenderFullScreen.cpp @@ -105,15 +105,32 @@ static PassRefPtr<RenderStyle> createFullScreenStyle() return fullscreenStyle.release(); } -RenderObject* RenderFullScreen::wrapRenderer(RenderObject* object, Document* document) +RenderObject* RenderFullScreen::wrapRenderer(RenderObject* object, RenderObject* parent, Document* document) { RenderFullScreen* fullscreenRenderer = new (document->renderArena()) RenderFullScreen(document); fullscreenRenderer->setStyle(createFullScreenStyle()); + if (parent && !parent->isChildAllowed(fullscreenRenderer, fullscreenRenderer->style())) { + fullscreenRenderer->destroy(); + return 0; + } if (object) { + // |object->parent()| can be null if the object is not yet attached + // to |parent|. if (RenderObject* parent = object->parent()) { + RenderBlock* containingBlock = object->containingBlock(); + ASSERT(containingBlock); + // Since we are moving the |object| to a new parent |fullscreenRenderer|, + // the line box tree underneath our |containingBlock| is not longer valid. + containingBlock->deleteLineBoxTree(); + parent->addChild(fullscreenRenderer, object); object->remove(); + + // Always just do a full layout to ensure that line boxes get deleted properly. + // Because objects moved from |parent| to |fullscreenRenderer|, we want to + // make new line boxes instead of leaving the old ones around. parent->setNeedsLayoutAndPrefWidthsRecalc(); + containingBlock->setNeedsLayoutAndPrefWidthsRecalc(); } fullscreenRenderer->addChild(object); fullscreenRenderer->setNeedsLayoutAndPrefWidthsRecalc(); diff --git a/Source/WebCore/rendering/RenderFullScreen.h b/Source/WebCore/rendering/RenderFullScreen.h index d0aac50ac..a675c5f09 100644 --- a/Source/WebCore/rendering/RenderFullScreen.h +++ b/Source/WebCore/rendering/RenderFullScreen.h @@ -42,7 +42,7 @@ public: void createPlaceholder(PassRefPtr<RenderStyle>, const LayoutRect& frameRect); - static RenderObject* wrapRenderer(RenderObject* renderer, Document*); + static RenderObject* wrapRenderer(RenderObject*, RenderObject*, Document*); void unwrapRenderer(); private: diff --git a/Source/WebCore/rendering/RenderGeometryMap.cpp b/Source/WebCore/rendering/RenderGeometryMap.cpp index 0a6c9e04f..edf59787c 100644 --- a/Source/WebCore/rendering/RenderGeometryMap.cpp +++ b/Source/WebCore/rendering/RenderGeometryMap.cpp @@ -92,8 +92,7 @@ void RenderGeometryMap::mapToAbsolute(TransformState& transformState) const { // If the mapping includes something like columns, we have to go via renderers. if (hasNonUniformStep()) { - bool fixed = false; - m_mapping.last().m_renderer->mapLocalToContainer(0, fixed, true, transformState, RenderObject::ApplyContainerFlip); + m_mapping.last().m_renderer->mapLocalToContainer(0, transformState, UseTransforms | ApplyContainerFlip); return; } diff --git a/Source/WebCore/rendering/RenderGrid.cpp b/Source/WebCore/rendering/RenderGrid.cpp index b4d2a0c08..6a4519d1f 100644 --- a/Source/WebCore/rendering/RenderGrid.cpp +++ b/Source/WebCore/rendering/RenderGrid.cpp @@ -80,13 +80,6 @@ void RenderGrid::layoutBlock(bool relayoutChildren, LayoutUnit) m_overflow.clear(); - if (scrollsOverflow()) { - if (style()->overflowX() == OSCROLL) - layer()->setHasHorizontalScrollbar(true); - if (style()->overflowY() == OSCROLL) - layer()->setHasVerticalScrollbar(true); - } - layoutGridItems(); LayoutUnit oldClientAfterEdge = clientLogicalBottom(); @@ -114,6 +107,35 @@ void RenderGrid::layoutBlock(bool relayoutChildren, LayoutUnit) setNeedsLayout(false); } +void RenderGrid::computePreferredLogicalWidths() +{ + ASSERT(preferredLogicalWidthsDirty()); + + m_minPreferredLogicalWidth = 0; + m_maxPreferredLogicalWidth = 0; + + // FIXME: We don't take our own logical width into account. + + const Vector<Length>& trackStyles = style()->gridColumns(); + + for (size_t i = 0; i < trackStyles.size(); ++i) { + Length trackLength = trackStyles[i]; + if (!trackLength.isFixed()) { + notImplemented(); + continue; + } + + m_minPreferredLogicalWidth += trackLength.intValue(); + m_maxPreferredLogicalWidth += trackLength.intValue(); + } + + // FIXME: We should account for min / max logical width. + + // FIXME: Include borders and paddings in inline direction. + + setPreferredLogicalWidthsDirty(false); +} + void RenderGrid::computedUsedBreadthOfGridTracks(TrackSizingDirection direction, Vector<GridTrack>& tracks) { const Vector<Length>& trackStyles = (direction == ForColumns) ? style()->gridColumns() : style()->gridRows(); diff --git a/Source/WebCore/rendering/RenderGrid.h b/Source/WebCore/rendering/RenderGrid.h index 829bf8862..f9b0879bd 100644 --- a/Source/WebCore/rendering/RenderGrid.h +++ b/Source/WebCore/rendering/RenderGrid.h @@ -38,6 +38,7 @@ public: virtual const char* renderName() const OVERRIDE; virtual void layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeight = 0) OVERRIDE; + virtual void computePreferredLogicalWidths() OVERRIDE; virtual bool avoidsFloats() const OVERRIDE { return true; } diff --git a/Source/WebCore/rendering/RenderInline.cpp b/Source/WebCore/rendering/RenderInline.cpp index 7b9fc2efb..da120bed1 100644 --- a/Source/WebCore/rendering/RenderInline.cpp +++ b/Source/WebCore/rendering/RenderInline.cpp @@ -39,7 +39,7 @@ #include "TransformState.h" #include "VisiblePosition.h" -#if ENABLE(DASHBOARD_SUPPORT) +#if ENABLE(DASHBOARD_SUPPORT) || ENABLE(WIDGET_REGION) #include "Frame.h" #endif @@ -1114,7 +1114,7 @@ LayoutSize RenderInline::offsetFromContainer(RenderObject* container, const Layo return offset; } -void RenderInline::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed, bool useTransforms, TransformState& transformState, ApplyContainerFlipOrNot applyContainerFlip, bool* wasFixed) const +void RenderInline::mapLocalToContainer(RenderBoxModelObject* repaintContainer, TransformState& transformState, MapLocalToContainerFlags mode, bool* wasFixed) const { if (repaintContainer == this) return; @@ -1135,18 +1135,18 @@ void RenderInline::mapLocalToContainer(RenderBoxModelObject* repaintContainer, b if (!o) return; - if (applyContainerFlip && o->isBox()) { + if (mode & ApplyContainerFlip && o->isBox()) { if (o->style()->isFlippedBlocksWritingMode()) { IntPoint centerPoint = roundedIntPoint(transformState.mappedPoint()); transformState.move(toRenderBox(o)->flipForWritingModeIncludingColumns(centerPoint) - centerPoint); } - applyContainerFlip = DoNotApplyContainerFlip; + mode &= ~ApplyContainerFlip; } LayoutSize containerOffset = offsetFromContainer(o, roundedLayoutPoint(transformState.mappedPoint())); - bool preserve3D = useTransforms && (o->style()->preserves3D() || style()->preserves3D()); - if (useTransforms && shouldUseTransformFromContainer(o)) { + bool preserve3D = mode & UseTransforms && (o->style()->preserves3D() || style()->preserves3D()); + if (mode & UseTransforms && shouldUseTransformFromContainer(o)) { TransformationMatrix t; getTransformFromContainer(o, containerOffset, t); transformState.applyTransform(t, preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform); @@ -1161,7 +1161,7 @@ void RenderInline::mapLocalToContainer(RenderBoxModelObject* repaintContainer, b return; } - o->mapLocalToContainer(repaintContainer, fixed, useTransforms, transformState, applyContainerFlip, wasFixed); + o->mapLocalToContainer(repaintContainer, transformState, mode, wasFixed); } const RenderObject* RenderInline::pushMappingToContainer(const RenderBoxModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap) const @@ -1534,7 +1534,7 @@ void RenderInline::paintOutlineForLine(GraphicsContext* graphicsContext, const L antialias); } -#if ENABLE(DASHBOARD_SUPPORT) +#if ENABLE(DASHBOARD_SUPPORT) || ENABLE(WIDGET_REGION) void RenderInline::addDashboardRegions(Vector<DashboardRegionValue>& regions) { // Convert the style regions to absolute coordinates. diff --git a/Source/WebCore/rendering/RenderInline.h b/Source/WebCore/rendering/RenderInline.h index a8cc2f1be..e207caf58 100644 --- a/Source/WebCore/rendering/RenderInline.h +++ b/Source/WebCore/rendering/RenderInline.h @@ -135,7 +135,7 @@ private: virtual LayoutRect rectWithOutlineForRepaint(RenderBoxModelObject* repaintContainer, LayoutUnit outlineWidth) const; virtual void computeRectForRepaint(RenderBoxModelObject* repaintContainer, LayoutRect&, bool fixed) const; - virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed, bool useTransforms, TransformState&, ApplyContainerFlipOrNot = ApplyContainerFlip, bool* wasFixed = 0) const; + virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, TransformState&, MapLocalToContainerFlags mode = ApplyContainerFlip, bool* wasFixed = 0) const OVERRIDE; virtual const RenderObject* pushMappingToContainer(const RenderBoxModelObject* ancestorToStopAt, RenderGeometryMap&) const; virtual VisiblePosition positionForPoint(const LayoutPoint&); @@ -159,7 +159,7 @@ private: virtual void imageChanged(WrappedImagePtr, const IntRect* = 0); -#if ENABLE(DASHBOARD_SUPPORT) +#if ENABLE(DASHBOARD_SUPPORT) || ENABLE(WIDGET_REGION) virtual void addDashboardRegions(Vector<DashboardRegionValue>&); #endif diff --git a/Source/WebCore/rendering/RenderLayer.cpp b/Source/WebCore/rendering/RenderLayer.cpp index 74b0f5a67..373beab8a 100644 --- a/Source/WebCore/rendering/RenderLayer.cpp +++ b/Source/WebCore/rendering/RenderLayer.cpp @@ -485,6 +485,17 @@ void RenderLayer::computeRepaintRects(LayoutPoint* offsetFromRoot) m_outlineBox = renderer()->outlineBoundsForRepaint(repaintContainer, offsetFromRoot); } + +void RenderLayer::computeRepaintRectsIncludingDescendants() +{ + // FIXME: computeRepaintRects() has to walk up the parent chain for every layer to compute the rects. + // We should make this more efficient. + computeRepaintRects(); + + for (RenderLayer* layer = firstChild(); layer; layer = layer->nextSibling()) + layer->computeRepaintRectsIncludingDescendants(); +} + void RenderLayer::clearRepaintRects() { ASSERT(!m_hasVisibleContent); @@ -1446,7 +1457,7 @@ void RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, LayoutP // If the fixed layer's container is the root, just add in the offset of the view. We can obtain this by calling // localToAbsolute() on the RenderView. FloatPoint absPos = renderer()->localToAbsolute(FloatPoint(), true); - location += flooredLayoutSize(absPos); + location += LayoutSize(absPos.x(), absPos.y()); return; } @@ -1668,7 +1679,7 @@ void RenderLayer::scrollTo(int x, int y) // We should have a RenderView if we're trying to scroll. ASSERT(view); if (view) { -#if ENABLE(DASHBOARD_SUPPORT) +#if ENABLE(DASHBOARD_SUPPORT) || ENABLE(WIDGET_REGION) // Update dashboard regions, scrolling may change the clip of a // particular region. view->frameView()->updateDashboardRegions(); @@ -2229,6 +2240,10 @@ void RenderLayer::invalidateScrollbarRect(Scrollbar* scrollbar, const IntRect& r IntRect scrollRect = rect; RenderBox* box = renderBox(); ASSERT(box); + // If we are not yet inserted into the tree, there is no need to repaint. + if (!box->parent()) + return; + if (scrollbar == m_vBar.get()) scrollRect.move(verticalScrollbarStart(0, box->width()), box->borderTop()); else @@ -2315,7 +2330,7 @@ void RenderLayer::setHasHorizontalScrollbar(bool hasScrollbar) if (m_vBar) m_vBar->styleChanged(); -#if ENABLE(DASHBOARD_SUPPORT) +#if ENABLE(DASHBOARD_SUPPORT) || ENABLE(WIDGET_REGION) // Force an update since we know the scrollbars have changed things. if (renderer()->document()->hasDashboardRegions()) renderer()->document()->setDashboardRegionsDirty(true); @@ -2338,7 +2353,7 @@ void RenderLayer::setHasVerticalScrollbar(bool hasScrollbar) if (m_vBar) m_vBar->styleChanged(); -#if ENABLE(DASHBOARD_SUPPORT) +#if ENABLE(DASHBOARD_SUPPORT) || ENABLE(WIDGET_REGION) // Force an update since we know the scrollbars have changed things. if (renderer()->document()->hasDashboardRegions()) renderer()->document()->setDashboardRegionsDirty(true); @@ -2522,13 +2537,17 @@ void RenderLayer::updateScrollbarsAfterLayout() RenderBox* box = renderBox(); ASSERT(box); + // List box parts handle the scrollbars by themselves so we have nothing to do. + if (box->style()->appearance() == ListboxPart) + return; + bool hasHorizontalOverflow = this->hasHorizontalOverflow(); bool hasVerticalOverflow = this->hasVerticalOverflow(); // overflow:scroll should just enable/disable. - if (m_hBar && renderer()->style()->overflowX() == OSCROLL) + if (renderer()->style()->overflowX() == OSCROLL) m_hBar->setEnabled(hasHorizontalOverflow); - if (m_vBar && renderer()->style()->overflowY() == OSCROLL) + if (renderer()->style()->overflowY() == OSCROLL) m_vBar->setEnabled(hasVerticalOverflow); // overflow:auto may need to lay out again if scrollbars got added/removed. @@ -2543,7 +2562,7 @@ void RenderLayer::updateScrollbarsAfterLayout() updateSelfPaintingLayer(); -#if ENABLE(DASHBOARD_SUPPORT) +#if ENABLE(DASHBOARD_SUPPORT) || ENABLE(WIDGET_REGION) // Force an update since we know the scrollbars have changed things. if (renderer()->document()->hasDashboardRegions()) renderer()->document()->setDashboardRegionsDirty(true); @@ -4818,33 +4837,45 @@ void RenderLayer::updateStackingContextsAfterStyleChange(const RenderStyle* oldS } } -static bool overflowCanHaveAScrollbar(EOverflow overflow) +static bool overflowRequiresScrollbar(EOverflow overflow) { - return overflow == OAUTO || overflow == OSCROLL || overflow == OOVERLAY; + return overflow == OSCROLL; +} + +static bool overflowDefinesAutomaticScrollbar(EOverflow overflow) +{ + return overflow == OAUTO || overflow == OOVERLAY; } void RenderLayer::updateScrollbarsAfterStyleChange(const RenderStyle* oldStyle) { // Overflow are a box concept. - if (!renderBox()) + RenderBox* box = renderBox(); + if (!box) + return; + + // List box parts handle the scrollbars by themselves so we have nothing to do. + if (box->style()->appearance() == ListboxPart) return; - EOverflow overflowX = renderBox()->style()->overflowX(); - EOverflow overflowY = renderBox()->style()->overflowY(); - if (hasHorizontalScrollbar() && !overflowCanHaveAScrollbar(overflowX)) - setHasHorizontalScrollbar(false); - if (hasVerticalScrollbar() && !overflowCanHaveAScrollbar(overflowY)) - setHasVerticalScrollbar(false); + EOverflow overflowX = box->style()->overflowX(); + EOverflow overflowY = box->style()->overflowY(); + + // To avoid doing a relayout in updateScrollbarsAfterLayout, we try to keep any automatic scrollbar that was already present. + bool needsHorizontalScrollbar = (hasHorizontalScrollbar() && overflowDefinesAutomaticScrollbar(overflowX)) || overflowRequiresScrollbar(overflowX); + bool needsVerticalScrollbar = (hasVerticalScrollbar() && overflowDefinesAutomaticScrollbar(overflowY)) || overflowRequiresScrollbar(overflowY); + setHasHorizontalScrollbar(needsHorizontalScrollbar); + setHasVerticalScrollbar(needsVerticalScrollbar); // With overflow: scroll, scrollbars are always visible but may be disabled. // When switching to another value, we need to re-enable them (see bug 11985). - if (hasHorizontalScrollbar() && oldStyle->overflowX() == OSCROLL && overflowX != OSCROLL) { - ASSERT(overflowCanHaveAScrollbar(overflowX)); + if (needsHorizontalScrollbar && oldStyle && oldStyle->overflowX() == OSCROLL && overflowX != OSCROLL) { + ASSERT(hasHorizontalScrollbar()); m_hBar->setEnabled(true); } - if (hasVerticalScrollbar() && oldStyle->overflowY() == OSCROLL && overflowY != OSCROLL) { - ASSERT(overflowCanHaveAScrollbar(overflowY)); + if (needsVerticalScrollbar && oldStyle && oldStyle->overflowY() == OSCROLL && overflowY != OSCROLL) { + ASSERT(hasVerticalScrollbar()); m_vBar->setEnabled(true); } diff --git a/Source/WebCore/rendering/RenderLayer.h b/Source/WebCore/rendering/RenderLayer.h index be945707a..dd6df15a1 100644 --- a/Source/WebCore/rendering/RenderLayer.h +++ b/Source/WebCore/rendering/RenderLayer.h @@ -673,6 +673,7 @@ private: void dirtyAncestorChainHasSelfPaintingLayerDescendantStatus(); void computeRepaintRects(LayoutPoint* offsetFromRoot = 0); + void computeRepaintRectsIncludingDescendants(); void clearRepaintRects(); void clipToRect(RenderLayer* rootLayer, GraphicsContext*, const LayoutRect& paintDirtyRect, const ClipRect&, diff --git a/Source/WebCore/rendering/RenderLayerBacking.cpp b/Source/WebCore/rendering/RenderLayerBacking.cpp index 57b83e352..415891731 100644 --- a/Source/WebCore/rendering/RenderLayerBacking.cpp +++ b/Source/WebCore/rendering/RenderLayerBacking.cpp @@ -52,6 +52,7 @@ #include "RenderVideo.h" #include "RenderView.h" #include "ScrollingCoordinator.h" +#include "Settings.h" #include "StyleResolver.h" #include "TiledBacking.h" @@ -121,8 +122,11 @@ RenderLayerBacking::RenderLayerBacking(RenderLayer* layer) if (m_usingTiledCacheLayer) { if (Page* page = renderer()->frame()->page()) { if (TiledBacking* tiledBacking = m_graphicsLayer->tiledBacking()) { + Frame* frame = renderer()->frame(); + tiledBacking->setIsInWindow(page->isOnscreen()); - tiledBacking->setCanHaveScrollbars(renderer()->frame()->view()->canHaveScrollbars()); + tiledBacking->setCanHaveScrollbars(frame->view()->canHaveScrollbars()); + tiledBacking->setScrollingPerformanceLoggingEnabled(frame->settings() && frame->settings()->scrollingPerformanceLoggingEnabled()); } } } @@ -895,16 +899,23 @@ bool RenderLayerBacking::paintsChildren() const return false; } +static bool isCompositedPlugin(RenderObject* renderer) +{ + return renderer->isEmbeddedObject() && toRenderEmbeddedObject(renderer)->allowsAcceleratedCompositing(); +} + // A "simple container layer" is a RenderLayer which has no visible content to render. // It may have no children, or all its children may be themselves composited. // This is a useful optimization, because it allows us to avoid allocating backing store. bool RenderLayerBacking::isSimpleContainerCompositingLayer() const { RenderObject* renderObject = renderer(); - if (renderObject->isReplaced() || // replaced objects are not containers - renderObject->hasMask()) // masks require special treatment + if (renderObject->hasMask()) // masks require special treatment return false; + if (renderObject->isReplaced() && !isCompositedPlugin(renderObject)) + return false; + if (paintsBoxDecorations() || paintsChildren()) return false; @@ -1619,6 +1630,20 @@ double RenderLayerBacking::backingStoreMemoryEstimate() const return backingMemory; } +#if PLATFORM(BLACKBERRY) +bool RenderLayerBacking::contentsVisible(const GraphicsLayer*, const IntRect& localContentRect) const +{ + Frame* frame = renderer()->frame(); + FrameView* view = frame ? frame->view() : 0; + if (!view) + return false; + + IntRect visibleContentRect(view->visibleContentRect()); + FloatQuad absoluteContentQuad = renderer()->localToAbsoluteQuad(FloatRect(localContentRect)); + return absoluteContentQuad.enclosingBoundingBox().intersects(visibleContentRect); +} +#endif + } // namespace WebCore #endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/rendering/RenderLayerCompositor.cpp b/Source/WebCore/rendering/RenderLayerCompositor.cpp index c3cf9835f..6062aaec8 100644 --- a/Source/WebCore/rendering/RenderLayerCompositor.cpp +++ b/Source/WebCore/rendering/RenderLayerCompositor.cpp @@ -494,11 +494,10 @@ bool RenderLayerCompositor::updateBacking(RenderLayer* layer, CompositingChangeR layer->ensureBacking(); - // The RenderLayer's needs to update repaint rects here, because the target - // repaintContainer may have changed after becoming a composited layer. - // https://bugs.webkit.org/show_bug.cgi?id=80641 + // This layer and all of its descendants have cached repaints rects that are relative to + // the repaint container, so change when compositing changes; we need to update them here. if (layer->parent()) - layer->computeRepaintRects(); + layer->computeRepaintRectsIncludingDescendants(); layerChanged = true; } @@ -518,9 +517,9 @@ bool RenderLayerCompositor::updateBacking(RenderLayer* layer, CompositingChangeR layer->clearBacking(); layerChanged = true; - // The layer's cached repaints rects are relative to the repaint container, so change when - // compositing changes; we need to update them here. - layer->computeRepaintRects(); + // This layer and all of its descendants have cached repaints rects that are relative to + // the repaint container, so change when compositing changes; we need to update them here. + layer->computeRepaintRectsIncludingDescendants(); // If we need to repaint, do so now that we've removed the backing if (shouldRepaint == CompositingChangeRepaintNow) diff --git a/Source/WebCore/rendering/RenderListBox.cpp b/Source/WebCore/rendering/RenderListBox.cpp index 40b5f58fd..2f5ae2b6c 100644 --- a/Source/WebCore/rendering/RenderListBox.cpp +++ b/Source/WebCore/rendering/RenderListBox.cpp @@ -146,6 +146,11 @@ void RenderListBox::updateFromElement() } } +bool RenderListBox::canBeReplacedWithInlineRunIn() const +{ + return false; +} + void RenderListBox::selectionChanged() { repaint(); @@ -378,7 +383,9 @@ void RenderListBox::paintItemForeground(PaintInfo& paintInfo, const LayoutPoint& { FontCachePurgePreventer fontCachePurgePreventer; - const Vector<HTMLElement*>& listItems = toHTMLSelectElement(node())->listItems(); + HTMLSelectElement* selectElement = toHTMLSelectElement(node()); + + const Vector<HTMLElement*>& listItems = selectElement->listItems(); HTMLElement* element = listItems[listIndex]; RenderStyle* itemStyle = element->renderStyle(); @@ -401,7 +408,7 @@ void RenderListBox::paintItemForeground(PaintInfo& paintInfo, const LayoutPoint& if (frame()->selection()->isFocusedAndActive() && document()->focusedNode() == node()) textColor = theme()->activeListBoxSelectionForegroundColor(); // Honor the foreground color for disabled items - else if (!element->disabled()) + else if (!element->disabled() && !selectElement->disabled()) textColor = theme()->inactiveListBoxSelectionForegroundColor(); } @@ -620,6 +627,11 @@ void RenderListBox::setScrollOffset(const IntPoint& offset) scrollTo(offset.y()); } +IntPoint RenderListBox::scrollPosition() const +{ + return IntPoint(0, m_indexOffset); +} + void RenderListBox::scrollTo(int newOffset) { if (newOffset == m_indexOffset) @@ -864,7 +876,7 @@ void RenderListBox::setHasVerticalScrollbar(bool hasScrollbar) if (m_vBar) m_vBar->styleChanged(); -#if ENABLE(DASHBOARD_SUPPORT) +#if ENABLE(DASHBOARD_SUPPORT) || ENABLE(WIDGET_REGION) // Force an update since we know the scrollbars have changed things. if (document()->hasDashboardRegions()) document()->setDashboardRegionsDirty(true); diff --git a/Source/WebCore/rendering/RenderListBox.h b/Source/WebCore/rendering/RenderListBox.h index 10b1945c2..6038c4316 100644 --- a/Source/WebCore/rendering/RenderListBox.h +++ b/Source/WebCore/rendering/RenderListBox.h @@ -61,7 +61,7 @@ private: virtual bool isListBox() const { return true; } virtual void updateFromElement(); - + virtual bool canBeReplacedWithInlineRunIn() const OVERRIDE; virtual bool hasControlClip() const { return true; } virtual void paintObject(PaintInfo&, const LayoutPoint&); virtual LayoutRect controlClipRect(const LayoutPoint&) const; @@ -100,6 +100,7 @@ private: virtual int scrollSize(ScrollbarOrientation) const; virtual int scrollPosition(Scrollbar*) const; virtual void setScrollOffset(const IntPoint&); + virtual IntPoint scrollPosition() const OVERRIDE; virtual void invalidateScrollbarRect(Scrollbar*, const IntRect&); virtual bool isActive() const; virtual bool isScrollCornerVisible() const { return false; } // We don't support resize on list boxes yet. If we did these would have to change. diff --git a/Source/WebCore/rendering/RenderMenuList.cpp b/Source/WebCore/rendering/RenderMenuList.cpp index 56eccf8a1..521cc0327 100644 --- a/Source/WebCore/rendering/RenderMenuList.cpp +++ b/Source/WebCore/rendering/RenderMenuList.cpp @@ -74,6 +74,11 @@ RenderMenuList::~RenderMenuList() m_popup = 0; } +bool RenderMenuList::canBeReplacedWithInlineRunIn() const +{ + return false; +} + void RenderMenuList::createInnerBlock() { if (m_innerBlock) { diff --git a/Source/WebCore/rendering/RenderMenuList.h b/Source/WebCore/rendering/RenderMenuList.h index 7466b1ff9..0b4300840 100644 --- a/Source/WebCore/rendering/RenderMenuList.h +++ b/Source/WebCore/rendering/RenderMenuList.h @@ -68,6 +68,7 @@ private: virtual LayoutRect controlClipRect(const LayoutPoint&) const; virtual bool hasControlClip() const { return true; } virtual bool canHaveGeneratedChildren() const OVERRIDE { return false; } + virtual bool canBeReplacedWithInlineRunIn() const OVERRIDE; virtual const char* renderName() const { return "RenderMenuList"; } diff --git a/Source/WebCore/rendering/RenderNamedFlowThread.cpp b/Source/WebCore/rendering/RenderNamedFlowThread.cpp index 227af7df5..5b02453e4 100644 --- a/Source/WebCore/rendering/RenderNamedFlowThread.cpp +++ b/Source/WebCore/rendering/RenderNamedFlowThread.cpp @@ -36,6 +36,7 @@ namespace WebCore { RenderNamedFlowThread::RenderNamedFlowThread(Node* node, PassRefPtr<WebKitNamedFlow> namedFlow) : RenderFlowThread(node) , m_namedFlow(namedFlow) + , m_regionLayoutUpdateEventTimer(this, &RenderNamedFlowThread::regionLayoutUpdateEventTimerFired) { m_namedFlow->setRenderer(this); } @@ -192,6 +193,10 @@ void RenderNamedFlowThread::removeRegionFromThread(RenderRegion* renderRegion) return; } + // After removing all the regions in the flow the following layout needs to dispatch the regionLayoutUpdate event + if (m_regionList.isEmpty()) + setDispatchRegionLayoutUpdateEvent(true); + invalidateRegions(); } @@ -301,4 +306,19 @@ void RenderNamedFlowThread::willBeDestroyed() RenderFlowThread::willBeDestroyed(); } +void RenderNamedFlowThread::dispatchRegionLayoutUpdateEvent() +{ + RenderFlowThread::dispatchRegionLayoutUpdateEvent(); + + if (!m_regionLayoutUpdateEventTimer.isActive() && m_namedFlow->hasEventListeners()) + m_regionLayoutUpdateEventTimer.startOneShot(0); +} + +void RenderNamedFlowThread::regionLayoutUpdateEventTimerFired(Timer<RenderNamedFlowThread>*) +{ + ASSERT(m_namedFlow); + + m_namedFlow->dispatchRegionLayoutUpdateEvent(); +} + } diff --git a/Source/WebCore/rendering/RenderNamedFlowThread.h b/Source/WebCore/rendering/RenderNamedFlowThread.h index 5e0d96249..4101b771e 100644 --- a/Source/WebCore/rendering/RenderNamedFlowThread.h +++ b/Source/WebCore/rendering/RenderNamedFlowThread.h @@ -28,6 +28,7 @@ #define RenderNamedFlowThread_h #include "RenderFlowThread.h" +#include "Timer.h" #include <wtf/HashCountedSet.h> #include <wtf/ListHashSet.h> #include <wtf/text/AtomicString.h> @@ -76,11 +77,14 @@ private: virtual const char* renderName() const OVERRIDE; virtual bool isRenderNamedFlowThread() const OVERRIDE { return true; } + virtual void dispatchRegionLayoutUpdateEvent() OVERRIDE; + bool dependsOn(RenderNamedFlowThread* otherRenderFlowThread) const; void addDependencyOnFlowThread(RenderNamedFlowThread*); void removeDependencyOnFlowThread(RenderNamedFlowThread*); void checkInvalidRegions(); bool canBeDestroyed() const { return m_regionList.isEmpty() && m_contentNodes.isEmpty(); } + void regionLayoutUpdateEventTimerFired(Timer<RenderNamedFlowThread>*); private: // Observer flow threads have invalid regions that depend on the state of this thread @@ -101,6 +105,8 @@ private: // The DOM Object that represents a named flow. RefPtr<WebKitNamedFlow> m_namedFlow; + + Timer<RenderNamedFlowThread> m_regionLayoutUpdateEventTimer; }; inline RenderNamedFlowThread* toRenderNamedFlowThread(RenderObject* object) diff --git a/Source/WebCore/rendering/RenderObject.cpp b/Source/WebCore/rendering/RenderObject.cpp index 6391334ef..b5f69575a 100755 --- a/Source/WebCore/rendering/RenderObject.cpp +++ b/Source/WebCore/rendering/RenderObject.cpp @@ -151,7 +151,7 @@ RenderObject* RenderObject::createObject(Node* node, RenderStyle* style) if (node->hasTagName(rtTag) && style->display() == BLOCK) return new (arena) RenderRubyText(node); if (doc->cssRegionsEnabled() && style->isDisplayRegionType() && !style->regionThread().isEmpty() && doc->renderView()) - return new (arena) RenderRegion(node, doc->renderView()->flowThreadController()->ensureRenderFlowThreadWithName(style->regionThread())); + return new (arena) RenderRegion(node, 0); switch (style->display()) { case NONE: return 0; @@ -834,14 +834,22 @@ void RenderObject::drawLineForBoxSide(GraphicsContext* graphicsContext, int x1, BoxSide side, Color color, EBorderStyle style, int adjacentWidth1, int adjacentWidth2, bool antialias) { - int width = (side == BSTop || side == BSBottom ? y2 - y1 : x2 - x1); + int thickness; + int length; + if (side == BSTop || side == BSBottom) { + thickness = y2 - y1; + length = x2 - x1; + } else { + thickness = x2 - x1; + length = y2 - y1; + } - // FIXME: We really would like this check to be an ASSERT as we don't want to draw 0px borders. However - // nothing guarantees that the following recursive calls to drawLineForBoxSide will have non-null width. - if (!width) + // FIXME: We really would like this check to be an ASSERT as we don't want to draw empty borders. However + // nothing guarantees that the following recursive calls to drawLineForBoxSide will have non-null dimensions. + if (!thickness || !length) return; - if (style == DOUBLE && width < 3) + if (style == DOUBLE && thickness < 3) style = SOLID; switch (style) { @@ -851,11 +859,11 @@ void RenderObject::drawLineForBoxSide(GraphicsContext* graphicsContext, int x1, case DOTTED: case DASHED: { graphicsContext->setStrokeColor(color, m_style->colorSpace()); - graphicsContext->setStrokeThickness(width); + graphicsContext->setStrokeThickness(thickness); StrokeStyle oldStrokeStyle = graphicsContext->strokeStyle(); graphicsContext->setStrokeStyle(style == DASHED ? DashedStroke : DottedStroke); - if (width > 0) { + if (thickness > 0) { bool wasAntialiased = graphicsContext->shouldAntialias(); graphicsContext->setShouldAntialias(antialias); @@ -875,7 +883,8 @@ void RenderObject::drawLineForBoxSide(GraphicsContext* graphicsContext, int x1, break; } case DOUBLE: { - int third = (width + 1) / 3; + int thirdOfThickness = (thickness + 1) / 3; + ASSERT(thirdOfThickness); if (adjacentWidth1 == 0 && adjacentWidth2 == 0) { StrokeStyle oldStrokeStyle = graphicsContext->strokeStyle(); @@ -888,16 +897,16 @@ void RenderObject::drawLineForBoxSide(GraphicsContext* graphicsContext, int x1, switch (side) { case BSTop: case BSBottom: - graphicsContext->drawRect(IntRect(x1, y1, x2 - x1, third)); - graphicsContext->drawRect(IntRect(x1, y2 - third, x2 - x1, third)); + graphicsContext->drawRect(IntRect(x1, y1, length, thirdOfThickness)); + graphicsContext->drawRect(IntRect(x1, y2 - thirdOfThickness, length, thirdOfThickness)); break; case BSLeft: - graphicsContext->drawRect(IntRect(x1, y1 + 1, third, y2 - y1 - 1)); - graphicsContext->drawRect(IntRect(x2 - third, y1 + 1, third, y2 - y1 - 1)); - break; case BSRight: - graphicsContext->drawRect(IntRect(x1, y1 + 1, third, y2 - y1 - 1)); - graphicsContext->drawRect(IntRect(x2 - third, y1 + 1, third, y2 - y1 - 1)); + // FIXME: Why do we offset the border by 1 in this case but not the other one? + if (length > 1) { + graphicsContext->drawRect(IntRect(x1, y1 + 1, thirdOfThickness, length - 1)); + graphicsContext->drawRect(IntRect(x2 - thirdOfThickness, y1 + 1, thirdOfThickness, length - 1)); + } break; } @@ -910,33 +919,33 @@ void RenderObject::drawLineForBoxSide(GraphicsContext* graphicsContext, int x1, switch (side) { case BSTop: drawLineForBoxSide(graphicsContext, x1 + max((-adjacentWidth1 * 2 + 1) / 3, 0), - y1, x2 - max((-adjacentWidth2 * 2 + 1) / 3, 0), y1 + third, + y1, x2 - max((-adjacentWidth2 * 2 + 1) / 3, 0), y1 + thirdOfThickness, side, color, SOLID, adjacent1BigThird, adjacent2BigThird, antialias); drawLineForBoxSide(graphicsContext, x1 + max((adjacentWidth1 * 2 + 1) / 3, 0), - y2 - third, x2 - max((adjacentWidth2 * 2 + 1) / 3, 0), y2, + y2 - thirdOfThickness, x2 - max((adjacentWidth2 * 2 + 1) / 3, 0), y2, side, color, SOLID, adjacent1BigThird, adjacent2BigThird, antialias); break; case BSLeft: drawLineForBoxSide(graphicsContext, x1, y1 + max((-adjacentWidth1 * 2 + 1) / 3, 0), - x1 + third, y2 - max((-adjacentWidth2 * 2 + 1) / 3, 0), + x1 + thirdOfThickness, y2 - max((-adjacentWidth2 * 2 + 1) / 3, 0), side, color, SOLID, adjacent1BigThird, adjacent2BigThird, antialias); - drawLineForBoxSide(graphicsContext, x2 - third, y1 + max((adjacentWidth1 * 2 + 1) / 3, 0), + drawLineForBoxSide(graphicsContext, x2 - thirdOfThickness, y1 + max((adjacentWidth1 * 2 + 1) / 3, 0), x2, y2 - max((adjacentWidth2 * 2 + 1) / 3, 0), side, color, SOLID, adjacent1BigThird, adjacent2BigThird, antialias); break; case BSBottom: drawLineForBoxSide(graphicsContext, x1 + max((adjacentWidth1 * 2 + 1) / 3, 0), - y1, x2 - max((adjacentWidth2 * 2 + 1) / 3, 0), y1 + third, + y1, x2 - max((adjacentWidth2 * 2 + 1) / 3, 0), y1 + thirdOfThickness, side, color, SOLID, adjacent1BigThird, adjacent2BigThird, antialias); drawLineForBoxSide(graphicsContext, x1 + max((-adjacentWidth1 * 2 + 1) / 3, 0), - y2 - third, x2 - max((-adjacentWidth2 * 2 + 1) / 3, 0), y2, + y2 - thirdOfThickness, x2 - max((-adjacentWidth2 * 2 + 1) / 3, 0), y2, side, color, SOLID, adjacent1BigThird, adjacent2BigThird, antialias); break; case BSRight: drawLineForBoxSide(graphicsContext, x1, y1 + max((adjacentWidth1 * 2 + 1) / 3, 0), - x1 + third, y2 - max((adjacentWidth2 * 2 + 1) / 3, 0), + x1 + thirdOfThickness, y2 - max((adjacentWidth2 * 2 + 1) / 3, 0), side, color, SOLID, adjacent1BigThird, adjacent2BigThird, antialias); - drawLineForBoxSide(graphicsContext, x2 - third, y1 + max((-adjacentWidth1 * 2 + 1) / 3, 0), + drawLineForBoxSide(graphicsContext, x2 - thirdOfThickness, y1 + max((-adjacentWidth1 * 2 + 1) / 3, 0), x2, y2 - max((-adjacentWidth2 * 2 + 1) / 3, 0), side, color, SOLID, adjacent1BigThird, adjacent2BigThird, antialias); break; @@ -1444,10 +1453,7 @@ void RenderObject::repaintOverhangingFloats(bool) bool RenderObject::checkForRepaintDuringLayout() const { - // FIXME: <https://bugs.webkit.org/show_bug.cgi?id=20885> It is probably safe to also require - // m_everHadLayout. Currently, only RenderBlock::layoutBlock() adds this condition. See also - // <https://bugs.webkit.org/show_bug.cgi?id=15129>. - return !document()->view()->needsFullRepaint() && !hasLayer(); + return !document()->view()->needsFullRepaint() && !hasLayer() && everHadLayout(); } LayoutRect RenderObject::rectWithOutlineForRepaint(RenderBoxModelObject* repaintContainer, LayoutUnit outlineWidth) const @@ -1787,7 +1793,7 @@ void RenderObject::styleWillChange(StyleDifference diff, const RenderStyle* newS bool visibilityChanged = m_style->visibility() != newStyle->visibility() || m_style->zIndex() != newStyle->zIndex() || m_style->hasAutoZIndex() != newStyle->hasAutoZIndex(); -#if ENABLE(DASHBOARD_SUPPORT) +#if ENABLE(DASHBOARD_SUPPORT) || ENABLE(WIDGET_REGION) if (visibilityChanged) document()->setDashboardRegionsDirty(true); #endif @@ -1978,7 +1984,12 @@ LayoutRect RenderObject::viewRect() const FloatPoint RenderObject::localToAbsolute(const FloatPoint& localPoint, bool fixed, bool useTransforms) const { TransformState transformState(TransformState::ApplyTransformDirection, localPoint); - mapLocalToContainer(0, fixed, useTransforms, transformState); + MapLocalToContainerFlags mode = ApplyContainerFlip; + if (fixed) + mode |= IsFixed; + if (useTransforms) + mode |= UseTransforms; + mapLocalToContainer(0, transformState, mode); transformState.flatten(); return transformState.lastPlanarPoint(); @@ -1993,7 +2004,7 @@ FloatPoint RenderObject::absoluteToLocal(const FloatPoint& containerPoint, bool return transformState.lastPlanarPoint(); } -void RenderObject::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed, bool useTransforms, TransformState& transformState, ApplyContainerFlipOrNot applyContainerFlip, bool* wasFixed) const +void RenderObject::mapLocalToContainer(RenderBoxModelObject* repaintContainer, TransformState& transformState, MapLocalToContainerFlags mode, bool* wasFixed) const { if (repaintContainer == this) return; @@ -2004,10 +2015,10 @@ void RenderObject::mapLocalToContainer(RenderBoxModelObject* repaintContainer, b // FIXME: this should call offsetFromContainer to share code, but I'm not sure it's ever called. LayoutPoint centerPoint = roundedLayoutPoint(transformState.mappedPoint()); - if (applyContainerFlip && o->isBox()) { + if (mode & ApplyContainerFlip && o->isBox()) { if (o->style()->isFlippedBlocksWritingMode()) transformState.move(toRenderBox(o)->flipForWritingModeIncludingColumns(roundedLayoutPoint(transformState.mappedPoint())) - centerPoint); - applyContainerFlip = DoNotApplyContainerFlip; + mode &= ~ApplyContainerFlip; } LayoutSize columnOffset; @@ -2018,7 +2029,7 @@ void RenderObject::mapLocalToContainer(RenderBoxModelObject* repaintContainer, b if (o->hasOverflowClip()) transformState.move(-toRenderBox(o)->scrolledContentOffset()); - o->mapLocalToContainer(repaintContainer, fixed, useTransforms, transformState, applyContainerFlip, wasFixed); + o->mapLocalToContainer(repaintContainer, transformState, mode, wasFixed); } const RenderObject* RenderObject::pushMappingToContainer(const RenderBoxModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap) const @@ -2092,7 +2103,10 @@ FloatQuad RenderObject::localToContainerQuad(const FloatQuad& localQuad, RenderB // Track the point at the center of the quad's bounding box. As mapLocalToContainer() calls offsetFromContainer(), // it will use that point as the reference point to decide which column's transform to apply in multiple-column blocks. TransformState transformState(TransformState::ApplyTransformDirection, localQuad.boundingBox().center(), localQuad); - mapLocalToContainer(repaintContainer, fixed, true, transformState, ApplyContainerFlip, wasFixed); + MapLocalToContainerFlags mode = ApplyContainerFlip | UseTransforms; + if (fixed) + mode |= IsFixed; + mapLocalToContainer(repaintContainer, transformState, mode, wasFixed); transformState.flatten(); return transformState.lastPlanarQuad(); @@ -2101,7 +2115,10 @@ FloatQuad RenderObject::localToContainerQuad(const FloatQuad& localQuad, RenderB FloatPoint RenderObject::localToContainerPoint(const FloatPoint& localPoint, RenderBoxModelObject* repaintContainer, bool fixed, bool* wasFixed) const { TransformState transformState(TransformState::ApplyTransformDirection, localPoint); - mapLocalToContainer(repaintContainer, fixed, true, transformState, ApplyContainerFlip, wasFixed); + MapLocalToContainerFlags mode = ApplyContainerFlip | UseTransforms; + if (fixed) + mode |= IsFixed; + mapLocalToContainer(repaintContainer, transformState, mode, wasFixed); transformState.flatten(); return transformState.lastPlanarPoint(); @@ -2632,7 +2649,7 @@ void RenderObject::getTextDecorationColors(int decorations, Color& underline, Co } } -#if ENABLE(DASHBOARD_SUPPORT) +#if ENABLE(DASHBOARD_SUPPORT) || ENABLE(WIDGET_REGION) void RenderObject::addDashboardRegions(Vector<DashboardRegionValue>& regions) { // Convert the style regions to absolute coordinates. @@ -2890,6 +2907,11 @@ bool RenderObject::canHaveGeneratedChildren() const return canHaveChildren(); } +bool RenderObject::canBeReplacedWithInlineRunIn() const +{ + return true; +} + #if ENABLE(SVG) RenderSVGResourceContainer* RenderObject::toRenderSVGResourceContainer() diff --git a/Source/WebCore/rendering/RenderObject.h b/Source/WebCore/rendering/RenderObject.h index 2dcd62e5d..5ef90fc0e 100644 --- a/Source/WebCore/rendering/RenderObject.h +++ b/Source/WebCore/rendering/RenderObject.h @@ -26,8 +26,7 @@ #ifndef RenderObject_h #define RenderObject_h -#include "CachedImage.h" -#include "Document.h" +#include "CachedImageClient.h" #include "Element.h" #include "FractionalLayoutUnit.h" #include "FloatQuad.h" @@ -46,6 +45,7 @@ namespace WebCore { class AffineTransform; class AnimationController; class Cursor; +class Document; class HitTestPoint; class HitTestResult; class InlineBox; @@ -107,9 +107,16 @@ enum PlaceGeneratedRunInFlag { DoNotPlaceGeneratedRunIn }; +enum MapLocalToContainerMode { + IsFixed = 1 << 0, + UseTransforms = 1 << 1, + ApplyContainerFlip = 1 << 2 +}; +typedef unsigned MapLocalToContainerFlags; + const int caretWidth = 1; -#if ENABLE(DASHBOARD_SUPPORT) +#if ENABLE(DASHBOARD_SUPPORT) || ENABLE(WIDGET_REGION) struct DashboardRegionValue { bool operator==(const DashboardRegionValue& o) const { @@ -636,7 +643,7 @@ public: // repaint and do not need a relayout virtual void updateFromElement() { } -#if ENABLE(DASHBOARD_SUPPORT) +#if ENABLE(DASHBOARD_SUPPORT) || ENABLE(WIDGET_REGION) virtual void addDashboardRegions(Vector<DashboardRegionValue>&); void collectDashboardRegions(Vector<DashboardRegionValue>&); #endif @@ -844,7 +851,6 @@ public: // Virtual function helpers for the deprecated Flexible Box Layout (display: -webkit-box). virtual bool isDeprecatedFlexibleBox() const { return false; } - virtual bool isFlexingChildren() const { return false; } virtual bool isStretchingChildren() const { return false; } // Virtual function helper for the new FlexibleBox Layout (display: -webkit-flex). @@ -878,8 +884,7 @@ public: // Map points and quads through elements, potentially via 3d transforms. You should never need to call these directly; use // localToAbsolute/absoluteToLocal methods instead. - enum ApplyContainerFlipOrNot { DoNotApplyContainerFlip, ApplyContainerFlip }; - virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool useTransforms, bool fixed, TransformState&, ApplyContainerFlipOrNot = ApplyContainerFlip, bool* wasFixed = 0) const; + virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, TransformState&, MapLocalToContainerFlags mode = ApplyContainerFlip, bool* wasFixed = 0) const; virtual void mapAbsoluteToLocalPoint(bool fixed, bool useTransforms, TransformState&) const; // Pushes state onto RenderGeometryMap about how to map coordinates from this renderer to its container, or ancestorToStopAt (whichever is encountered first). @@ -927,6 +932,8 @@ protected: virtual LayoutRect outlineBoundsForRepaint(RenderBoxModelObject* /*repaintContainer*/, LayoutPoint* /*cachedOffsetToRepaintContainer*/ = 0) const { return LayoutRect(); } + virtual bool canBeReplacedWithInlineRunIn() const; + private: RenderStyle* firstLineStyleSlowCase() const; StyleDifference adjustStyleDifference(StyleDifference, unsigned contextSensitiveProperties) const; diff --git a/Source/WebCore/rendering/RenderObjectChildList.cpp b/Source/WebCore/rendering/RenderObjectChildList.cpp index da98088e2..3158fbfb6 100644 --- a/Source/WebCore/rendering/RenderObjectChildList.cpp +++ b/Source/WebCore/rendering/RenderObjectChildList.cpp @@ -117,6 +117,9 @@ RenderObject* RenderObjectChildList::removeChildNode(RenderObject* owner, Render if (oldChild->isRenderRegion()) toRenderRegion(oldChild)->detachRegion(); + if (oldChild->isQuote()) + toRenderQuote(oldChild)->detachQuote(); + if (oldChild->inRenderFlowThread()) { if (oldChild->isBox()) oldChild->enclosingRenderFlowThread()->removeRenderBoxRegionInfo(toRenderBox(oldChild)); @@ -158,7 +161,6 @@ RenderObject* RenderObjectChildList::removeChildNode(RenderObject* owner, Render // by skipping this step when destroying the entire tree. if (!owner->documentBeingDestroyed()) { RenderCounter::rendererRemovedFromTree(oldChild); - RenderQuote::rendererRemovedFromTree(oldChild); } if (AXObjectCache::accessibilityEnabled()) @@ -210,13 +212,16 @@ void RenderObjectChildList::appendChildNode(RenderObject* owner, RenderObject* n if (newChild->isRenderRegion()) toRenderRegion(newChild)->attachRegion(); + // You can't attachQuote() otherwise the quote would be attached too early + // and get the wrong depth since generated content is inserted into anonymous + // renderers before going into the main render tree. + if (RenderNamedFlowThread* containerFlowThread = renderNamedFlowThreadContainer(owner)) containerFlowThread->addFlowChild(newChild); } if (!owner->documentBeingDestroyed()) { RenderCounter::rendererSubtreeAttached(newChild); - RenderQuote::rendererSubtreeAttached(newChild); } newChild->setNeedsLayoutAndPrefWidthsRecalc(); // Goes up the containing block hierarchy. if (!owner->normalChildNeedsLayout()) @@ -279,13 +284,15 @@ void RenderObjectChildList::insertChildNode(RenderObject* owner, RenderObject* c if (child->isRenderRegion()) toRenderRegion(child)->attachRegion(); + // Calling attachQuote() here would be too early (before anonymous renderers are inserted) + // see appendChild() for more explanation. + if (RenderNamedFlowThread* containerFlowThread = renderNamedFlowThreadContainer(owner)) containerFlowThread->addFlowChild(child, beforeChild); } if (!owner->documentBeingDestroyed()) { RenderCounter::rendererSubtreeAttached(child); - RenderQuote::rendererSubtreeAttached(child); } child->setNeedsLayoutAndPrefWidthsRecalc(); if (!owner->normalChildNeedsLayout()) diff --git a/Source/WebCore/rendering/RenderProgress.cpp b/Source/WebCore/rendering/RenderProgress.cpp index d004506a3..7243e96dc 100644 --- a/Source/WebCore/rendering/RenderProgress.cpp +++ b/Source/WebCore/rendering/RenderProgress.cpp @@ -33,7 +33,7 @@ using namespace std; namespace WebCore { -RenderProgress::RenderProgress(HTMLProgressElement* element) +RenderProgress::RenderProgress(HTMLElement* element) : RenderBlock(element) , m_position(HTMLProgressElement::InvalidPosition) , m_animationStartTime(0) @@ -59,6 +59,11 @@ void RenderProgress::updateFromElement() RenderBlock::updateFromElement(); } +bool RenderProgress::canBeReplacedWithInlineRunIn() const +{ + return false; +} + double RenderProgress::animationProgress() const { return m_animating ? (fmod((currentTime() - m_animationStartTime), m_animationDuration) / m_animationDuration) : 0; @@ -97,7 +102,14 @@ void RenderProgress::updateAnimationState() HTMLProgressElement* RenderProgress::progressElement() const { - return static_cast<HTMLProgressElement*>(node()); + if (!node()) + return 0; + + if (isHTMLProgressElement(node())) + return toHTMLProgressElement(node()); + + ASSERT(node()->shadowHost()); + return toHTMLProgressElement(node()->shadowHost()); } } // namespace WebCore diff --git a/Source/WebCore/rendering/RenderProgress.h b/Source/WebCore/rendering/RenderProgress.h index 96921bdb4..6835e48c8 100644 --- a/Source/WebCore/rendering/RenderProgress.h +++ b/Source/WebCore/rendering/RenderProgress.h @@ -30,7 +30,7 @@ class HTMLProgressElement; class RenderProgress : public RenderBlock { public: - RenderProgress(HTMLProgressElement*); + RenderProgress(HTMLElement*); virtual ~RenderProgress(); double position() const { return m_position; } @@ -38,6 +38,7 @@ public: double animationStartTime() const { return m_animationStartTime; } bool isDeterminate() const; + virtual void updateFromElement(); HTMLProgressElement* progressElement() const; @@ -45,7 +46,7 @@ private: virtual const char* renderName() const { return "RenderProgress"; } virtual bool isProgress() const { return true; } virtual bool requiresForcedStyleRecalcPropagation() const { return true; } - virtual void updateFromElement(); + virtual bool canBeReplacedWithInlineRunIn() const OVERRIDE; void animationTimerFired(Timer<RenderProgress>*); void updateAnimationState(); diff --git a/Source/WebCore/rendering/RenderQuote.cpp b/Source/WebCore/rendering/RenderQuote.cpp index 79da0d20d..e17a044a4 100644 --- a/Source/WebCore/rendering/RenderQuote.cpp +++ b/Source/WebCore/rendering/RenderQuote.cpp @@ -21,321 +21,189 @@ #include "config.h" #include "RenderQuote.h" -#include "Document.h" -#include "Element.h" -#include "HTMLElement.h" -#include "QuotesData.h" -#include "RenderStyle.h" -#include <algorithm> #include <wtf/text/AtomicString.h> -#include <wtf/text/CString.h> -#define UNKNOWN_DEPTH -1 +#define U(x) ((const UChar*)L##x) namespace WebCore { -static inline void adjustDepth(int &depth, QuoteType type) -{ - switch (type) { - case OPEN_QUOTE: - case NO_OPEN_QUOTE: - ++depth; - break; - case CLOSE_QUOTE: - case NO_CLOSE_QUOTE: - if (depth) - --depth; - break; - default: - ASSERT_NOT_REACHED(); - } -} RenderQuote::RenderQuote(Document* node, QuoteType quote) : RenderText(node, StringImpl::empty()) , m_type(quote) - , m_depth(UNKNOWN_DEPTH) + , m_depth(0) , m_next(0) , m_previous(0) + , m_attached(false) { - view()->addRenderQuote(); } RenderQuote::~RenderQuote() { + ASSERT(!m_attached); + ASSERT(!m_next && !m_previous); } void RenderQuote::willBeDestroyed() { - if (view()) - view()->removeRenderQuote(); + detachQuote(); RenderText::willBeDestroyed(); } -const char* RenderQuote::renderName() const -{ - return "RenderQuote"; -} - -// This function places a list of quote renderers starting at "this" in the list of quote renderers already -// in the document's renderer tree. -// The assumptions are made (for performance): -// 1. The list of quotes already in the renderers tree of the document is already in a consistent state -// (All quote renderers are linked and have the correct depth set) -// 2. The quote renderers of the inserted list are in a tree of renderers of their own which has been just -// inserted in the main renderer tree with its root as child of some renderer. -// 3. The quote renderers in the inserted list have depths consistent with their position in the list relative -// to "this", thus if "this" does not need to change its depth upon insertion, the other renderers in the list don't -// need to either. -void RenderQuote::placeQuote() -{ - RenderQuote* head = this; - ASSERT(!head->m_previous); - RenderQuote* tail = 0; - for (RenderObject* predecessor = head->previousInPreOrder(); predecessor; predecessor = predecessor->previousInPreOrder()) { - if (!predecessor->isQuote()) - continue; - head->m_previous = toRenderQuote(predecessor); - if (head->m_previous->m_next) { - // We need to splice the list of quotes headed by head into the document's list of quotes. - tail = head; - while (tail->m_next) - tail = tail->m_next; - tail->m_next = head->m_previous->m_next; - ASSERT(tail->m_next->m_previous == head->m_previous); - tail->m_next->m_previous = tail; - tail = tail->m_next; // This marks the splicing point here there may be a depth discontinuity - } - head->m_previous->m_next = head; - ASSERT(head->m_previous->m_depth != UNKNOWN_DEPTH); - break; - } - int newDepth; - if (!head->m_previous) { - newDepth = 0; - goto skipNewDepthCalc; - } - newDepth = head->m_previous->m_depth; - do { - adjustDepth(newDepth, head->m_previous->m_type); -skipNewDepthCalc: - if (head->m_depth == newDepth) { // All remaining depth should be correct except if splicing was done. - if (!tail) // We've done the post splicing section already or there was no splicing. - break; - head = tail; // Continue after the splicing point - tail = 0; // Mark the possible splicing point discontinuity fixed. - newDepth = head->m_previous->m_depth; - continue; - } - head->m_depth = newDepth; - // FIXME: If the width and height of the quotation characters does not change we may only need to - // Invalidate the renderer's area not a relayout. - head->setNeedsLayoutAndPrefWidthsRecalc(); - head = head->m_next; - if (head == tail) // We are at the splicing point - tail = 0; // Mark the possible depth discontinuity fixed. - } while (head); -} - -#define ARRAY_SIZE(Carray) (sizeof(Carray) / sizeof(*Carray)) -#define LANGUAGE_DATA(name, languageSourceArray) { name, languageSourceArray, ARRAY_SIZE(languageSourceArray) } -#define U(x) ((const UChar*)L##x) - -static const UChar* simpleQuotes[] = {U("\""), U("\""), U("'"), U("'")}; - -static const UChar* englishQuotes[] = {U("\x201C"), U("\x201D"), U("\x2018"), U("\x2019")}; -static const UChar* norwegianQuotes[] = { U("\x00AB"), U("\x00BB"), U("\x2039"), U("\x203A") }; -static const UChar* romanianQuotes[] = { U("\x201E"), U("\x201D")}; -static const UChar* russianQuotes[] = { U("\x00AB"), U("\x00BB"), U("\x201E"), U("\x201C") }; -#undef U - -struct LanguageData { - const char *name; - const UChar* const* const array; - const int arraySize; - bool operator<(const LanguageData& compareTo) const - { - return strcmp(name, compareTo.name); - } -}; - -// Data mast be alphabetically sorted and in all lower case for fast comparison -LanguageData languageData[] = { - LANGUAGE_DATA("en", englishQuotes), - LANGUAGE_DATA("no", norwegianQuotes), - LANGUAGE_DATA("ro", romanianQuotes), - LANGUAGE_DATA("ru", russianQuotes) -}; -#undef LANGUAGE_DATA -const LanguageData* const languageDataEnd = languageData + ARRAY_SIZE(languageData); - -#define defaultLanguageQuotesSource simpleQuotes -#define defaultLanguageQuotesCount ARRAY_SIZE(defaultLanguageQuotesSource) - -static QuotesData* defaultLanguageQuotesValue = 0; -static const QuotesData* defaultLanguageQuotes() -{ - if (!defaultLanguageQuotesValue) { - defaultLanguageQuotesValue = QuotesData::create(defaultLanguageQuotesCount); - if (!defaultLanguageQuotesValue) - return 0; - String* data = defaultLanguageQuotesValue->data(); - for (size_t i = 0; i < defaultLanguageQuotesCount; ++i) - data[i] = defaultLanguageQuotesSource[i]; - } - return defaultLanguageQuotesValue; -} -#undef defaultLanguageQuotesSource -#undef defaultLanguageQuotesCount - -typedef HashMap<RefPtr<AtomicStringImpl>, QuotesData* > QuotesMap; +typedef HashMap<AtomicString, const QuotesData*, CaseFoldingHash> QuotesMap; -static QuotesMap& quotesMap() +static const QuotesMap& quotesDataLanguageMap() { DEFINE_STATIC_LOCAL(QuotesMap, staticQuotesMap, ()); + if (staticQuotesMap.size()) + return staticQuotesMap; + // FIXME: Expand this table to include all the languages in https://bug-3234-attachments.webkit.org/attachment.cgi?id=2135 + staticQuotesMap.set("en", QuotesData::create(U("\x201C"), U("\x201D"), U("\x2018"), U("\x2019")).leakRef()); + staticQuotesMap.set("no", QuotesData::create(U("\x00AB"), U("\x00BB"), U("\x2039"), U("\x203A")).leakRef()); + staticQuotesMap.set("ro", QuotesData::create(U("\x201E"), U("\x201D")).leakRef()); + staticQuotesMap.set("ru", QuotesData::create(U("\x00AB"), U("\x00BB"), U("\x201E"), U("\x201C")).leakRef()); return staticQuotesMap; } -static const QuotesData* quotesForLanguage(AtomicStringImpl* language) +static const QuotesData* basicQuotesData() { - QuotesData* returnValue; - AtomicString lower(language->lower()); - returnValue = quotesMap().get(lower.impl()); - if (returnValue) - return returnValue; - CString s(static_cast<const String&>(lower).ascii()); - LanguageData request = { s.buffer()->data(), 0, 0 }; - const LanguageData* lowerBound = std::lower_bound<const LanguageData*, const LanguageData>(languageData, languageDataEnd, request); - if (lowerBound == languageDataEnd) - return defaultLanguageQuotes(); - if (strncmp(lowerBound->name, request.name, strlen(lowerBound->name))) - return defaultLanguageQuotes(); - returnValue = QuotesData::create(lowerBound->arraySize); - if (!returnValue) - return defaultLanguageQuotes(); - String* data = returnValue->data(); - for (int i = 0; i < lowerBound->arraySize; ++i) - data[i] = lowerBound->array[i]; - quotesMap().set(lower.impl(), returnValue); - return returnValue; -} -#undef ARRAY_SIZE - -static const QuotesData* defaultQuotes(const RenderObject* object) -{ - DEFINE_STATIC_LOCAL(String, langString, ("lang")); - Node* node = object->generatingNode(); - Element* element; - if (!node) { - element = object->document()->body(); - if (!element) - element = object->document()->documentElement(); - } else if (!node->isElementNode()) { - element = node->parentElement(); - if (!element) - return defaultLanguageQuotes(); - } else - element = toElement(node); - const AtomicString* language; - while ((language = &element->getAttribute(langString)) && language->isNull()) { - element = element->parentElement(); - if (!element) - return defaultLanguageQuotes(); - } - return quotesForLanguage(language->impl()); + static const QuotesData* staticBasicQuotes = QuotesData::create(U("\""), U("\""), U("'"), U("'")).leakRef(); + return staticBasicQuotes; } PassRefPtr<StringImpl> RenderQuote::originalText() const { - if (!parent()) - return 0; - ASSERT(m_depth != UNKNOWN_DEPTH); - const QuotesData* quotes = style()->quotes(); - if (!quotes) - quotes = defaultQuotes(this); - if (!quotes->length) - return emptyAtom.impl(); - int index = m_depth * 2; switch (m_type) { case NO_OPEN_QUOTE: case NO_CLOSE_QUOTE: - return emptyString().impl(); + return StringImpl::empty(); case CLOSE_QUOTE: - if (index) - --index; - else - ++index; - break; + // FIXME: When m_depth is 0 we should return empty string. + return quotesData()->getCloseQuote(std::max(m_depth - 1, 0)).impl(); case OPEN_QUOTE: - break; - default: - ASSERT_NOT_REACHED(); - return emptyAtom.impl(); + return quotesData()->getOpenQuote(m_depth).impl(); } - if (index >= quotes->length) - index = (quotes->length-2) | (index & 1); - if (index < 0) - return emptyAtom.impl(); - return quotes->data()[index].impl(); + ASSERT_NOT_REACHED(); + return StringImpl::empty(); } void RenderQuote::computePreferredLogicalWidths(float lead) { + if (!m_attached) + attachQuote(); setTextInternal(originalText()); RenderText::computePreferredLogicalWidths(lead); } -void RenderQuote::rendererSubtreeAttached(RenderObject* renderer) +const QuotesData* RenderQuote::quotesData() const +{ + if (QuotesData* customQuotes = style()->quotes()) + return customQuotes; + + AtomicString language = style()->locale(); + if (language.isNull()) + return basicQuotesData(); + const QuotesData* quotes = quotesDataLanguageMap().get(language); + if (!quotes) + return basicQuotesData(); + return quotes; +} + +void RenderQuote::attachQuote() { - ASSERT(renderer->view()); - if (!renderer->view()->hasRenderQuotes()) + ASSERT(view()); + ASSERT(!m_attached); + ASSERT(!m_next && !m_previous); + + // FIXME: Don't set pref widths dirty during layout. See updateDepth() for + // more detail. + if (!isRooted()) { + setNeedsLayoutAndPrefWidthsRecalc(); return; - for (RenderObject* descendant = renderer; descendant; descendant = descendant->nextInPreOrder(renderer)) - if (descendant->isQuote()) { - toRenderQuote(descendant)->placeQuote(); - break; - } + } + + if (!view()->renderQuoteHead()) { + view()->setRenderQuoteHead(this); + m_attached = true; + return; + } + + for (RenderObject* predecessor = previousInPreOrder(); predecessor; predecessor = predecessor->previousInPreOrder()) { + // Skip unattached predecessors to avoid having stale m_previous pointers + // if the previous node is never attached and is then destroyed. + if (!predecessor->isQuote() || !toRenderQuote(predecessor)->isAttached()) + continue; + m_previous = toRenderQuote(predecessor); + m_next = m_previous->m_next; + m_previous->m_next = this; + if (m_next) + m_next->m_previous = this; + break; + } + + if (!m_previous) { + m_next = view()->renderQuoteHead(); + view()->setRenderQuoteHead(this); + if (m_next) + m_next->m_previous = this; + } + m_attached = true; + + for (RenderQuote* quote = this; quote; quote = quote->m_next) + quote->updateDepth(); + + ASSERT(!m_next || m_next->m_attached); + ASSERT(!m_next || m_next->m_previous == this); + ASSERT(!m_previous || m_previous->m_attached); + ASSERT(!m_previous || m_previous->m_next == this); } -void RenderQuote::rendererRemovedFromTree(RenderObject* renderer) +void RenderQuote::detachQuote() { - ASSERT(renderer->view()); - if (!renderer->view()->hasRenderQuotes()) + ASSERT(!m_next || m_next->m_attached); + ASSERT(!m_previous || m_previous->m_attached); + if (!m_attached) return; - for (RenderObject* descendant = renderer; descendant; descendant = descendant->nextInPreOrder(renderer)) - if (descendant->isQuote()) { - RenderQuote* removedQuote = toRenderQuote(descendant); - RenderQuote* lastQuoteBefore = removedQuote->m_previous; - removedQuote->m_previous = 0; - int depth = removedQuote->m_depth; - for (descendant = descendant->nextInPreOrder(renderer); descendant; descendant = descendant->nextInPreOrder(renderer)) - if (descendant->isQuote()) - removedQuote = toRenderQuote(descendant); - RenderQuote* quoteAfter = removedQuote->m_next; - removedQuote->m_next = 0; - if (lastQuoteBefore) - lastQuoteBefore->m_next = quoteAfter; - if (quoteAfter) { - quoteAfter->m_previous = lastQuoteBefore; - do { - if (depth == quoteAfter->m_depth) - break; - quoteAfter->m_depth = depth; - quoteAfter->setNeedsLayoutAndPrefWidthsRecalc(); - adjustDepth(depth, quoteAfter->m_type); - quoteAfter = quoteAfter->m_next; - } while (quoteAfter); - } - break; - } + if (m_previous) + m_previous->m_next = m_next; + else if (view()) + view()->setRenderQuoteHead(m_next); + if (m_next) + m_next->m_previous = m_previous; + if (!documentBeingDestroyed()) { + for (RenderQuote* quote = m_next; quote; quote = quote->m_next) + quote->updateDepth(); + } + m_attached = false; + m_next = 0; + m_previous = 0; + m_depth = 0; } -void RenderQuote::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle) +void RenderQuote::updateDepth() { - const QuotesData* newQuotes = style()->quotes(); - const QuotesData* oldQuotes = oldStyle ? oldStyle->quotes() : 0; - if (!QuotesData::equal(newQuotes, oldQuotes)) + ASSERT(m_attached); + int oldDepth = m_depth; + m_depth = 0; + if (m_previous) { + m_depth = m_previous->m_depth; + switch (m_previous->m_type) { + case OPEN_QUOTE: + case NO_OPEN_QUOTE: + m_depth++; + break; + case CLOSE_QUOTE: + case NO_CLOSE_QUOTE: + if (m_depth) + m_depth--; + break; + } + } + // FIXME: Don't call setNeedsLayout or dirty our preferred widths during layout. + // This is likely to fail anyway as one of our ancestor will call setNeedsLayout(false), + // preventing the future layout to occur on |this|. The solution is to move that to a + // pre-layout phase. + if (oldDepth != m_depth) setNeedsLayoutAndPrefWidthsRecalc(); - RenderText::styleDidChange(diff, oldStyle); } } // namespace WebCore diff --git a/Source/WebCore/rendering/RenderQuote.h b/Source/WebCore/rendering/RenderQuote.h index 10e22d1c7..cf7032ca7 100644 --- a/Source/WebCore/rendering/RenderQuote.h +++ b/Source/WebCore/rendering/RenderQuote.h @@ -21,6 +21,9 @@ #ifndef RenderQuote_h #define RenderQuote_h +#include "Document.h" +#include "QuotesData.h" +#include "RenderStyle.h" #include "RenderStyleConstants.h" #include "RenderText.h" @@ -30,22 +33,25 @@ class RenderQuote : public RenderText { public: RenderQuote(Document*, const QuoteType); virtual ~RenderQuote(); + void attachQuote(); + void detachQuote(); - static void rendererSubtreeAttached(RenderObject*); - static void rendererRemovedFromTree(RenderObject*); -protected: - virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); - virtual void willBeDestroyed(); private: - virtual const char* renderName() const; - virtual bool isQuote() const { return true; }; - virtual PassRefPtr<StringImpl> originalText() const; - virtual void computePreferredLogicalWidths(float leadWidth); + virtual void willBeDestroyed() OVERRIDE; + virtual const char* renderName() const OVERRIDE { return "RenderQuote"; }; + virtual bool isQuote() const OVERRIDE { return true; }; + virtual PassRefPtr<StringImpl> originalText() const OVERRIDE; + virtual void computePreferredLogicalWidths(float leadWidth) OVERRIDE; + + const QuotesData* quotesData() const; + void updateDepth(); + bool isAttached() { return m_attached; } + QuoteType m_type; int m_depth; RenderQuote* m_next; RenderQuote* m_previous; - void placeQuote(); + bool m_attached; }; inline RenderQuote* toRenderQuote(RenderObject* object) diff --git a/Source/WebCore/rendering/RenderRegion.cpp b/Source/WebCore/rendering/RenderRegion.cpp index 5362836a4..aa4e05077 100644 --- a/Source/WebCore/rendering/RenderRegion.cpp +++ b/Source/WebCore/rendering/RenderRegion.cpp @@ -49,7 +49,6 @@ RenderRegion::RenderRegion(Node* node, RenderFlowThread* flowThread) , m_isValid(false) , m_hasCustomRegionStyle(false) , m_regionState(RegionUndefined) - , m_dispatchRegionLayoutUpdateEvent(false) { } @@ -63,13 +62,14 @@ LayoutUnit RenderRegion::logicalHeightForFlowThreadContent() const return m_flowThread->isHorizontalWritingMode() ? contentHeight() : contentWidth(); } -LayoutRect RenderRegion::regionOverflowRect() const +LayoutRect RenderRegion::regionOversetRect() const { // FIXME: Would like to just use hasOverflowClip() but we aren't a block yet. When RenderRegion is eliminated and // folded into RenderBlock, switch to hasOverflowClip(). bool clipX = style()->overflowX() != OVISIBLE; bool clipY = style()->overflowY() != OVISIBLE; - if ((clipX && clipY) || !isValid() || !m_flowThread) + bool isLastRegionWithRegionOverflowBreak = (isLastRegion() && (style()->regionOverflow() == BreakRegionOverflow)); + if ((clipX && clipY) || !isValid() || !m_flowThread || isLastRegionWithRegionOverflowBreak) return regionRect(); LayoutRect flowThreadOverflow = m_flowThread->visualOverflowRect(); @@ -141,6 +141,18 @@ bool RenderRegion::nodeAtPoint(const HitTestRequest& request, HitTestResult& res return false; } +void RenderRegion::checkRegionStyle() +{ + ASSERT(m_flowThread); + bool customRegionStyle = false; + if (node()) { + Element* regionElement = static_cast<Element*>(node()); + customRegionStyle = view()->document()->styleResolver()->checkRegionStyle(regionElement); + } + setHasCustomRegionStyle(customRegionStyle); + m_flowThread->checkRegionsWithStyling(); +} + void RenderRegion::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle) { RenderReplaced::styleDidChange(diff, oldStyle); @@ -153,13 +165,7 @@ void RenderRegion::styleDidChange(StyleDifference diff, const RenderStyle* oldSt return; } - bool customRegionStyle = false; - if (node()) { - Element* regionElement = static_cast<Element*>(node()); - customRegionStyle = view()->document()->styleResolver()->checkRegionStyle(regionElement); - } - setHasCustomRegionStyle(customRegionStyle); - m_flowThread->checkRegionsWithStyling(); + checkRegionStyle(); } void RenderRegion::layout() @@ -187,9 +193,19 @@ void RenderRegion::layout() void RenderRegion::attachRegion() { - if (!m_flowThread) + if (documentBeingDestroyed()) return; + ASSERT(!m_flowThread); + // Initialize the flow thread reference and create the flow thread object if needed. + // The flow thread lifetime is influenced by the number of regions attached to it, + // and we are attaching the region to the flow thread. + m_flowThread = view()->flowThreadController()->ensureRenderFlowThreadWithName(style()->regionThread()); + + // A region is valid if it is not part of a circular reference, which is checked below + // and in RenderNamedFlowThread::addRegionToThread. + setIsValid(false); + // By now the flow thread should already be added to the rendering tree, // so we go up the rendering parents and check that this region is not part of the same // flow that it actually needs to display. It would create a circular reference. @@ -202,6 +218,8 @@ void RenderRegion::attachRegion() // cannot change, so it is not worth adding it to the list. if (m_flowThread == m_parentNamedFlowThread) { m_flowThread = 0; + // This region is not valid for this flow thread (as being part of a circular dependency). + setIsValid(false); return; } break; @@ -209,12 +227,17 @@ void RenderRegion::attachRegion() } m_flowThread->addRegionToThread(this); + + // The region just got attached to the flow thread, lets check whether + // it has region styling rules associated. + checkRegionStyle(); } void RenderRegion::detachRegion() { if (m_flowThread) m_flowThread->removeRegionFromThread(this); + m_flowThread = 0; } RenderBoxRegionInfo* RenderRegion::renderBoxRegionInfo(const RenderBox* box) const diff --git a/Source/WebCore/rendering/RenderRegion.h b/Source/WebCore/rendering/RenderRegion.h index 826e98072..6093a9c03 100644 --- a/Source/WebCore/rendering/RenderRegion.h +++ b/Source/WebCore/rendering/RenderRegion.h @@ -52,7 +52,7 @@ public: void setRegionRect(const LayoutRect& rect) { m_regionRect = rect; } LayoutRect regionRect() const { return m_regionRect; } - LayoutRect regionOverflowRect() const; + LayoutRect regionOversetRect() const; void attachRegion(); void detachRegion(); @@ -88,13 +88,11 @@ public: RegionUndefined, RegionEmpty, RegionFit, - RegionOverflow + RegionOverset }; RegionState regionState() const { return isValid() ? m_regionState : RegionUndefined; } void setRegionState(RegionState regionState) { m_regionState = regionState; } - void setDispatchRegionLayoutUpdateEvent(bool value) { m_dispatchRegionLayoutUpdateEvent = value; } - bool shouldDispatchRegionLayoutUpdateEvent() { return m_dispatchRegionLayoutUpdateEvent; } virtual LayoutUnit logicalWidthForFlowThreadContent() const; virtual LayoutUnit logicalHeightForFlowThreadContent() const; @@ -108,6 +106,9 @@ private: void restoreRegionObjectsOriginalStyle(); void setObjectStyleInRegion(RenderObject*, PassRefPtr<RenderStyle>, bool objectRegionStyleCached); void printRegionObjectsStyles(); + + void checkRegionStyle(); + RenderFlowThread* m_flowThread; // If this RenderRegion is displayed as part of another named flow, @@ -139,7 +140,6 @@ private: bool m_isValid; bool m_hasCustomRegionStyle; RegionState m_regionState; - bool m_dispatchRegionLayoutUpdateEvent; }; inline RenderRegion* toRenderRegion(RenderObject* object) diff --git a/Source/WebCore/rendering/RenderReplaced.cpp b/Source/WebCore/rendering/RenderReplaced.cpp index 35716be52..bcd967e6a 100644 --- a/Source/WebCore/rendering/RenderReplaced.cpp +++ b/Source/WebCore/rendering/RenderReplaced.cpp @@ -297,8 +297,11 @@ void RenderReplaced::computeAspectRatioInformationForRenderBox(RenderBox* conten } } else { computeIntrinsicRatioInformation(intrinsicSize, intrinsicRatio, isPercentageIntrinsicSize); - if (intrinsicRatio) + if (intrinsicRatio) { ASSERT(!isPercentageIntrinsicSize); + if (!intrinsicSize.isEmpty()) + m_intrinsicSize = isHorizontalWritingMode() ? flooredIntSize(intrinsicSize) : flooredIntSize(intrinsicSize).transposedSize(); // FIXME: This introduces precision errors. We should convert m_intrinsicSize to be a float. + } } // Now constrain the intrinsic size along each axis according to minimum and maximum width/heights along the diff --git a/Source/WebCore/rendering/RenderSlider.cpp b/Source/WebCore/rendering/RenderSlider.cpp index f78ba5c75..1abca2fdb 100644 --- a/Source/WebCore/rendering/RenderSlider.cpp +++ b/Source/WebCore/rendering/RenderSlider.cpp @@ -59,6 +59,11 @@ RenderSlider::~RenderSlider() { } +bool RenderSlider::canBeReplacedWithInlineRunIn() const +{ + return false; +} + LayoutUnit RenderSlider::baselinePosition(FontBaseline, bool /*firstLine*/, LineDirectionMode, LinePositionMode) const { // FIXME: Patch this function for writing-mode. diff --git a/Source/WebCore/rendering/RenderSlider.h b/Source/WebCore/rendering/RenderSlider.h index 5709e2d13..ebd0bd856 100644 --- a/Source/WebCore/rendering/RenderSlider.h +++ b/Source/WebCore/rendering/RenderSlider.h @@ -39,6 +39,7 @@ namespace WebCore { private: virtual const char* renderName() const { return "RenderSlider"; } virtual bool isSlider() const { return true; } + virtual bool canBeReplacedWithInlineRunIn() const OVERRIDE; virtual LayoutUnit baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const; virtual void computePreferredLogicalWidths(); diff --git a/Source/WebCore/rendering/RenderTable.cpp b/Source/WebCore/rendering/RenderTable.cpp index e939004db..2cda8dcc7 100644 --- a/Source/WebCore/rendering/RenderTable.cpp +++ b/Source/WebCore/rendering/RenderTable.cpp @@ -1206,16 +1206,33 @@ void RenderTable::updateFirstLetter() { } -enum LineBox { FirstLineBox, LastLineBox }; +LayoutUnit RenderTable::baselinePosition(FontBaseline baselineType, bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) const +{ + LayoutUnit baseline = firstLineBoxBaseline(); + if (baseline != -1) + return baseline; + + return RenderBox::baselinePosition(baselineType, firstLine, direction, linePositionMode); +} + +LayoutUnit RenderTable::lastLineBoxBaseline() const +{ + // Tables don't contribute their baseline towards the computation of an inline-block's baseline. + return -1; +} -static LayoutUnit getLineBoxBaseline(const RenderTable* table, LineBox lineBox) +LayoutUnit RenderTable::firstLineBoxBaseline() const { - if (table->isWritingModeRoot()) + // The baseline of a 'table' is the same as the 'inline-table' baseline per CSS 3 Flexbox (CSS 2.1 + // doesn't define the baseline of a 'table' only an 'inline-table'). + // This is also needed to properly determine the baseline of a cell if it has a table child. + + if (isWritingModeRoot()) return -1; - table->recalcSectionsIfNeeded(); + recalcSectionsIfNeeded(); - const RenderTableSection* topNonEmptySection = table->topNonEmptySection(); + const RenderTableSection* topNonEmptySection = this->topNonEmptySection(); if (!topNonEmptySection) return -1; @@ -1223,26 +1240,10 @@ static LayoutUnit getLineBoxBaseline(const RenderTable* table, LineBox lineBox) if (baseline > 0) return topNonEmptySection->logicalTop() + baseline; - // The 'first' linebox baseline in a table in the absence of any text in the first section - // is the top of the table. - if (lineBox == FirstLineBox) - return topNonEmptySection->logicalTop(); - - // The 'last' linebox baseline in a table is the baseline of text in the first - // cell in the first row/section, so if there is no text do not return a baseline. + // FIXME: A table row always has a baseline per CSS 2.1. Will this return the right value? return -1; } -LayoutUnit RenderTable::lastLineBoxBaseline() const -{ - return getLineBoxBaseline(this, LastLineBox); -} - -LayoutUnit RenderTable::firstLineBoxBaseline() const -{ - return getLineBoxBaseline(this, FirstLineBox); -} - LayoutRect RenderTable::overflowClipRect(const LayoutPoint& location, RenderRegion* region, OverlayScrollbarSizeRelevancy relevancy) { LayoutRect rect = RenderBlock::overflowClipRect(location, region, relevancy); diff --git a/Source/WebCore/rendering/RenderTable.h b/Source/WebCore/rendering/RenderTable.h index 87418f068..e4c70f47f 100644 --- a/Source/WebCore/rendering/RenderTable.h +++ b/Source/WebCore/rendering/RenderTable.h @@ -251,6 +251,7 @@ private: virtual void computePreferredLogicalWidths(); virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE; + virtual LayoutUnit baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const OVERRIDE; virtual LayoutUnit firstLineBoxBaseline() const OVERRIDE; virtual LayoutUnit lastLineBoxBaseline() const OVERRIDE; diff --git a/Source/WebCore/rendering/RenderTableSection.cpp b/Source/WebCore/rendering/RenderTableSection.cpp index 1f1379e48..80e6465ec 100644 --- a/Source/WebCore/rendering/RenderTableSection.cpp +++ b/Source/WebCore/rendering/RenderTableSection.cpp @@ -587,9 +587,9 @@ void RenderTableSection::layoutRows() } } - if (HashSet<RenderBox*>* percentHeightDescendants = cell->percentHeightDescendants()) { - HashSet<RenderBox*>::iterator end = percentHeightDescendants->end(); - for (HashSet<RenderBox*>::iterator it = percentHeightDescendants->begin(); it != end; ++it) { + if (ListHashSet<RenderBox*>* percentHeightDescendants = cell->percentHeightDescendants()) { + ListHashSet<RenderBox*>::iterator end = percentHeightDescendants->end(); + for (ListHashSet<RenderBox*>::iterator it = percentHeightDescendants->begin(); it != end; ++it) { RenderBox* box = *it; if (!box->isReplaced() && !box->scrollsOverflow() && !flexAllChildren) continue; diff --git a/Source/WebCore/rendering/RenderText.cpp b/Source/WebCore/rendering/RenderText.cpp index f93704dc2..73e57754a 100644 --- a/Source/WebCore/rendering/RenderText.cpp +++ b/Source/WebCore/rendering/RenderText.cpp @@ -678,15 +678,11 @@ LayoutRect RenderText::localCaretRect(InlineBox* inlineBox, int caretOffset, Lay RenderBlock* cb = containingBlock(); RenderStyle* cbStyle = cb->style(); + float leftEdge; float rightEdge; - if (style()->autoWrap()) { - leftEdge = 0; - rightEdge = cb->logicalWidth(); - } else { - leftEdge = min(static_cast<float>(0), rootLeft); - rightEdge = max(static_cast<float>(cb->logicalWidth()), rootRight); - } + leftEdge = min<float>(0, rootLeft); + rightEdge = max<float>(cb->logicalWidth(), rootRight); bool rightAligned = false; switch (cbStyle->textAlign()) { diff --git a/Source/WebCore/rendering/RenderTextControl.cpp b/Source/WebCore/rendering/RenderTextControl.cpp index 8b138352e..10a420aa8 100644 --- a/Source/WebCore/rendering/RenderTextControl.cpp +++ b/Source/WebCore/rendering/RenderTextControl.cpp @@ -81,7 +81,7 @@ static inline bool updateUserModifyProperty(Node* node, RenderStyle* style) if (node->isElementNode()) { Element* element = static_cast<Element*>(node); isEnabled = element->isEnabledFormControl(); - isReadOnlyControl = element->isReadOnlyFormControl(); + isReadOnlyControl = element->isTextFormControl() && static_cast<HTMLTextFormControlElement*>(element)->readOnly(); } style->setUserModify((isReadOnlyControl || !isEnabled) ? READ_ONLY : READ_WRITE_PLAINTEXT_ONLY); @@ -299,4 +299,9 @@ RenderObject* RenderTextControl::layoutSpecialExcludedChild(bool relayoutChildre return placeholderRenderer; } +bool RenderTextControl::canBeReplacedWithInlineRunIn() const +{ + return false; +} + } // namespace WebCore diff --git a/Source/WebCore/rendering/RenderTextControl.h b/Source/WebCore/rendering/RenderTextControl.h index 1a48f5dbe..b8f1f3025 100644 --- a/Source/WebCore/rendering/RenderTextControl.h +++ b/Source/WebCore/rendering/RenderTextControl.h @@ -72,6 +72,7 @@ private: virtual void removeLeftoverAnonymousBlock(RenderBlock*) { } virtual bool avoidsFloats() const { return true; } virtual bool canHaveGeneratedChildren() const OVERRIDE { return false; } + virtual bool canBeReplacedWithInlineRunIn() const OVERRIDE; virtual void addFocusRingRects(Vector<IntRect>&, const LayoutPoint&); diff --git a/Source/WebCore/rendering/RenderTheme.cpp b/Source/WebCore/rendering/RenderTheme.cpp index f1661722e..3382d3fbd 100644 --- a/Source/WebCore/rendering/RenderTheme.cpp +++ b/Source/WebCore/rendering/RenderTheme.cpp @@ -828,7 +828,7 @@ bool RenderTheme::isReadOnlyControl(const RenderObject* o) const Node* node = o->node(); if (!node || !node->isElementNode()) return false; - return static_cast<Element*>(node)->isReadOnlyFormControl(); + return static_cast<Element*>(node)->shouldMatchReadOnlySelector(); } bool RenderTheme::isHovered(const RenderObject* o) const @@ -963,6 +963,11 @@ bool RenderTheme::paintMeter(RenderObject*, const PaintInfo&, const IntRect&) #endif #if ENABLE(DATALIST_ELEMENT) +LayoutUnit RenderTheme::sliderTickSnappingThreshold() const +{ + return 0; +} + void RenderTheme::paintSliderTicks(RenderObject* o, const PaintInfo& paintInfo, const IntRect& rect) { Node* node = o->node(); @@ -1024,13 +1029,13 @@ void RenderTheme::paintSliderTicks(RenderObject* o, const PaintInfo& paintInfo, if (!input->isValidValue(value)) continue; double parsedValue = parseToDoubleForNumberType(input->sanitizeValue(value)); - double tickPosition = (parsedValue - min) / (max - min); - if (!o->style()->isLeftToRightDirection()) - tickPosition = 1.0 - tickPosition; + double tickFraction = (parsedValue - min) / (max - min); + double tickRatio = isHorizontal && o->style()->isLeftToRightDirection() ? tickFraction : 1.0 - tickFraction; + double tickPosition = round(tickRegionSideMargin + tickRegionWidth * tickRatio); if (isHorizontal) - tickRect.setX(floor(tickRegionSideMargin + tickRegionWidth * tickPosition)); + tickRect.setX(tickPosition); else - tickRect.setY(floor(tickRegionSideMargin + tickRegionWidth * tickPosition)); + tickRect.setY(tickPosition); paintInfo.context->fillRect(tickRect); } } diff --git a/Source/WebCore/rendering/RenderTheme.h b/Source/WebCore/rendering/RenderTheme.h index 3d3976266..6facf5280 100644 --- a/Source/WebCore/rendering/RenderTheme.h +++ b/Source/WebCore/rendering/RenderTheme.h @@ -215,6 +215,8 @@ public: #endif #if ENABLE(DATALIST_ELEMENT) + // Returns the threshold distance for snapping to a slider tick mark. + virtual LayoutUnit sliderTickSnappingThreshold() const; // Returns size of one slider tick mark for a horizontal track. // For vertical tracks we rotate it and use it. i.e. Width is always length along the track. virtual IntSize sliderTickSize() const = 0; diff --git a/Source/WebCore/rendering/RenderThemeChromiumCommon.cpp b/Source/WebCore/rendering/RenderThemeChromiumCommon.cpp index 368c2b566..68de37b12 100644 --- a/Source/WebCore/rendering/RenderThemeChromiumCommon.cpp +++ b/Source/WebCore/rendering/RenderThemeChromiumCommon.cpp @@ -32,10 +32,18 @@ namespace WebCore { bool RenderThemeChromiumCommon::supportsDataListUI(const AtomicString& type) { - // FIXME: We still need to support datetime, date, month, week, time, datetime-local, color. + // FIXME: We still need to support datetime, date, month, week, time, datetime-local. return type == InputTypeNames::text() || type == InputTypeNames::search() || type == InputTypeNames::url() || type == InputTypeNames::telephone() || type == InputTypeNames::email() || type == InputTypeNames::number() +#if ENABLE(INPUT_TYPE_COLOR) + || type == InputTypeNames::color() +#endif || type == InputTypeNames::range(); } +LayoutUnit RenderThemeChromiumCommon::sliderTickSnappingThreshold() +{ + return 5; +} + } diff --git a/Source/WebCore/rendering/RenderThemeChromiumCommon.h b/Source/WebCore/rendering/RenderThemeChromiumCommon.h index be099a8e2..80aeca952 100644 --- a/Source/WebCore/rendering/RenderThemeChromiumCommon.h +++ b/Source/WebCore/rendering/RenderThemeChromiumCommon.h @@ -27,6 +27,7 @@ #ifndef RenderThemeChromiumCommon_h #define RenderThemeChromiumCommon_h +#include "LayoutTypes.h" #include <wtf/text/AtomicString.h> namespace WebCore { @@ -34,6 +35,7 @@ namespace WebCore { class RenderThemeChromiumCommon { public: static bool supportsDataListUI(const AtomicString& type); + static LayoutUnit sliderTickSnappingThreshold(); }; } diff --git a/Source/WebCore/rendering/RenderThemeChromiumMac.h b/Source/WebCore/rendering/RenderThemeChromiumMac.h index 973299a31..e19ffa303 100644 --- a/Source/WebCore/rendering/RenderThemeChromiumMac.h +++ b/Source/WebCore/rendering/RenderThemeChromiumMac.h @@ -71,6 +71,9 @@ private: virtual Color disabledTextColor(const Color& textColor, const Color&) const OVERRIDE { return textColor; } virtual void updateActiveState(NSCell*, const RenderObject*); virtual String extraDefaultStyleSheet(); +#if ENABLE(DATALIST_ELEMENT) + virtual LayoutUnit sliderTickSnappingThreshold() const OVERRIDE; +#endif #if ENABLE(CALENDAR_PICKER) virtual CString extraCalendarPickerStyleSheet() OVERRIDE; #endif diff --git a/Source/WebCore/rendering/RenderThemeChromiumMac.mm b/Source/WebCore/rendering/RenderThemeChromiumMac.mm index 05a9589db..fc01e6fa9 100644 --- a/Source/WebCore/rendering/RenderThemeChromiumMac.mm +++ b/Source/WebCore/rendering/RenderThemeChromiumMac.mm @@ -192,6 +192,13 @@ String RenderThemeChromiumMac::extraDefaultStyleSheet() String(themeChromiumUserAgentStyleSheet, sizeof(themeChromiumUserAgentStyleSheet)); } +#if ENABLE(DATALIST_ELEMENT) +LayoutUnit RenderThemeChromiumMac::sliderTickSnappingThreshold() const +{ + return RenderThemeChromiumCommon::sliderTickSnappingThreshold(); +} +#endif + #if ENABLE(CALENDAR_PICKER) CString RenderThemeChromiumMac::extraCalendarPickerStyleSheet() { diff --git a/Source/WebCore/rendering/RenderThemeChromiumSkia.cpp b/Source/WebCore/rendering/RenderThemeChromiumSkia.cpp index 7ce2a0cd5..3eaae4111 100644 --- a/Source/WebCore/rendering/RenderThemeChromiumSkia.cpp +++ b/Source/WebCore/rendering/RenderThemeChromiumSkia.cpp @@ -591,6 +591,13 @@ bool RenderThemeChromiumSkia::shouldShowPlaceholderWhenFocused() const return true; } +#if ENABLE(DATALIST_ELEMENT) +LayoutUnit RenderThemeChromiumSkia::sliderTickSnappingThreshold() const +{ + return RenderThemeChromiumCommon::sliderTickSnappingThreshold(); +} +#endif + #if ENABLE(PROGRESS_ELEMENT) // diff --git a/Source/WebCore/rendering/RenderThemeChromiumSkia.h b/Source/WebCore/rendering/RenderThemeChromiumSkia.h index 489738c85..ee9b11c37 100644 --- a/Source/WebCore/rendering/RenderThemeChromiumSkia.h +++ b/Source/WebCore/rendering/RenderThemeChromiumSkia.h @@ -174,6 +174,10 @@ private: virtual Color disabledTextColor(const Color& textColor, const Color&) const OVERRIDE { return textColor; } virtual bool shouldShowPlaceholderWhenFocused() const OVERRIDE; +#if ENABLE(DATALIST_ELEMENT) + virtual LayoutUnit sliderTickSnappingThreshold() const OVERRIDE; +#endif + int menuListInternalPadding(RenderStyle*, int paddingType) const; bool paintMediaButtonInternal(GraphicsContext*, const IntRect&, Image*); IntRect convertToPaintingRect(RenderObject* inputRenderer, const RenderObject* partRenderer, LayoutRect partRect, const IntRect& localOffset) const; diff --git a/Source/WebCore/rendering/RenderThemeMac.mm b/Source/WebCore/rendering/RenderThemeMac.mm index 1b92006f1..25b03b737 100644 --- a/Source/WebCore/rendering/RenderThemeMac.mm +++ b/Source/WebCore/rendering/RenderThemeMac.mm @@ -1571,7 +1571,7 @@ bool RenderThemeMac::paintSearchFieldCancelButton(RenderObject* o, const PaintIn NSSearchFieldCell* search = this->search(); - if (input->isEnabledFormControl() && !input->isReadOnlyFormControl()) { + if (input->isEnabledFormControl() && (input->isTextFormControl() && !static_cast<HTMLTextFormControlElement*>(input)->readOnly())) { updateActiveState([search cancelButtonCell], o); updatePressedState([search cancelButtonCell], o); } diff --git a/Source/WebCore/rendering/RenderView.cpp b/Source/WebCore/rendering/RenderView.cpp index 8bd49ccfa..048f6e1ce 100644 --- a/Source/WebCore/rendering/RenderView.cpp +++ b/Source/WebCore/rendering/RenderView.cpp @@ -62,7 +62,7 @@ RenderView::RenderView(Node* node, FrameView* view) , m_pageLogicalHeightChanged(false) , m_layoutState(0) , m_layoutStateDisableCount(0) - , m_renderQuoteCount(0) + , m_renderQuoteHead(0) , m_renderCounterCount(0) { // Clear our anonymous bit, set because RenderObject assumes @@ -165,20 +165,20 @@ void RenderView::layout() setNeedsLayout(false); } -void RenderView::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed, bool useTransforms, TransformState& transformState, ApplyContainerFlipOrNot, bool* wasFixed) const +void RenderView::mapLocalToContainer(RenderBoxModelObject* repaintContainer, TransformState& transformState, MapLocalToContainerFlags mode, bool* wasFixed) const { // If a container was specified, and was not 0 or the RenderView, // then we should have found it by now. ASSERT_ARG(repaintContainer, !repaintContainer || repaintContainer == this); - ASSERT_UNUSED(wasFixed, !wasFixed || *wasFixed == fixed); + ASSERT_UNUSED(wasFixed, !wasFixed || *wasFixed == (mode & IsFixed)); - if (!repaintContainer && useTransforms && shouldUseTransformFromContainer(0)) { + if (!repaintContainer && mode & UseTransforms && shouldUseTransformFromContainer(0)) { TransformationMatrix t; getTransformFromContainer(0, LayoutSize(), t); transformState.applyTransform(t); } - if (fixed && m_frameView) + if (mode & IsFixed && m_frameView) transformState.move(m_frameView->scrollOffsetForFixedPosition()); } @@ -961,12 +961,12 @@ void RenderView::setFixedPositionedObjectsNeedLayout() { ASSERT(m_frameView); - PositionedObjectsListHashSet* positionedObjects = this->positionedObjects(); + ListHashSet<RenderBox*>* positionedObjects = this->positionedObjects(); if (!positionedObjects) return; - PositionedObjectsListHashSet::const_iterator end = positionedObjects->end(); - for (PositionedObjectsListHashSet::const_iterator it = positionedObjects->begin(); it != end; ++it) { + ListHashSet<RenderBox*>::const_iterator end = positionedObjects->end(); + for (ListHashSet<RenderBox*>::const_iterator it = positionedObjects->begin(); it != end; ++it) { RenderBox* currBox = *it; currBox->setNeedsLayout(true); } diff --git a/Source/WebCore/rendering/RenderView.h b/Source/WebCore/rendering/RenderView.h index 04a806e9b..e8e422765 100644 --- a/Source/WebCore/rendering/RenderView.h +++ b/Source/WebCore/rendering/RenderView.h @@ -32,6 +32,7 @@ namespace WebCore { class FlowThreadController; class RenderWidget; +class RenderQuote; #if USE(ACCELERATED_COMPOSITING) class RenderLayerCompositor; @@ -194,19 +195,19 @@ public: void setFixedPositionedObjectsNeedLayout(); - // FIXME: This is a work around because the current implementation of counters and quotes + void setRenderQuoteHead(RenderQuote* head) { m_renderQuoteHead = head; } + RenderQuote* renderQuoteHead() const { return m_renderQuoteHead; } + + // FIXME: This is a work around because the current implementation of counters // requires walking the entire tree repeatedly and most pages don't actually use either // feature so we shouldn't take the performance hit when not needed. Long term we should // rewrite the counter and quotes code. - void addRenderQuote() { m_renderQuoteCount++; } - void removeRenderQuote() { ASSERT(m_renderQuoteCount > 0); m_renderQuoteCount--; } - bool hasRenderQuotes() { return m_renderQuoteCount; } void addRenderCounter() { m_renderCounterCount++; } void removeRenderCounter() { ASSERT(m_renderCounterCount > 0); m_renderCounterCount--; } bool hasRenderCounters() { return m_renderCounterCount; } protected: - virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool useTransforms, bool fixed, TransformState&, ApplyContainerFlipOrNot = ApplyContainerFlip, bool* wasFixed = 0) const; + virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, TransformState&, MapLocalToContainerFlags mode = ApplyContainerFlip, bool* wasFixed = 0) const OVERRIDE; virtual const RenderObject* pushMappingToContainer(const RenderBoxModelObject* ancestorToStopAt, RenderGeometryMap&) const; virtual void mapAbsoluteToLocalPoint(bool fixed, bool useTransforms, TransformState&) const; virtual bool requiresColumns(int desiredColumnCount) const OVERRIDE; @@ -301,7 +302,7 @@ private: OwnPtr<FlowThreadController> m_flowThreadController; RefPtr<IntervalArena> m_intervalArena; - unsigned m_renderQuoteCount; + RenderQuote* m_renderQuoteHead; unsigned m_renderCounterCount; }; diff --git a/Source/WebCore/rendering/TextAutosizer.cpp b/Source/WebCore/rendering/TextAutosizer.cpp index 0824aa336..82399c739 100644 --- a/Source/WebCore/rendering/TextAutosizer.cpp +++ b/Source/WebCore/rendering/TextAutosizer.cpp @@ -68,6 +68,8 @@ void TextAutosizer::processBlock(RenderBlock* block, const IntSize& windowSize) { int windowLogicalWidth = block->isHorizontalWritingMode() ? windowSize.width() : windowSize.height(); float multiplier = static_cast<float>(block->logicalWidth()) / windowLogicalWidth; // FIXME: This is overly simplistic. + multiplier *= m_document->settings()->textAutosizingFontScaleFactor(); + if (multiplier < 1) return; for (RenderObject* descendant = traverseNext(block, block, treatAsInline); descendant; descendant = traverseNext(descendant, block, treatAsInline)) { diff --git a/Source/WebCore/rendering/mathml/RenderMathMLBlock.cpp b/Source/WebCore/rendering/mathml/RenderMathMLBlock.cpp index a4f927407..08885e001 100644 --- a/Source/WebCore/rendering/mathml/RenderMathMLBlock.cpp +++ b/Source/WebCore/rendering/mathml/RenderMathMLBlock.cpp @@ -194,9 +194,19 @@ LayoutUnit RenderMathMLBlock::preferredLogicalHeightAfterSizing(RenderObject* ch ASSERT(!child->needsLayout()); return toRenderBox(child)->logicalHeight(); } + // This currently ignores -webkit-line-box-contain: return child->style()->fontSize(); } +LayoutUnit RenderMathMLBlock::baselinePosition(FontBaseline baselineType, bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) const +{ + // mathml.css sets math { -webkit-line-box-contain: glyphs replaced; line-height: 0; }, so when linePositionMode == PositionOfInteriorLineBoxes we want to + // return 0 here to match our line-height. This matters when RootInlineBox::ascentAndDescentForBox is called on a RootInlineBox for an inline-block. + if (linePositionMode == PositionOfInteriorLineBoxes) + return 0; + return RenderBlock::baselinePosition(baselineType, firstLine, direction, linePositionMode); +} + const char* RenderMathMLBlock::renderName() const { EDisplay display = style()->display(); diff --git a/Source/WebCore/rendering/mathml/RenderMathMLBlock.h b/Source/WebCore/rendering/mathml/RenderMathMLBlock.h index 45f729643..25ec75039 100644 --- a/Source/WebCore/rendering/mathml/RenderMathMLBlock.h +++ b/Source/WebCore/rendering/mathml/RenderMathMLBlock.h @@ -76,6 +76,8 @@ public: // computePreferredLogicalWidths() in derived classes must ensure m_preferredLogicalHeight is set to < 0 or its correct value. virtual void computePreferredLogicalWidths() OVERRIDE; + virtual LayoutUnit baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const OVERRIDE; + #if ENABLE(DEBUG_MATH_LAYOUT) virtual void paint(PaintInfo&, const LayoutPoint&); #endif @@ -83,26 +85,6 @@ public: // Create a new RenderMathMLBlock, with a new style inheriting from this->style(). RenderMathMLBlock* createAnonymousMathMLBlock(EDisplay = BLOCK); -protected: - static LayoutUnit getBoxModelObjectHeight(const RenderObject* object) - { - if (object && object->isBoxModelObject()) { - const RenderBoxModelObject* box = toRenderBoxModelObject(object); - return box->offsetHeight(); - } - - return 0; - } - static LayoutUnit getBoxModelObjectWidth(const RenderObject* object) - { - if (object && object->isBoxModelObject()) { - const RenderBoxModelObject* box = toRenderBoxModelObject(object); - return box->offsetWidth(); - } - - return 0; - } - private: virtual const char* renderName() const OVERRIDE; diff --git a/Source/WebCore/rendering/mathml/RenderMathMLFraction.cpp b/Source/WebCore/rendering/mathml/RenderMathMLFraction.cpp index ffc4f1bc8..77bebd84f 100644 --- a/Source/WebCore/rendering/mathml/RenderMathMLFraction.cpp +++ b/Source/WebCore/rendering/mathml/RenderMathMLFraction.cpp @@ -197,7 +197,7 @@ LayoutUnit RenderMathMLFraction::baselinePosition(FontBaseline, bool firstLine, int shift = int(ceil((refStyle->fontMetrics().xHeight() + 1) / 2)); return numeratorWrapper->pixelSnappedOffsetHeight() + shift; } - return RenderBlock::baselinePosition(AlphabeticBaseline, firstLine, lineDirection, linePositionMode); + return RenderMathMLBlock::baselinePosition(AlphabeticBaseline, firstLine, lineDirection, linePositionMode); } } diff --git a/Source/WebCore/rendering/mathml/RenderMathMLOperator.cpp b/Source/WebCore/rendering/mathml/RenderMathMLOperator.cpp index 1160aa1cf..196783804 100644 --- a/Source/WebCore/rendering/mathml/RenderMathMLOperator.cpp +++ b/Source/WebCore/rendering/mathml/RenderMathMLOperator.cpp @@ -331,7 +331,7 @@ void RenderMathMLOperator::updateFromElement() setNeedsLayoutAndPrefWidthsRecalc(); } -PassRefPtr<RenderStyle> RenderMathMLOperator::createStackableStyle(int lineHeight, int maxHeightForRenderer, int topRelative) +PassRefPtr<RenderStyle> RenderMathMLOperator::createStackableStyle(int /* lineHeight */, int maxHeightForRenderer, int topRelative) { RefPtr<RenderStyle> newStyle = RenderStyle::create(); newStyle->inheritFrom(style()); @@ -343,8 +343,7 @@ PassRefPtr<RenderStyle> RenderMathMLOperator::createStackableStyle(int lineHeigh desc.setComputedSize(gGlyphFontSize); newStyle->setFontDescription(desc); newStyle->font().update(style()->font().fontSelector()); - newStyle->setLineHeight(Length(lineHeight, Fixed)); - newStyle->setVerticalAlign(TOP); + // FIXME: With -webkit-line-box-contain, this method's lineHeight argument is no longer used. It should be removed in a future patch. if (maxHeightForRenderer > 0) newStyle->setMaxHeight(Length(maxHeightForRenderer, Fixed)); @@ -387,7 +386,7 @@ LayoutUnit RenderMathMLOperator::baselinePosition(FontBaseline, bool firstLine, { if (m_isStacked) return m_stretchHeight * 2 / 3 - (m_stretchHeight - static_cast<int>(m_stretchHeight / gOperatorExpansion)) / 2; - return RenderBlock::baselinePosition(AlphabeticBaseline, firstLine, lineDirection, linePositionMode); + return RenderMathMLBlock::baselinePosition(AlphabeticBaseline, firstLine, lineDirection, linePositionMode); } } diff --git a/Source/WebCore/rendering/mathml/RenderMathMLRoot.cpp b/Source/WebCore/rendering/mathml/RenderMathMLRoot.cpp index efeed1a1f..b9346b935 100644 --- a/Source/WebCore/rendering/mathml/RenderMathMLRoot.cpp +++ b/Source/WebCore/rendering/mathml/RenderMathMLRoot.cpp @@ -32,6 +32,7 @@ #include "GraphicsContext.h" #include "PaintInfo.h" +#include "RenderMathMLRow.h" using namespace std; @@ -70,6 +71,20 @@ RenderMathMLRoot::RenderMathMLRoot(Element* element) { } +void RenderMathMLRoot::addChild(RenderObject* newChild, RenderObject* beforeChild) +{ + // Insert an implicit <mrow> for <mroot> as well as <msqrt>, to ensure firstChild() will have a box + // to measure and store a glyph-based height for preferredLogicalHeightAfterSizing. + if (!firstChild()) + RenderMathMLBlock::addChild(RenderMathMLRow::createAnonymousWithParentRenderer(this)); + + // An <mroot>'s index has { position: absolute }. + if (newChild->style()->position() == AbsolutePosition) + RenderMathMLBlock::addChild(newChild); + else + firstChild()->addChild(newChild, beforeChild && beforeChild->style()->position() != AbsolutePosition ? beforeChild : 0); +} + RenderBoxModelObject* RenderMathMLRoot::index() const { if (!firstChild()) @@ -86,7 +101,7 @@ void RenderMathMLRoot::computePreferredLogicalWidths() computeChildrenPreferredLogicalHeights(); - int baseHeight = firstChild() ? roundToInt(preferredLogicalHeightAfterSizing(firstChild())) : 0; + int baseHeight = firstChild() ? roundToInt(preferredLogicalHeightAfterSizing(firstChild())) : style()->fontSize(); int frontWidth = lroundf(gFrontWidthEms * style()->fontSize()); @@ -150,9 +165,9 @@ void RenderMathMLRoot::paint(PaintInfo& info, const LayoutPoint& paintOffset) int startX = adjustedPaintOffset.x(); int frontWidth = lroundf(gFrontWidthEms * style()->fontSize()); - int overbarWidth = roundToInt(getBoxModelObjectWidth(firstChild())) + m_overbarLeftPointShift; + int overbarWidth = roundToInt(contentLogicalWidth()) + m_overbarLeftPointShift; - int baseHeight = roundToInt(getBoxModelObjectHeight(firstChild())); + int baseHeight = roundToInt(contentLogicalHeight()); int rootPad = lroundf(gSpaceAboveEms * style()->fontSize()); adjustedPaintOffset.setY(adjustedPaintOffset.y() - rootPad); diff --git a/Source/WebCore/rendering/mathml/RenderMathMLRoot.h b/Source/WebCore/rendering/mathml/RenderMathMLRoot.h index cd5d6e6e2..2ae303aa8 100644 --- a/Source/WebCore/rendering/mathml/RenderMathMLRoot.h +++ b/Source/WebCore/rendering/mathml/RenderMathMLRoot.h @@ -37,6 +37,8 @@ class RenderMathMLRoot : public RenderMathMLBlock { public: RenderMathMLRoot(Element*); + virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0) OVERRIDE; + protected: virtual void layout() OVERRIDE; diff --git a/Source/WebCore/rendering/mathml/RenderMathMLSquareRoot.cpp b/Source/WebCore/rendering/mathml/RenderMathMLSquareRoot.cpp index b4b07a2cf..da7504520 100644 --- a/Source/WebCore/rendering/mathml/RenderMathMLSquareRoot.cpp +++ b/Source/WebCore/rendering/mathml/RenderMathMLSquareRoot.cpp @@ -30,8 +30,6 @@ #include "RenderMathMLSquareRoot.h" -#include "RenderMathMLRow.h" - namespace WebCore { RenderMathMLSquareRoot::RenderMathMLSquareRoot(Element* element) @@ -39,22 +37,6 @@ RenderMathMLSquareRoot::RenderMathMLSquareRoot(Element* element) { } -void RenderMathMLSquareRoot::addChild(RenderObject* newChild, RenderObject* beforeChild) -{ - if (!firstChild()) { - RenderMathMLRow* newMRow = RenderMathMLRow::createAnonymousWithParentRenderer(this); - - RenderMathMLRoot::addChild(newMRow); - - // newMRow->isAnonymousBlock() is false because newMRow's display is INLINE_BLOCK, - // so we don't need to worry about removeLeftoverAnonymousBlock(). - ASSERT(!newMRow->isAnonymousBlock()); - } - - ASSERT(firstChild() && firstChild()->isAnonymous() && firstChild()->isRenderMathMLBlock() && toRenderMathMLBlock(firstChild())->isRenderMathMLRow()); - firstChild()->addChild(newChild, beforeChild); -} - } #endif // ENABLE(MATHML) diff --git a/Source/WebCore/rendering/mathml/RenderMathMLSquareRoot.h b/Source/WebCore/rendering/mathml/RenderMathMLSquareRoot.h index cbb2c5706..90e186c6b 100644 --- a/Source/WebCore/rendering/mathml/RenderMathMLSquareRoot.h +++ b/Source/WebCore/rendering/mathml/RenderMathMLSquareRoot.h @@ -37,8 +37,6 @@ class RenderMathMLSquareRoot : public RenderMathMLRoot { public: RenderMathMLSquareRoot(Element*); - virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0) OVERRIDE; - private: virtual const char* renderName() const { return "RenderMathMLSquareRoot"; } }; diff --git a/Source/WebCore/rendering/mathml/RenderMathMLSubSup.cpp b/Source/WebCore/rendering/mathml/RenderMathMLSubSup.cpp index da406003a..d8dab715a 100644 --- a/Source/WebCore/rendering/mathml/RenderMathMLSubSup.cpp +++ b/Source/WebCore/rendering/mathml/RenderMathMLSubSup.cpp @@ -140,24 +140,18 @@ void RenderMathMLSubSup::layout() if (m_kind != SubSup || !m_scripts) return; - RenderBoxModelObject* base = this->base(); - RenderObject* superscriptWrapper = m_scripts->firstChild(); - RenderObject* subscriptWrapper = m_scripts->lastChild(); - if (!base || !superscriptWrapper || !subscriptWrapper || superscriptWrapper == subscriptWrapper) - return; - ASSERT(superscriptWrapper->isRenderMathMLBlock()); - ASSERT(subscriptWrapper->isRenderMathMLBlock()); - RenderObject* superscript = superscriptWrapper->firstChild(); - RenderObject* subscript = subscriptWrapper->firstChild(); - if (!superscript || !subscript) + RenderMathMLBlock* baseWrapper = toRenderMathMLBlock(firstChild()); + RenderMathMLBlock* superscriptWrapper = toRenderMathMLBlock(m_scripts->firstChild()); + RenderMathMLBlock* subscriptWrapper = toRenderMathMLBlock(m_scripts->lastChild()); + if (!baseWrapper || !superscriptWrapper || !subscriptWrapper || superscriptWrapper == subscriptWrapper) return; - LineDirectionMode lineDirection = style()->isHorizontalWritingMode() ? HorizontalLine : VerticalLine; - LayoutUnit baseBaseline = base->baselinePosition(AlphabeticBaseline, true, lineDirection); - LayoutUnit baseExtendUnderBaseline = getBoxModelObjectHeight(base) - baseBaseline; + LayoutUnit baseWrapperBaseline = toRenderBox(firstChild())->firstLineBoxBaseline(); + LayoutUnit baseBaseline = baseWrapperBaseline - baseWrapper->paddingBefore(); + LayoutUnit baseExtendUnderBaseline = baseWrapper->logicalHeight() - baseWrapperBaseline; LayoutUnit axis = style()->fontMetrics().xHeight() / 2; - LayoutUnit superscriptHeight = getBoxModelObjectHeight(superscript); - LayoutUnit subscriptHeight = getBoxModelObjectHeight(subscript); + LayoutUnit superscriptHeight = superscriptWrapper->logicalHeight() - superscriptWrapper->paddingAfter(); + LayoutUnit subscriptHeight = subscriptWrapper->logicalHeight(); // Our layout rules are: Don't let the superscript go below the "axis" (half x-height above the // baseline), or the subscript above the axis. Also, don't let the superscript's top edge be @@ -181,7 +175,6 @@ void RenderMathMLSubSup::layout() setChildNeedsLayout(true, MarkOnlyThis); - RenderObject* baseWrapper = firstChild(); baseWrapper->style()->setPaddingTop(Length(basePaddingTop, Fixed)); baseWrapper->setNeedsLayout(true, MarkOnlyThis); diff --git a/Source/WebCore/rendering/mathml/RenderMathMLUnderOver.cpp b/Source/WebCore/rendering/mathml/RenderMathMLUnderOver.cpp index 272032db6..e07d1cc5c 100644 --- a/Source/WebCore/rendering/mathml/RenderMathMLUnderOver.cpp +++ b/Source/WebCore/rendering/mathml/RenderMathMLUnderOver.cpp @@ -35,8 +35,6 @@ namespace WebCore { using namespace MathMLNames; -static const double gOverSpacingAdjustment = 0.5; - RenderMathMLUnderOver::RenderMathMLUnderOver(Element* element) : RenderMathMLBlock(element) { @@ -143,133 +141,24 @@ inline int getOffsetHeight(RenderObject* obj) return 0; } -void RenderMathMLUnderOver::layout() -{ - RenderBlock::layout(); - RenderObject* over = 0; - RenderObject* base = 0; - switch (m_kind) { - case Over: - // We need to calculate the baseline over the over versus the start of the base and - // adjust the placement of the base. - over = firstChild(); - if (over) { - // FIXME: descending glyphs intrude into base (e.g. lowercase y over base) - // FIXME: bases that ascend higher than the line box intrude into the over - if (!over->firstChild() || !over->firstChild()->isBoxModelObject()) - break; - - LayoutUnit overSpacing = static_cast<LayoutUnit>(gOverSpacingAdjustment * (getOffsetHeight(over) - toRenderBoxModelObject(over->firstChild())->baselinePosition(AlphabeticBaseline, true, HorizontalLine))); - - // base row wrapper - base = over->nextSibling(); - if (base) { - if (overSpacing > 0) - base->style()->setMarginTop(Length(-overSpacing, Fixed)); - else - base->style()->setMarginTop(Length(0, Fixed)); - } - - } - break; - case Under: - // FIXME: Non-ascending glyphs in the under should be moved closer to the base - - // We need to calculate the baseline of the base versus the start of the under block and - // adjust the placement of the under block. - - // base row wrapper - base = firstChild(); - if (base) { - int baseHeight = getOffsetHeight(base); - // actual base - base = base->firstChild(); - if (!base || !base->isBoxModelObject()) - break; - - // FIXME: We need to look at the space between a single maximum height of - // the line boxes and the baseline and squeeze them together - LayoutUnit underSpacing = baseHeight - toRenderBoxModelObject(base)->baselinePosition(AlphabeticBaseline, true, HorizontalLine); - - // adjust the base's intrusion into the under - RenderObject* under = lastChild(); - if (under && underSpacing > 0) - under->style()->setMarginTop(Length(-underSpacing, Fixed)); - } - break; - case UnderOver: - // FIXME: Non-descending glyphs in the over should be moved closer to the base - // FIXME: Non-ascending glyphs in the under should be moved closer to the base - - // We need to calculate the baseline of the over versus the start of the base and - // adjust the placement of the base. - - over = firstChild(); - if (over) { - // FIXME: descending glyphs intrude into base (e.g. lowercase y over base) - // FIXME: bases that ascend higher than the line box intrude into the over - if (!over->firstChild() || !over->firstChild()->isBoxModelObject()) - break; - LayoutUnit overSpacing = static_cast<LayoutUnit>(gOverSpacingAdjustment * (getOffsetHeight(over) - toRenderBoxModelObject(over->firstChild())->baselinePosition(AlphabeticBaseline, true, HorizontalLine))); - - // base row wrapper - base = over->nextSibling(); - - if (base) { - if (overSpacing > 0) - base->style()->setMarginTop(Length(-overSpacing, Fixed)); - - // We need to calculate the baseline of the base versus the start of the under block and - // adjust the placement of the under block. - - int baseHeight = getOffsetHeight(base); - // actual base - base = base->firstChild(); - if (!base || !base->isBoxModelObject()) - break; - - // FIXME: We need to look at the space between a single maximum height of - // the line boxes and the baseline and squeeze them together - LayoutUnit underSpacing = baseHeight - toRenderBoxModelObject(base)->baselinePosition(AlphabeticBaseline, true, HorizontalLine); - - RenderObject* under = lastChild(); - if (under && under->firstChild() && under->firstChild()->isRenderInline() && underSpacing > 0) - under->style()->setMarginTop(Length(-underSpacing, Fixed)); - - } - } - break; - } - setNeedsLayout(true); - RenderBlock::layout(); -} - -LayoutUnit RenderMathMLUnderOver::baselinePosition(FontBaseline, bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) const +LayoutUnit RenderMathMLUnderOver::baselinePosition(FontBaseline baselineType, bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) const { RenderObject* current = firstChild(); if (!current || linePositionMode == PositionOfInteriorLineBoxes) - return RenderBlock::baselinePosition(AlphabeticBaseline, firstLine, direction, linePositionMode); + return RenderMathMLBlock::baselinePosition(baselineType, firstLine, direction, linePositionMode); - LayoutUnit baseline = 0; + LayoutUnit baseline = direction == HorizontalLine ? marginTop() : marginRight(); switch (m_kind) { case UnderOver: case Over: - baseline += getOffsetHeight(current); - current = current->nextSibling(); - if (current) { - // actual base - RenderObject* base = current->firstChild(); - if (!base || !base->isBoxModelObject()) - break; - baseline += toRenderBoxModelObject(base)->baselinePosition(AlphabeticBaseline, firstLine, HorizontalLine, linePositionMode); - // added the negative top margin - baseline += current->style()->marginTop().value(); + if (current->nextSibling()) { + baseline += getOffsetHeight(current); + current = current->nextSibling(); } - break; + // fall through case Under: - RenderObject* base = current->firstChild(); - if (base && base->isBoxModelObject()) - baseline += toRenderBoxModelObject(base)->baselinePosition(AlphabeticBaseline, true, HorizontalLine); + ASSERT(current->isRenderBlock()); + baseline += toRenderBox(current)->firstLineBoxBaseline(); } return baseline; diff --git a/Source/WebCore/rendering/mathml/RenderMathMLUnderOver.h b/Source/WebCore/rendering/mathml/RenderMathMLUnderOver.h index b450689c9..07107b94a 100644 --- a/Source/WebCore/rendering/mathml/RenderMathMLUnderOver.h +++ b/Source/WebCore/rendering/mathml/RenderMathMLUnderOver.h @@ -39,7 +39,6 @@ public: virtual RenderMathMLOperator* unembellishedOperator(); - virtual void layout(); virtual LayoutUnit baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const; private: diff --git a/Source/WebCore/rendering/style/QuotesData.cpp b/Source/WebCore/rendering/style/QuotesData.cpp index 4e81f7567..c854bd53c 100644 --- a/Source/WebCore/rendering/style/QuotesData.cpp +++ b/Source/WebCore/rendering/style/QuotesData.cpp @@ -1,5 +1,6 @@ /** * Copyright (C) 2011 Nokia Inc. All rights reserved. + * Copyright (C) 2012 Google 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 @@ -23,38 +24,53 @@ namespace WebCore { -QuotesData* QuotesData::create(int stringCount) +PassRefPtr<QuotesData> QuotesData::create(String open, String close) { - char* tmp = new char[sizeof(QuotesData)+sizeof(String)*stringCount]; - if (!tmp) - return 0; - QuotesData* ret = new (tmp) QuotesData(stringCount); - for (int i = 0; i < stringCount; ++i) - new (tmp +sizeof(QuotesData) + sizeof(String)*i) String(); - return ret; + RefPtr<QuotesData> data = QuotesData::create(); + data->addPair(std::make_pair(open, close)); + return data; } -bool QuotesData::equal(const QuotesData* quotesData1, const QuotesData* quotesData2) +PassRefPtr<QuotesData> QuotesData::create(String open1, String close1, String open2, String close2) { - if (quotesData1 == quotesData2) - return true; - if (!quotesData1 || !quotesData2) - return false; - if (quotesData1->length != quotesData2->length) - return false; - const String* data1 = quotesData1->data(); - const String* data2 = quotesData2->data(); - for (int i = quotesData1->length - 1; i >= 0; --i) - if (data1[i] != data2[i]) - return false; - return true; + RefPtr<QuotesData> data = QuotesData::create(); + data->addPair(std::make_pair(open1, close1)); + data->addPair(std::make_pair(open2, close2)); + return data; +} + +void QuotesData::addPair(std::pair<String, String> quotePair) +{ + m_quotePairs.append(quotePair); +} + +const String QuotesData::getOpenQuote(int index) const +{ + ASSERT(index >= 0); + if (!m_quotePairs.size()) + return emptyString(); + if ((size_t)index >= m_quotePairs.size()) + return m_quotePairs.last().first; + return m_quotePairs.at(index).first; } -QuotesData::~QuotesData() +const String QuotesData::getCloseQuote(int index) const { - String* p = data(); - for (int i = 0; i < length; ++i) - p[i].~String(); + ASSERT(index >= 0); + if (!m_quotePairs.size()) + return emptyString(); + if ((size_t)index >= m_quotePairs.size()) + return m_quotePairs.last().second; + return m_quotePairs.at(index).second; +} + +bool QuotesData::equals(const QuotesData* a, const QuotesData* b) +{ + if (a == b) + return true; + if (!a || !b) + return false; + return a->m_quotePairs == b->m_quotePairs; } } // namespace WebCore diff --git a/Source/WebCore/rendering/style/QuotesData.h b/Source/WebCore/rendering/style/QuotesData.h index f817996f0..5699f3245 100644 --- a/Source/WebCore/rendering/style/QuotesData.h +++ b/Source/WebCore/rendering/style/QuotesData.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2011 Nokia Inc. All rights reserved. + * Copyright (C) 2012 Google 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 @@ -21,24 +22,32 @@ #ifndef QuotesData_h #define QuotesData_h +#include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> -#include <wtf/RefPtr.h> +#include <wtf/Vector.h> #include <wtf/text/WTFString.h> namespace WebCore { class QuotesData : public RefCounted<QuotesData> { public: - virtual ~QuotesData(); - static QuotesData* create(int stringCount); - String* data() { return reinterpret_cast<String*>(this+1); } - const String* data() const { return reinterpret_cast<const String*>(this+1); } - int length; - void operator delete(void* p) { delete[] static_cast<char*>(p); } - static bool equal(const QuotesData*, const QuotesData*); + static PassRefPtr<QuotesData> create() { return adoptRef(new QuotesData()); } + static PassRefPtr<QuotesData> create(const String open, const String close); + static PassRefPtr<QuotesData> create(const String open1, const String close1, const String open2, const String close2); + + // FIXME: this should be an operator==. + static bool equals(const QuotesData*, const QuotesData*); + + void addPair(const std::pair<String, String> quotePair); + const String getOpenQuote(int index) const; + const String getCloseQuote(int index) const; + private: - QuotesData(int stringCount) : length(stringCount) {} + QuotesData() { } + + Vector<std::pair<String, String> > m_quotePairs; }; -} +} // namespace WebCore + #endif // QuotesData_h diff --git a/Source/WebCore/rendering/style/RenderStyle.cpp b/Source/WebCore/rendering/style/RenderStyle.cpp index 8e5a90e8c..2303ffa04 100644 --- a/Source/WebCore/rendering/style/RenderStyle.cpp +++ b/Source/WebCore/rendering/style/RenderStyle.cpp @@ -28,6 +28,7 @@ #include "CSSPropertyNames.h" #include "CSSWrapShapes.h" #include "FontSelector.h" +#include "MemoryInstrumentation.h" #include "QuotesData.h" #include "RenderArena.h" #include "RenderObject.h" @@ -444,7 +445,7 @@ StyleDifference RenderStyle::diff(const RenderStyle* other, unsigned& changedCon } #endif -#if ENABLE(DASHBOARD_SUPPORT) +#if ENABLE(DASHBOARD_SUPPORT) || ENABLE(WIDGET_REGION) // If regions change, trigger a relayout to re-calc regions. if (rareNonInheritedData->m_dashboardRegions != other->rareNonInheritedData->m_dashboardRegions) return StyleDifferenceLayout; @@ -579,6 +580,9 @@ StyleDifference RenderStyle::diff(const RenderStyle* other, unsigned& changedCon return StyleDifferenceLayout; } + if (!QuotesData::equals(rareInheritedData->quotes.get(), other->rareInheritedData->quotes.get())) + return StyleDifferenceLayout; + #if ENABLE(SVG) // SVGRenderStyle::diff() might have returned StyleDifferenceRepaint, eg. if fill changes. // If eg. the font-size changed at the same time, we're not allowed to return StyleDifferenceRepaint, @@ -700,7 +704,7 @@ void RenderStyle::setCursorList(PassRefPtr<CursorList> other) void RenderStyle::setQuotes(PassRefPtr<QuotesData> q) { - if (QuotesData::equal(rareInheritedData->quotes.get(), q.get())) + if (QuotesData::equals(rareInheritedData->quotes.get(), q.get())) return; rareInheritedData.access()->quotes = q; } @@ -1049,7 +1053,7 @@ const AtomicString& RenderStyle::textEmphasisMarkString() const return nullAtom; } -#if ENABLE(DASHBOARD_SUPPORT) +#if ENABLE(DASHBOARD_SUPPORT) || ENABLE(WIDGET_REGION) const Vector<StyleDashboardRegion>& RenderStyle::initialDashboardRegions() { DEFINE_STATIC_LOCAL(Vector<StyleDashboardRegion>, emptyList, ()); @@ -1486,4 +1490,24 @@ LayoutBoxExtent RenderStyle::imageOutsets(const NinePieceImage& image) const NinePieceImage::computeOutset(image.outset().left(), borderLeftWidth())); } +void RenderStyle::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const +{ + MemoryClassInfo info(memoryObjectInfo, this, MemoryInstrumentation::CSS); + info.addMember(m_box); + info.addMember(visual); + // FIXME: m_background contains RefPtr<StyleImage> that might need to be instrumented. + info.addMember(m_background); + // FIXME: surrond contains some fields e.g. BorderData that might need to be instrumented. + info.addMember(surround); + info.addInstrumentedMember(rareNonInheritedData); + info.addInstrumentedMember(rareInheritedData); + // FIXME: inherited contains StyleImage and Font fields that might need to be instrumented. + info.addMember(inherited); + if (m_cachedPseudoStyles) + info.addVectorPtr(m_cachedPseudoStyles.get()); +#if ENABLE(SVG) + info.addMember(m_svgStyle); +#endif +} + } // namespace WebCore diff --git a/Source/WebCore/rendering/style/RenderStyle.h b/Source/WebCore/rendering/style/RenderStyle.h index d56d2d3c1..5c0bd5dcf 100644 --- a/Source/WebCore/rendering/style/RenderStyle.h +++ b/Source/WebCore/rendering/style/RenderStyle.h @@ -78,7 +78,7 @@ #include "StyleFilterData.h" #endif -#if ENABLE(DASHBOARD_SUPPORT) +#if ENABLE(DASHBOARD_SUPPORT) || ENABLE(WIDGET_REGION) #include "StyleDashboardRegion.h" #endif @@ -105,6 +105,7 @@ class BorderData; class CounterContent; class CursorList; class IntRect; +class MemoryObjectInfo; class Pair; class ShadowData; class StyleImage; @@ -798,7 +799,7 @@ public: EBoxOrient boxOrient() const { return static_cast<EBoxOrient>(rareNonInheritedData->m_deprecatedFlexibleBox->orient); } EBoxPack boxPack() const { return static_cast<EBoxPack>(rareNonInheritedData->m_deprecatedFlexibleBox->pack); } - float order() const { return rareNonInheritedData->m_order; } + int order() const { return rareNonInheritedData->m_order; } float flexGrow() const { return rareNonInheritedData->m_flexibleBox->m_flexGrow; } float flexShrink() const { return rareNonInheritedData->m_flexibleBox->m_flexShrink; } Length flexBasis() const { return rareNonInheritedData->m_flexibleBox->m_flexBasis; } @@ -1011,7 +1012,7 @@ public: void setMinHeight(Length v) { SET_VAR(m_box, m_minHeight, v) } void setMaxHeight(Length v) { SET_VAR(m_box, m_maxHeight, v) } -#if ENABLE(DASHBOARD_SUPPORT) +#if ENABLE(DASHBOARD_SUPPORT) || ENABLE(WIDGET_REGION) Vector<StyleDashboardRegion> dashboardRegions() const { return rareNonInheritedData->m_dashboardRegions; } void setDashboardRegions(Vector<StyleDashboardRegion> regions) { SET_VAR(rareNonInheritedData, m_dashboardRegions, regions); } @@ -1268,7 +1269,7 @@ public: void setFlexGrow(float f) { SET_VAR(rareNonInheritedData.access()->m_flexibleBox, m_flexGrow, f); } void setFlexShrink(float f) { SET_VAR(rareNonInheritedData.access()->m_flexibleBox, m_flexShrink, f); } void setFlexBasis(Length length) { SET_VAR(rareNonInheritedData.access()->m_flexibleBox, m_flexBasis, length); } - void setOrder(float o) { SET_VAR(rareNonInheritedData, m_order, o); } + void setOrder(int o) { SET_VAR(rareNonInheritedData, m_order, o); } void setAlignContent(EAlignContent p) { SET_VAR(rareNonInheritedData, m_alignContent, p); } void setAlignItems(EAlignItems a) { SET_VAR(rareNonInheritedData, m_alignItems, a); } void setAlignSelf(EAlignItems a) { SET_VAR(rareNonInheritedData, m_alignSelf, a); } @@ -1483,22 +1484,9 @@ public: StyleDifference diff(const RenderStyle*, unsigned& changedContextSensitiveProperties) const; - bool isDisplayReplacedType() const - { - return display() == INLINE_BLOCK || display() == INLINE_BOX || display() == INLINE_TABLE || display() == INLINE_GRID; - } - - bool isDisplayInlineType() const - { - return display() == INLINE || isDisplayReplacedType(); - } - - bool isOriginalDisplayInlineType() const - { - return originalDisplay() == INLINE || originalDisplay() == INLINE_BLOCK - || originalDisplay() == INLINE_BOX || originalDisplay() == INLINE_TABLE || originalDisplay() == INLINE_GRID; - } - + bool isDisplayReplacedType() const { return isDisplayReplacedType(display()); } + bool isDisplayInlineType() const { return isDisplayInlineType(display()); } + bool isOriginalDisplayInlineType() const { return isDisplayInlineType(originalDisplay()); } bool isDisplayRegionType() const { return display() == BLOCK || display() == INLINE_BLOCK @@ -1541,6 +1529,8 @@ public: void setHasExplicitlyInheritedProperties() { m_bitfields.setExplicitInheritance(true); } bool hasExplicitlyInheritedProperties() const { return m_bitfields.explicitInheritance(); } + + void reportMemoryUsage(MemoryObjectInfo*) const; // Initial values for all the properties static EBorderCollapse initialBorderCollapse() { return BSEPARATE; } @@ -1610,7 +1600,7 @@ public: static float initialFlexGrow() { return 0; } static float initialFlexShrink() { return 1; } static Length initialFlexBasis() { return Length(Auto); } - static float initialOrder() { return 0; } + static int initialOrder() { return 0; } static EAlignContent initialAlignContent() { return AlignContentStretch; } static EAlignItems initialAlignItems() { return AlignStretch; } static EAlignItems initialAlignSelf() { return AlignAuto; } @@ -1715,7 +1705,7 @@ public: #if ENABLE(OVERFLOW_SCROLLING) static bool initialUseTouchOverflowScrolling() { return false; } #endif -#if ENABLE(DASHBOARD_SUPPORT) +#if ENABLE(DASHBOARD_SUPPORT) || ENABLE(WIDGET_REGION) static const Vector<StyleDashboardRegion>& initialDashboardRegions(); static const Vector<StyleDashboardRegion>& noneDashboardRegions(); #endif @@ -1748,6 +1738,20 @@ private: return isHorizontalWritingMode() ? getShadowVerticalExtent(shadow, logicalTop, logicalBottom) : getShadowHorizontalExtent(shadow, logicalTop, logicalBottom); } + bool isDisplayReplacedType(EDisplay display) const + { + return display == INLINE_BLOCK || display == INLINE_BOX +#if ENABLE(CSS3_FLEXBOX) + || display == INLINE_FLEX +#endif + || display == INLINE_TABLE || display == INLINE_GRID; + } + + bool isDisplayInlineType(EDisplay display) const + { + return display == INLINE || isDisplayReplacedType(display); + } + // Color accessors are all private to make sure callers use visitedDependentColor instead to access them. Color invalidColor() const { static Color invalid; return invalid; } Color borderLeftColor() const { return surround->border.left().color(); } diff --git a/Source/WebCore/rendering/style/RenderStyleConstants.h b/Source/WebCore/rendering/style/RenderStyleConstants.h index 149cd4471..f71934a3c 100644 --- a/Source/WebCore/rendering/style/RenderStyleConstants.h +++ b/Source/WebCore/rendering/style/RenderStyleConstants.h @@ -198,7 +198,7 @@ enum EUserDrag { // CSS3 User Select Values enum EUserSelect { - SELECT_NONE, SELECT_TEXT + SELECT_NONE, SELECT_TEXT, SELECT_ALL }; // Word Break Values. Matches WinIE, rather than CSS3 diff --git a/Source/WebCore/rendering/style/StyleCachedImage.cpp b/Source/WebCore/rendering/style/StyleCachedImage.cpp index 2e3abb943..4e353e99a 100644 --- a/Source/WebCore/rendering/style/StyleCachedImage.cpp +++ b/Source/WebCore/rendering/style/StyleCachedImage.cpp @@ -24,6 +24,7 @@ #include "config.h" #include "StyleCachedImage.h" +#include "CachedImage.h" #include "RenderObject.h" namespace WebCore { diff --git a/Source/WebCore/rendering/style/StyleCachedImage.h b/Source/WebCore/rendering/style/StyleCachedImage.h index c9913fd82..0943b0e67 100644 --- a/Source/WebCore/rendering/style/StyleCachedImage.h +++ b/Source/WebCore/rendering/style/StyleCachedImage.h @@ -24,12 +24,14 @@ #ifndef StyleCachedImage_h #define StyleCachedImage_h -#include "CachedImage.h" +#include "CachedImageClient.h" #include "CachedResourceHandle.h" #include "StyleImage.h" namespace WebCore { +class CachedImage; + class StyleCachedImage : public StyleImage, private CachedImageClient { WTF_MAKE_FAST_ALLOCATED; public: diff --git a/Source/WebCore/rendering/style/StyleCachedImageSet.h b/Source/WebCore/rendering/style/StyleCachedImageSet.h index d35947fb3..7e7cafcd2 100644 --- a/Source/WebCore/rendering/style/StyleCachedImageSet.h +++ b/Source/WebCore/rendering/style/StyleCachedImageSet.h @@ -28,7 +28,7 @@ #if ENABLE(CSS_IMAGE_SET) -#include "CachedImage.h" +#include "CachedImageClient.h" #include "CachedResourceHandle.h" #include "StyleImage.h" diff --git a/Source/WebCore/rendering/style/StyleCustomFilterProgram.h b/Source/WebCore/rendering/style/StyleCustomFilterProgram.h index bff09a98c..1cbe01d35 100644 --- a/Source/WebCore/rendering/style/StyleCustomFilterProgram.h +++ b/Source/WebCore/rendering/style/StyleCustomFilterProgram.h @@ -45,9 +45,9 @@ namespace WebCore { class StyleCustomFilterProgram : public CustomFilterProgram, public CachedResourceClient { WTF_MAKE_FAST_ALLOCATED; public: - static PassRefPtr<StyleCustomFilterProgram> create(PassRefPtr<StyleShader> vertexShader, PassRefPtr<StyleShader> fragmentShader) + static PassRefPtr<StyleCustomFilterProgram> create(PassRefPtr<StyleShader> vertexShader, PassRefPtr<StyleShader> fragmentShader, CustomFilterProgramMixSettings mixSettings) { - return adoptRef(new StyleCustomFilterProgram(vertexShader, fragmentShader)); + return adoptRef(new StyleCustomFilterProgram(vertexShader, fragmentShader, mixSettings)); } void setVertexShader(PassRefPtr<StyleShader> shader) { m_vertexShader = shader; } @@ -106,9 +106,10 @@ public: { if (resource->errorOccurred()) return; + // Note that m_cachedVertexShader might be equal to m_cachedFragmentShader and it would only get one event in that case. if (resource == m_cachedVertexShader.get()) m_isVertexShaderLoaded = true; - else if (resource == m_cachedFragmentShader.get()) + if (resource == m_cachedFragmentShader.get()) m_isFragmentShaderLoaded = true; if (isLoaded()) notifyClients(); @@ -125,8 +126,9 @@ public: } private: - StyleCustomFilterProgram(PassRefPtr<StyleShader> vertexShader, PassRefPtr<StyleShader> fragmentShader) - : m_vertexShader(vertexShader) + StyleCustomFilterProgram(PassRefPtr<StyleShader> vertexShader, PassRefPtr<StyleShader> fragmentShader, CustomFilterProgramMixSettings mixSettings) + : CustomFilterProgram(mixSettings) + , m_vertexShader(vertexShader) , m_fragmentShader(fragmentShader) , m_isVertexShaderLoaded(false) , m_isFragmentShaderLoaded(false) diff --git a/Source/WebCore/rendering/style/StyleDashboardRegion.h b/Source/WebCore/rendering/style/StyleDashboardRegion.h index bbb0cda0c..552fdeb82 100644 --- a/Source/WebCore/rendering/style/StyleDashboardRegion.h +++ b/Source/WebCore/rendering/style/StyleDashboardRegion.h @@ -24,7 +24,7 @@ #ifndef StyleDashboardRegion_h #define StyleDashboardRegion_h -#if ENABLE(DASHBOARD_SUPPORT) +#if ENABLE(DASHBOARD_SUPPORT) || ENABLE(WIDGET_REGION) #include "LengthBox.h" #include "PlatformString.h" @@ -57,5 +57,5 @@ struct StyleDashboardRegion { } // namespace WebCore -#endif // ENABLE(DASHBOARD_SUPPORT) +#endif // ENABLE(DASHBOARD_SUPPORT) || ENABLE(WIDGET_REGION) #endif // StyleDashboardRegion_h diff --git a/Source/WebCore/rendering/style/StyleRareInheritedData.cpp b/Source/WebCore/rendering/style/StyleRareInheritedData.cpp index 97de42d3c..14cb67d88 100644 --- a/Source/WebCore/rendering/style/StyleRareInheritedData.cpp +++ b/Source/WebCore/rendering/style/StyleRareInheritedData.cpp @@ -23,6 +23,7 @@ #include "StyleRareInheritedData.h" #include "CursorList.h" +#include "MemoryInstrumentation.h" #include "QuotesData.h" #include "RenderStyle.h" #include "RenderStyleConstants.h" @@ -233,7 +234,7 @@ bool StyleRareInheritedData::operator==(const StyleRareInheritedData& o) const && hyphenationString == o.hyphenationString && locale == o.locale && textEmphasisCustomMark == o.textEmphasisCustomMark - && QuotesData::equal(quotes.get(), o.quotes.get()) + && QuotesData::equals(quotes.get(), o.quotes.get()) && m_tabSize == o.m_tabSize && m_lineGrid == o.m_lineGrid #if ENABLE(CSS_IMAGE_ORIENTATION) @@ -261,4 +262,20 @@ bool StyleRareInheritedData::shadowDataEquivalent(const StyleRareInheritedData& return true; } +void StyleRareInheritedData::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const +{ + MemoryClassInfo info(memoryObjectInfo, this, MemoryInstrumentation::CSS); + info.addMember(textShadow); + info.addMember(highlight); + info.addMember(cursorData); + info.addMember(hyphenationString); + info.addMember(locale); + info.addMember(textEmphasisCustomMark); + info.addMember(quotes); + info.addMember(m_lineGrid); +#if ENABLE(CSS_VARIABLES) + info.addMember(m_variables); +#endif +} + } // namespace WebCore diff --git a/Source/WebCore/rendering/style/StyleRareInheritedData.h b/Source/WebCore/rendering/style/StyleRareInheritedData.h index b30982df9..39e096ea4 100644 --- a/Source/WebCore/rendering/style/StyleRareInheritedData.h +++ b/Source/WebCore/rendering/style/StyleRareInheritedData.h @@ -39,6 +39,7 @@ namespace WebCore { class CursorList; +class MemoryObjectInfo; class QuotesData; class ShadowData; @@ -58,6 +59,8 @@ public: } bool shadowDataEquivalent(const StyleRareInheritedData&) const; + void reportMemoryUsage(MemoryObjectInfo*) const; + Color textStrokeColor; float textStrokeWidth; Color textFillColor; @@ -86,7 +89,7 @@ public: unsigned khtmlLineBreak : 1; // EKHTMLLineBreak unsigned textSizeAdjust : 1; // An Apple extension. unsigned resize : 2; // EResize - unsigned userSelect : 1; // EUserSelect + unsigned userSelect : 2; // EUserSelect unsigned colorSpace : 1; // ColorSpace unsigned speak : 3; // ESpeak unsigned hyphens : 2; // Hyphens diff --git a/Source/WebCore/rendering/style/StyleRareNonInheritedData.cpp b/Source/WebCore/rendering/style/StyleRareNonInheritedData.cpp index 22b3272e8..8d57922e3 100644 --- a/Source/WebCore/rendering/style/StyleRareNonInheritedData.cpp +++ b/Source/WebCore/rendering/style/StyleRareNonInheritedData.cpp @@ -23,6 +23,7 @@ #include "StyleRareNonInheritedData.h" #include "ContentData.h" +#include "MemoryInstrumentation.h" #include "RenderCounter.h" #include "RenderStyle.h" #include "ShadowData.h" @@ -166,7 +167,7 @@ bool StyleRareNonInheritedData::operator==(const StyleRareNonInheritedData& o) c && m_perspectiveOriginX == o.m_perspectiveOriginX && m_perspectiveOriginY == o.m_perspectiveOriginY && lineClamp == o.lineClamp -#if ENABLE(DASHBOARD_SUPPORT) +#if ENABLE(DASHBOARD_SUPPORT) || ENABLE(WIDGET_REGION) && m_dashboardRegions == o.m_dashboardRegions #endif && m_deprecatedFlexibleBox == o.m_deprecatedFlexibleBox @@ -286,4 +287,32 @@ bool StyleRareNonInheritedData::transitionDataEquivalent(const StyleRareNonInher return true; } +void StyleRareNonInheritedData::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const +{ + MemoryClassInfo info(memoryObjectInfo, this, MemoryInstrumentation::CSS); +#if ENABLE(DASHBOARD_SUPPORT) + info.addVector(m_dashboardRegions); +#endif + info.addMember(m_deprecatedFlexibleBox); + info.addMember(m_flexibleBox); + info.addMember(m_marquee); + info.addMember(m_multiCol); + info.addMember(m_transform); +#if ENABLE(CSS_FILTERS) + info.addMember(m_filter); +#endif + info.addMember(m_grid); + info.addMember(m_gridItem); + info.addMember(m_content); + info.addMember(m_counterDirectives); + info.addMember(m_boxShadow); + info.addMember(m_boxReflect); + info.addMember(m_animations); + info.addMember(m_transitions); + info.addMember(m_wrapShapeInside); + info.addMember(m_wrapShapeOutside); + info.addMember(m_flowThread); + info.addMember(m_regionThread); +} + } // namespace WebCore diff --git a/Source/WebCore/rendering/style/StyleRareNonInheritedData.h b/Source/WebCore/rendering/style/StyleRareNonInheritedData.h index 5e6fde2a6..a206015ec 100644 --- a/Source/WebCore/rendering/style/StyleRareNonInheritedData.h +++ b/Source/WebCore/rendering/style/StyleRareNonInheritedData.h @@ -39,6 +39,7 @@ namespace WebCore { class AnimationList; +class MemoryObjectInfo; class ShadowData; class StyleDeprecatedFlexibleBoxData; #if ENABLE(CSS_FILTERS) @@ -56,7 +57,7 @@ class StyleTransformData; class ContentData; struct LengthSize; -#if ENABLE(DASHBOARD_SUPPORT) +#if ENABLE(DASHBOARD_SUPPORT) || ENABLE(WIDGET_REGION) struct StyleDashboardRegion; #endif @@ -89,6 +90,8 @@ public: bool animationDataEquivalent(const StyleRareNonInheritedData&) const; bool transitionDataEquivalent(const StyleRareNonInheritedData&) const; + void reportMemoryUsage(MemoryObjectInfo*) const; + float opacity; // Whether or not we're transparent. float m_aspectRatioDenominator; @@ -102,7 +105,7 @@ public: Length m_perspectiveOriginY; LineClampValue lineClamp; // An Apple extension. -#if ENABLE(DASHBOARD_SUPPORT) +#if ENABLE(DASHBOARD_SUPPORT) || ENABLE(WIDGET_REGION) Vector<StyleDashboardRegion> m_dashboardRegions; #endif @@ -146,7 +149,7 @@ public: Color m_visitedLinkBorderTopColor; Color m_visitedLinkBorderBottomColor; - float m_order; + int m_order; AtomicString m_flowThread; AtomicString m_regionThread; diff --git a/Source/WebCore/rendering/svg/RenderSVGForeignObject.cpp b/Source/WebCore/rendering/svg/RenderSVGForeignObject.cpp index d66056615..0a975f415 100644 --- a/Source/WebCore/rendering/svg/RenderSVGForeignObject.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGForeignObject.cpp @@ -190,7 +190,7 @@ bool RenderSVGForeignObject::nodeAtPoint(const HitTestRequest&, HitTestResult&, return false; } -void RenderSVGForeignObject::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool /* fixed */, bool /* useTransforms */, TransformState& transformState, ApplyContainerFlipOrNot, bool* wasFixed) const +void RenderSVGForeignObject::mapLocalToContainer(RenderBoxModelObject* repaintContainer, TransformState& transformState, MapLocalToContainerFlags, bool* wasFixed) const { SVGRenderSupport::mapLocalToContainer(this, repaintContainer, transformState, wasFixed); } diff --git a/Source/WebCore/rendering/svg/RenderSVGForeignObject.h b/Source/WebCore/rendering/svg/RenderSVGForeignObject.h index 80ddfd630..7da36eac6 100644 --- a/Source/WebCore/rendering/svg/RenderSVGForeignObject.h +++ b/Source/WebCore/rendering/svg/RenderSVGForeignObject.h @@ -54,7 +54,7 @@ public: virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE; virtual bool isSVGForeignObject() const { return true; } - virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed, bool useTransforms, TransformState&, ApplyContainerFlipOrNot = ApplyContainerFlip, bool* wasFixed = 0) const; + virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, TransformState&, MapLocalToContainerFlags mode = ApplyContainerFlip, bool* wasFixed = 0) const OVERRIDE; virtual const RenderObject* pushMappingToContainer(const RenderBoxModelObject* ancestorToStopAt, RenderGeometryMap&) const; virtual void setNeedsTransformUpdate() { m_needsTransformUpdate = true; } diff --git a/Source/WebCore/rendering/svg/RenderSVGInline.cpp b/Source/WebCore/rendering/svg/RenderSVGInline.cpp index 057bfda00..2c6312eeb 100644 --- a/Source/WebCore/rendering/svg/RenderSVGInline.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGInline.cpp @@ -79,7 +79,7 @@ void RenderSVGInline::computeFloatRectForRepaint(RenderBoxModelObject* repaintCo SVGRenderSupport::computeFloatRectForRepaint(this, repaintContainer, repaintRect, fixed); } -void RenderSVGInline::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool /* useTransforms */, bool /* fixed */, TransformState& transformState, ApplyContainerFlipOrNot, bool* wasFixed) const +void RenderSVGInline::mapLocalToContainer(RenderBoxModelObject* repaintContainer, TransformState& transformState, MapLocalToContainerFlags, bool* wasFixed) const { SVGRenderSupport::mapLocalToContainer(this, repaintContainer, transformState, wasFixed); } diff --git a/Source/WebCore/rendering/svg/RenderSVGInline.h b/Source/WebCore/rendering/svg/RenderSVGInline.h index 533a99aa6..3dc7dda80 100644 --- a/Source/WebCore/rendering/svg/RenderSVGInline.h +++ b/Source/WebCore/rendering/svg/RenderSVGInline.h @@ -47,7 +47,7 @@ public: virtual LayoutRect clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer) const; virtual void computeFloatRectForRepaint(RenderBoxModelObject* repaintContainer, FloatRect&, bool fixed = false) const; - virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool useTransforms, bool fixed, TransformState&, ApplyContainerFlipOrNot = ApplyContainerFlip, bool* wasFixed = 0) const; + virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, TransformState&, MapLocalToContainerFlags mode = ApplyContainerFlip, bool* wasFixed = 0) const OVERRIDE; virtual const RenderObject* pushMappingToContainer(const RenderBoxModelObject* ancestorToStopAt, RenderGeometryMap&) const; virtual void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const; diff --git a/Source/WebCore/rendering/svg/RenderSVGModelObject.cpp b/Source/WebCore/rendering/svg/RenderSVGModelObject.cpp index 18e7ecace..7314179c8 100644 --- a/Source/WebCore/rendering/svg/RenderSVGModelObject.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGModelObject.cpp @@ -55,7 +55,7 @@ void RenderSVGModelObject::computeFloatRectForRepaint(RenderBoxModelObject* repa SVGRenderSupport::computeFloatRectForRepaint(this, repaintContainer, repaintRect, fixed); } -void RenderSVGModelObject::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool /* fixed */, bool /* useTransforms */, TransformState& transformState, ApplyContainerFlipOrNot, bool* wasFixed) const +void RenderSVGModelObject::mapLocalToContainer(RenderBoxModelObject* repaintContainer, TransformState& transformState, MapLocalToContainerFlags, bool* wasFixed) const { SVGRenderSupport::mapLocalToContainer(this, repaintContainer, transformState, wasFixed); } diff --git a/Source/WebCore/rendering/svg/RenderSVGModelObject.h b/Source/WebCore/rendering/svg/RenderSVGModelObject.h index 0d8192609..b4c3f68aa 100644 --- a/Source/WebCore/rendering/svg/RenderSVGModelObject.h +++ b/Source/WebCore/rendering/svg/RenderSVGModelObject.h @@ -58,7 +58,7 @@ public: virtual void absoluteRects(Vector<IntRect>&, const LayoutPoint& accumulatedOffset) const; virtual void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const; - virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool useTransforms, bool fixed, TransformState&, ApplyContainerFlipOrNot = ApplyContainerFlip, bool* wasFixed = 0) const; + virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, TransformState&, MapLocalToContainerFlags mode = ApplyContainerFlip, bool* wasFixed = 0) const OVERRIDE; virtual const RenderObject* pushMappingToContainer(const RenderBoxModelObject* ancestorToStopAt, RenderGeometryMap&) const; virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle); virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); diff --git a/Source/WebCore/rendering/svg/RenderSVGRoot.cpp b/Source/WebCore/rendering/svg/RenderSVGRoot.cpp index 707da886e..5d56b5ce7 100644 --- a/Source/WebCore/rendering/svg/RenderSVGRoot.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGRoot.cpp @@ -395,12 +395,12 @@ void RenderSVGRoot::computeFloatRectForRepaint(RenderBoxModelObject* repaintCont // This method expects local CSS box coordinates. // Callers with local SVG viewport coordinates should first apply the localToBorderBoxTransform // to convert from SVG viewport coordinates to local CSS box coordinates. -void RenderSVGRoot::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed, bool useTransforms, TransformState& transformState, ApplyContainerFlipOrNot, bool* wasFixed) const +void RenderSVGRoot::mapLocalToContainer(RenderBoxModelObject* repaintContainer, TransformState& transformState, MapLocalToContainerFlags mode, bool* wasFixed) const { - ASSERT(!fixed); // We should have no fixed content in the SVG rendering tree. - ASSERT(useTransforms); // mapping a point through SVG w/o respecting trasnforms is useless. + ASSERT(mode & ~IsFixed); // We should have no fixed content in the SVG rendering tree. + ASSERT(mode & UseTransforms); // mapping a point through SVG w/o respecting trasnforms is useless. - RenderReplaced::mapLocalToContainer(repaintContainer, fixed, useTransforms, transformState, ApplyContainerFlip, wasFixed); + RenderReplaced::mapLocalToContainer(repaintContainer, transformState, mode | ApplyContainerFlip, wasFixed); } const RenderObject* RenderSVGRoot::pushMappingToContainer(const RenderBoxModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap) const diff --git a/Source/WebCore/rendering/svg/RenderSVGRoot.h b/Source/WebCore/rendering/svg/RenderSVGRoot.h index 9aa7e7c18..3e2f3c70d 100644 --- a/Source/WebCore/rendering/svg/RenderSVGRoot.h +++ b/Source/WebCore/rendering/svg/RenderSVGRoot.h @@ -95,7 +95,7 @@ private: virtual LayoutRect clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer) const; virtual void computeFloatRectForRepaint(RenderBoxModelObject* repaintContainer, FloatRect& repaintRect, bool fixed) const; - virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool useTransforms, bool fixed, TransformState&, ApplyContainerFlipOrNot = ApplyContainerFlip, bool* wasFixed = 0) const; + virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, TransformState&, MapLocalToContainerFlags mode = ApplyContainerFlip, bool* wasFixed = 0) const OVERRIDE; virtual const RenderObject* pushMappingToContainer(const RenderBoxModelObject* ancestorToStopAt, RenderGeometryMap&) const; virtual bool canBeSelectionLeaf() const { return false; } diff --git a/Source/WebCore/rendering/svg/RenderSVGText.cpp b/Source/WebCore/rendering/svg/RenderSVGText.cpp index d30ba1cd6..398babe03 100644 --- a/Source/WebCore/rendering/svg/RenderSVGText.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGText.cpp @@ -111,7 +111,7 @@ void RenderSVGText::computeFloatRectForRepaint(RenderBoxModelObject* repaintCont SVGRenderSupport::computeFloatRectForRepaint(this, repaintContainer, repaintRect, fixed); } -void RenderSVGText::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool /* fixed */, bool /* useTransforms */, TransformState& transformState, ApplyContainerFlipOrNot, bool* wasFixed) const +void RenderSVGText::mapLocalToContainer(RenderBoxModelObject* repaintContainer, TransformState& transformState, MapLocalToContainerFlags, bool* wasFixed) const { SVGRenderSupport::mapLocalToContainer(this, repaintContainer, transformState, wasFixed); } diff --git a/Source/WebCore/rendering/svg/RenderSVGText.h b/Source/WebCore/rendering/svg/RenderSVGText.h index 93cb64f8f..ee2dbda23 100644 --- a/Source/WebCore/rendering/svg/RenderSVGText.h +++ b/Source/WebCore/rendering/svg/RenderSVGText.h @@ -75,7 +75,7 @@ private: virtual void computeRectForRepaint(RenderBoxModelObject* repaintContainer, LayoutRect&, bool fixed = false) const; virtual void computeFloatRectForRepaint(RenderBoxModelObject* repaintContainer, FloatRect&, bool fixed = false) const; - virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool useTransforms, bool fixed, TransformState&, ApplyContainerFlipOrNot = ApplyContainerFlip, bool* wasFixed = 0) const; + virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, TransformState&, MapLocalToContainerFlags mode = ApplyContainerFlip, bool* wasFixed = 0) const OVERRIDE; virtual const RenderObject* pushMappingToContainer(const RenderBoxModelObject* ancestorToStopAt, RenderGeometryMap&) const; virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0); virtual void removeChild(RenderObject*) OVERRIDE; diff --git a/Source/WebCore/rendering/svg/SVGRenderSupport.cpp b/Source/WebCore/rendering/svg/SVGRenderSupport.cpp index 0bfb0a527..d88371429 100644 --- a/Source/WebCore/rendering/svg/SVGRenderSupport.cpp +++ b/Source/WebCore/rendering/svg/SVGRenderSupport.cpp @@ -83,7 +83,7 @@ void SVGRenderSupport::mapLocalToContainer(const RenderObject* object, RenderBox if (parent->isSVGRoot()) transformState.applyTransform(toRenderSVGRoot(parent)->localToBorderBoxTransform()); - parent->mapLocalToContainer(repaintContainer, false, true, transformState, RenderObject::DoNotApplyContainerFlip, wasFixed); + parent->mapLocalToContainer(repaintContainer, transformState, UseTransforms, wasFixed); } const RenderObject* SVGRenderSupport::pushMappingToContainer(const RenderObject* object, const RenderBoxModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap) @@ -207,6 +207,7 @@ void SVGRenderSupport::layoutChildren(RenderObject* start, bool selfNeedsLayout) for (RenderObject* child = start->firstChild(); child; child = child->nextSibling()) { bool needsLayout = selfNeedsLayout; + bool childEverHadLayout = child->everHadLayout(); if (transformChanged) { // If the transform changed we need to update the text metrics (note: this also happens for layoutSizeChanged=true). @@ -232,15 +233,19 @@ void SVGRenderSupport::layoutChildren(RenderObject* start, bool selfNeedsLayout) } } - if (needsLayout) { + if (needsLayout) child->setNeedsLayout(true, MarkOnlyThis); + + if (child->needsLayout()) { child->layout(); - } else { - if (child->needsLayout()) - child->layout(); - else if (layoutSizeChanged) - notlayoutedObjects.add(child); - } + // Renderers are responsible for repainting themselves when changing, except + // for the initial paint to avoid potential double-painting caused by non-sensical "old" bounds. + // We could handle this in the individual objects, but for now it's easier to have + // parent containers call repaint(). (RenderBlock::layout* has similar logic.) + if (!childEverHadLayout) + child->repaint(); + } else if (layoutSizeChanged) + notlayoutedObjects.add(child); ASSERT(!child->needsLayout()); } |