summaryrefslogtreecommitdiff
path: root/Source/WebCore/rendering
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/rendering')
-rw-r--r--Source/WebCore/rendering/EllipsisBox.cpp8
-rw-r--r--Source/WebCore/rendering/HitTestResult.cpp140
-rw-r--r--Source/WebCore/rendering/HitTestResult.h64
-rw-r--r--Source/WebCore/rendering/InlineFlowBox.cpp8
-rw-r--r--Source/WebCore/rendering/InlineTextBox.cpp31
-rw-r--r--Source/WebCore/rendering/InlineTextBox.h5
-rw-r--r--Source/WebCore/rendering/LayoutState.cpp10
-rw-r--r--Source/WebCore/rendering/LayoutState.h4
-rwxr-xr-xSource/WebCore/rendering/RenderBlock.cpp311
-rw-r--r--Source/WebCore/rendering/RenderBlock.h25
-rwxr-xr-xSource/WebCore/rendering/RenderBlockLineLayout.cpp2
-rw-r--r--Source/WebCore/rendering/RenderBox.cpp23
-rw-r--r--Source/WebCore/rendering/RenderBox.h27
-rw-r--r--Source/WebCore/rendering/RenderBoxModelObject.cpp23
-rw-r--r--Source/WebCore/rendering/RenderBoxModelObject.h24
-rw-r--r--Source/WebCore/rendering/RenderDeprecatedFlexibleBox.cpp2
-rw-r--r--Source/WebCore/rendering/RenderEmbeddedObject.cpp36
-rw-r--r--Source/WebCore/rendering/RenderEmbeddedObject.h2
-rw-r--r--Source/WebCore/rendering/RenderFlowThread.cpp8
-rw-r--r--Source/WebCore/rendering/RenderFrameBase.cpp25
-rw-r--r--Source/WebCore/rendering/RenderFrameSet.cpp6
-rw-r--r--Source/WebCore/rendering/RenderImage.cpp5
-rw-r--r--Source/WebCore/rendering/RenderInline.cpp39
-rw-r--r--Source/WebCore/rendering/RenderLayer.cpp68
-rw-r--r--Source/WebCore/rendering/RenderLayer.h11
-rw-r--r--Source/WebCore/rendering/RenderLayerBacking.cpp7
-rw-r--r--Source/WebCore/rendering/RenderLayerCompositor.cpp13
-rwxr-xr-xSource/WebCore/rendering/RenderObject.cpp7
-rw-r--r--Source/WebCore/rendering/RenderObject.h3
-rw-r--r--Source/WebCore/rendering/RenderQuote.cpp2
-rw-r--r--Source/WebCore/rendering/RenderScrollbar.cpp2
-rw-r--r--Source/WebCore/rendering/RenderScrollbarPart.cpp7
-rw-r--r--Source/WebCore/rendering/RenderScrollbarPart.h20
-rw-r--r--Source/WebCore/rendering/RenderTable.cpp35
-rw-r--r--Source/WebCore/rendering/RenderTable.h3
-rw-r--r--Source/WebCore/rendering/RenderTableCell.cpp5
-rw-r--r--Source/WebCore/rendering/RenderTableRow.cpp2
-rw-r--r--Source/WebCore/rendering/RenderTableSection.cpp12
-rw-r--r--Source/WebCore/rendering/RenderTextControl.cpp3
-rw-r--r--Source/WebCore/rendering/RenderThemeMac.h2
-rw-r--r--Source/WebCore/rendering/RenderThemeMac.mm42
-rw-r--r--Source/WebCore/rendering/RenderView.cpp58
-rw-r--r--Source/WebCore/rendering/RootInlineBox.cpp22
-rw-r--r--Source/WebCore/rendering/RootInlineBox.h2
-rw-r--r--Source/WebCore/rendering/mathml/RenderMathMLFenced.cpp53
-rw-r--r--Source/WebCore/rendering/mathml/RenderMathMLFenced.h2
-rw-r--r--Source/WebCore/rendering/mathml/RenderMathMLRoot.cpp127
-rw-r--r--Source/WebCore/rendering/mathml/RenderMathMLRoot.h5
-rw-r--r--Source/WebCore/rendering/mathml/RenderMathMLSquareRoot.cpp137
-rw-r--r--Source/WebCore/rendering/mathml/RenderMathMLSquareRoot.h10
-rw-r--r--Source/WebCore/rendering/style/RenderStyleConstants.h2
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGBlock.h4
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGInline.cpp17
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGInline.h2
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGInlineText.cpp18
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGInlineText.h1
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGResource.cpp18
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGText.cpp291
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGText.h20
-rw-r--r--Source/WebCore/rendering/svg/SVGRenderSupport.cpp4
-rw-r--r--Source/WebCore/rendering/svg/SVGTextLayoutAttributesBuilder.cpp52
-rw-r--r--Source/WebCore/rendering/svg/SVGTextLayoutAttributesBuilder.h7
-rw-r--r--Source/WebCore/rendering/svg/SVGTextMetricsBuilder.cpp6
63 files changed, 1026 insertions, 904 deletions
diff --git a/Source/WebCore/rendering/EllipsisBox.cpp b/Source/WebCore/rendering/EllipsisBox.cpp
index 5969a3222..8254784f5 100644
--- a/Source/WebCore/rendering/EllipsisBox.cpp
+++ b/Source/WebCore/rendering/EllipsisBox.cpp
@@ -23,6 +23,7 @@
#include "Document.h"
#include "GraphicsContext.h"
#include "HitTestResult.h"
+#include "InlineTextBox.h"
#include "PaintInfo.h"
#include "RenderBlock.h"
#include "RootInlineBox.h"
@@ -96,10 +97,11 @@ void EllipsisBox::paintSelection(GraphicsContext* context, const LayoutPoint& pa
GraphicsContextStateSaver stateSaver(*context);
LayoutUnit top = root()->selectionTop();
LayoutUnit h = root()->selectionHeight();
- // FIXME: We'll need to apply the correct clip rounding here: https://bugs.webkit.org/show_bug.cgi?id=63656
- context->clip(IntRect(x() + paintOffset.x(), top + paintOffset.y(), m_logicalWidth, h));
+ LayoutRect clipRect(x() + paintOffset.x(), top + paintOffset.y(), m_logicalWidth, h);
+ alignSelectionRectToDevicePixels(clipRect);
+ context->clip(clipRect);
// FIXME: Why is this always LTR? Fix by passing correct text run flags below.
- context->drawHighlightForText(font, RenderBlock::constructTextRun(renderer(), font, m_str, style, TextRun::AllowTrailingExpansion), IntPoint(x() + paintOffset.x(), y() + paintOffset.y() + top), h, c, style->colorSpace());
+ context->drawHighlightForText(font, RenderBlock::constructTextRun(renderer(), font, m_str, style, TextRun::AllowTrailingExpansion), roundedIntPoint(LayoutPoint(x() + paintOffset.x(), y() + paintOffset.y() + top)), h, c, style->colorSpace());
}
bool EllipsisBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const LayoutPoint& pointInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom)
diff --git a/Source/WebCore/rendering/HitTestResult.cpp b/Source/WebCore/rendering/HitTestResult.cpp
index c19f1222f..66e1da96b 100644
--- a/Source/WebCore/rendering/HitTestResult.cpp
+++ b/Source/WebCore/rendering/HitTestResult.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2006, 2008, 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -47,53 +48,109 @@ namespace WebCore {
using namespace HTMLNames;
-HitTestResult::HitTestResult()
- : m_isOverWidget(false)
- , m_isRectBased(false)
- , m_topPadding(0)
+HitTestPoint::HitTestPoint()
+ : m_topPadding(0)
, m_rightPadding(0)
, m_bottomPadding(0)
, m_leftPadding(0)
- , m_shadowContentFilterPolicy(DoNotAllowShadowContent)
- , m_region(0)
+ , m_isRectBased(false)
{
}
-HitTestResult::HitTestResult(const LayoutPoint& point)
+HitTestPoint::HitTestPoint(const LayoutPoint& point)
: m_point(point)
- , m_isOverWidget(false)
- , m_isRectBased(false)
, m_topPadding(0)
, m_rightPadding(0)
, m_bottomPadding(0)
, m_leftPadding(0)
- , m_shadowContentFilterPolicy(DoNotAllowShadowContent)
- , m_region(0)
+ , m_isRectBased(false)
{
}
-HitTestResult::HitTestResult(const LayoutPoint& centerPoint, unsigned topPadding, unsigned rightPadding, unsigned bottomPadding, unsigned leftPadding, ShadowContentFilterPolicy allowShadowContent)
+HitTestPoint::HitTestPoint(const LayoutPoint& centerPoint, unsigned topPadding, unsigned rightPadding, unsigned bottomPadding, unsigned leftPadding)
: m_point(centerPoint)
- , m_isOverWidget(false)
, m_topPadding(topPadding)
, m_rightPadding(rightPadding)
, m_bottomPadding(bottomPadding)
, m_leftPadding(leftPadding)
- , m_shadowContentFilterPolicy(allowShadowContent)
- , m_region(0)
{
// If all padding values passed in are zero then it is not a rect based hit test.
m_isRectBased = topPadding || rightPadding || bottomPadding || leftPadding;
+}
+
+HitTestPoint::HitTestPoint(const HitTestPoint& other)
+ : m_point(other.m_point)
+ , m_topPadding(other.m_topPadding)
+ , m_rightPadding(other.m_rightPadding)
+ , m_bottomPadding(other.m_bottomPadding)
+ , m_leftPadding(other.m_leftPadding)
+ , m_isRectBased(other.m_isRectBased)
+{
+}
+
+HitTestPoint::~HitTestPoint()
+{
+}
+
+HitTestPoint& HitTestPoint::operator=(const HitTestPoint& other)
+{
+ m_point = other.m_point;
+ m_topPadding = other.m_topPadding;
+ m_rightPadding = other.m_rightPadding;
+ m_bottomPadding = other.m_bottomPadding;
+ m_leftPadding = other.m_leftPadding;
+ m_isRectBased = other.m_isRectBased;
+
+ return *this;
+}
+
+IntRect HitTestPoint::rectForPoint(const LayoutPoint& point, unsigned topPadding, unsigned rightPadding, unsigned bottomPadding, unsigned leftPadding)
+{
+ IntPoint actualPoint(roundedIntPoint(point));
+ actualPoint -= IntSize(leftPadding, topPadding);
+
+ IntSize actualPadding(leftPadding + rightPadding, topPadding + bottomPadding);
+ // As IntRect is left inclusive and right exclusive (seeing IntRect::contains(x, y)), adding "1".
+ // FIXME: Remove this once non-rect based hit-detection stops using IntRect:intersects.
+ actualPadding += IntSize(1, 1);
+
+ return IntRect(actualPoint, actualPadding);
+}
- // Make sure all padding values are clamped to zero if it is not a rect hit test.
- if (!m_isRectBased)
- m_topPadding = m_rightPadding = m_bottomPadding = m_leftPadding = 0;
+HitTestResult::HitTestResult() : HitTestPoint()
+ , m_isOverWidget(false)
+ , m_shadowContentFilterPolicy(DoNotAllowShadowContent)
+ , m_region(0)
+{
+}
+
+HitTestResult::HitTestResult(const LayoutPoint& point) : HitTestPoint(point)
+ , m_isOverWidget(false)
+ , m_shadowContentFilterPolicy(DoNotAllowShadowContent)
+ , m_region(0)
+{
+}
+
+HitTestResult::HitTestResult(const LayoutPoint& centerPoint, unsigned topPadding, unsigned rightPadding, unsigned bottomPadding, unsigned leftPadding, ShadowContentFilterPolicy allowShadowContent)
+ : HitTestPoint(centerPoint, topPadding, rightPadding, bottomPadding, leftPadding)
+ , m_isOverWidget(false)
+ , m_shadowContentFilterPolicy(allowShadowContent)
+ , m_region(0)
+{
+}
+
+HitTestResult::HitTestResult(const HitTestPoint& other, ShadowContentFilterPolicy allowShadowContent)
+ : HitTestPoint(other)
+ , m_isOverWidget(false)
+ , m_shadowContentFilterPolicy(allowShadowContent)
+ , m_region(0)
+{
}
HitTestResult::HitTestResult(const HitTestResult& other)
- : m_innerNode(other.innerNode())
+ : HitTestPoint(other)
+ , m_innerNode(other.innerNode())
, m_innerNonSharedNode(other.innerNonSharedNode())
- , m_point(other.point())
, m_localPoint(other.localPoint())
, m_innerURLElement(other.URLElement())
, m_scrollbar(other.scrollbar())
@@ -101,16 +158,7 @@ HitTestResult::HitTestResult(const HitTestResult& other)
, m_shadowContentFilterPolicy(other.shadowContentFilterPolicy())
, m_region(other.region())
{
- // Only copy the padding and NodeSet in case of rect hit test.
- // Copying the later is rather expensive.
- if ((m_isRectBased = other.isRectBasedTest())) {
- m_topPadding = other.m_topPadding;
- m_rightPadding = other.m_rightPadding;
- m_bottomPadding = other.m_bottomPadding;
- m_leftPadding = other.m_leftPadding;
- } else
- m_topPadding = m_rightPadding = m_bottomPadding = m_leftPadding = 0;
-
+ // Only copy the NodeSet in case of rect hit test.
m_rectBasedTestResult = adoptPtr(other.m_rectBasedTestResult ? new NodeSet(*other.m_rectBasedTestResult) : 0);
}
@@ -120,25 +168,17 @@ HitTestResult::~HitTestResult()
HitTestResult& HitTestResult::operator=(const HitTestResult& other)
{
+ HitTestPoint::operator=(other);
m_innerNode = other.innerNode();
m_innerNonSharedNode = other.innerNonSharedNode();
- m_point = other.point();
m_localPoint = other.localPoint();
m_innerURLElement = other.URLElement();
m_scrollbar = other.scrollbar();
m_isOverWidget = other.isOverWidget();
- // Only copy the padding and NodeSet in case of rect hit test.
- // Copying the later is rather expensive.
- if ((m_isRectBased = other.isRectBasedTest())) {
- m_topPadding = other.m_topPadding;
- m_rightPadding = other.m_rightPadding;
- m_bottomPadding = other.m_bottomPadding;
- m_leftPadding = other.m_leftPadding;
- } else
- m_topPadding = m_rightPadding = m_bottomPadding = m_leftPadding = 0;
+ // Only copy the NodeSet in case of rect hit test.
m_rectBasedTestResult = adoptPtr(other.m_rectBasedTestResult ? new NodeSet(*other.m_rectBasedTestResult) : 0);
- m_shadowContentFilterPolicy = other.shadowContentFilterPolicy();
+ m_shadowContentFilterPolicy = other.shadowContentFilterPolicy();
m_region = other.m_region;
@@ -198,7 +238,7 @@ bool HitTestResult::isSelected() const
if (!frame)
return false;
- return frame->selection()->contains(m_point);
+ return frame->selection()->contains(point());
}
String HitTestResult::spellingToolTip(TextDirection& dir) const
@@ -209,7 +249,7 @@ String HitTestResult::spellingToolTip(TextDirection& dir) const
if (!m_innerNonSharedNode)
return String();
- DocumentMarker* marker = m_innerNonSharedNode->document()->markers()->markerContainingPoint(m_point, DocumentMarker::Grammar);
+ DocumentMarker* marker = m_innerNonSharedNode->document()->markers()->markerContainingPoint(point(), DocumentMarker::Grammar);
if (!marker)
return String();
@@ -225,7 +265,7 @@ String HitTestResult::replacedString() const
if (!m_innerNonSharedNode)
return String();
- DocumentMarker* marker = m_innerNonSharedNode->document()->markers()->markerContainingPoint(m_point, DocumentMarker::Replacement);
+ DocumentMarker* marker = m_innerNonSharedNode->document()->markers()->markerContainingPoint(point(), DocumentMarker::Replacement);
if (!marker)
return String();
@@ -652,18 +692,6 @@ void HitTestResult::append(const HitTestResult& other)
}
}
-IntRect HitTestResult::rectForPoint(const LayoutPoint& point, unsigned topPadding, unsigned rightPadding, unsigned bottomPadding, unsigned leftPadding)
-{
- IntPoint actualPoint(roundedIntPoint(point));
- actualPoint -= IntSize(leftPadding, topPadding);
-
- IntSize actualPadding(leftPadding + rightPadding, topPadding + bottomPadding);
- // As IntRect is left inclusive and right exclusive (seeing IntRect::contains(x, y)), adding "1".
- actualPadding += IntSize(1, 1);
-
- return IntRect(actualPoint, actualPadding);
-}
-
const HitTestResult::NodeSet& HitTestResult::rectBasedTestResult() const
{
if (!m_rectBasedTestResult)
diff --git a/Source/WebCore/rendering/HitTestResult.h b/Source/WebCore/rendering/HitTestResult.h
index e919472b2..a18fdb5a2 100644
--- a/Source/WebCore/rendering/HitTestResult.h
+++ b/Source/WebCore/rendering/HitTestResult.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -22,6 +23,7 @@
#define HitTestResult_h
#include "FloatRect.h"
+#include "HitTestRequest.h"
#include "LayoutTypes.h"
#include "TextDirection.h"
#include <wtf/Forward.h>
@@ -44,7 +46,42 @@ class Scrollbar;
enum ShadowContentFilterPolicy { DoNotAllowShadowContent, AllowShadowContent };
-class HitTestResult {
+class HitTestPoint {
+public:
+
+ HitTestPoint();
+ HitTestPoint(const LayoutPoint&);
+ // Pass non-negative padding values to perform a rect-based hit test.
+ HitTestPoint(const LayoutPoint& centerPoint, unsigned topPadding, unsigned rightPadding, unsigned bottomPadding, unsigned leftPadding);
+ HitTestPoint(const HitTestPoint&);
+ ~HitTestPoint();
+ HitTestPoint& operator=(const HitTestPoint&);
+
+ LayoutPoint point() const { return m_point; }
+ IntPoint roundedPoint() const { return roundedIntPoint(m_point); }
+
+ void setPoint(const LayoutPoint& p) { m_point = p; }
+
+ // Rect-based hit test related methods.
+ bool isRectBasedTest() const { return m_isRectBased; }
+ IntRect rectForPoint(const LayoutPoint&) const;
+ static IntRect rectForPoint(const LayoutPoint&, unsigned topPadding, unsigned rightPadding, unsigned bottomPadding, unsigned leftPadding);
+ int topPadding() const { return m_topPadding; }
+ int rightPadding() const { return m_rightPadding; }
+ int bottomPadding() const { return m_bottomPadding; }
+ int leftPadding() const { return m_leftPadding; }
+
+private:
+ LayoutPoint m_point;
+
+ int m_topPadding;
+ int m_rightPadding;
+ int m_bottomPadding;
+ int m_leftPadding;
+ bool m_isRectBased;
+};
+
+class HitTestResult : public HitTestPoint {
public:
typedef ListHashSet<RefPtr<Node> > NodeSet;
@@ -52,14 +89,13 @@ public:
HitTestResult(const LayoutPoint&);
// Pass non-negative padding values to perform a rect-based hit test.
HitTestResult(const LayoutPoint& centerPoint, unsigned topPadding, unsigned rightPadding, unsigned bottomPadding, unsigned leftPadding, ShadowContentFilterPolicy);
+ HitTestResult(const HitTestPoint&, ShadowContentFilterPolicy);
HitTestResult(const HitTestResult&);
~HitTestResult();
HitTestResult& operator=(const HitTestResult&);
Node* innerNode() const { return m_innerNode.get(); }
Node* innerNonSharedNode() const { return m_innerNonSharedNode.get(); }
- LayoutPoint point() const { return m_point; }
- IntPoint roundedPoint() const { return roundedIntPoint(m_point); }
LayoutPoint localPoint() const { return m_localPoint; }
Element* URLElement() const { return m_innerURLElement.get(); }
Scrollbar* scrollbar() const { return m_scrollbar.get(); }
@@ -70,11 +106,11 @@ public:
void setToNonShadowAncestor();
+ const HitTestPoint& hitTestPoint() const { return *this; }
ShadowContentFilterPolicy shadowContentFilterPolicy() const { return m_shadowContentFilterPolicy; }
void setInnerNode(Node*);
void setInnerNonSharedNode(Node*);
- void setPoint(const LayoutPoint& p) { m_point = p; }
void setLocalPoint(const LayoutPoint& p) { m_localPoint = p; }
void setURLElement(Element*);
void setScrollbar(Scrollbar*);
@@ -110,15 +146,6 @@ public:
bool mediaMuted() const;
void toggleMediaMuteState() const;
- // Rect-based hit test related methods.
- bool isRectBasedTest() const { return m_isRectBased; }
- IntRect rectForPoint(const LayoutPoint&) const;
- static IntRect rectForPoint(const LayoutPoint&, unsigned topPadding, unsigned rightPadding, unsigned bottomPadding, unsigned leftPadding);
- int topPadding() const { return m_topPadding; }
- int rightPadding() const { return m_rightPadding; }
- int bottomPadding() const { return m_bottomPadding; }
- int leftPadding() const { return m_leftPadding; }
-
// Returns true if it is rect-based hit test and needs to continue until the rect is fully
// enclosed by the boundaries of a node.
bool addNodeToRectBasedTestResult(Node*, const LayoutPoint& pointInContainer, const IntRect& = IntRect());
@@ -139,19 +166,14 @@ private:
RefPtr<Node> m_innerNode;
RefPtr<Node> m_innerNonSharedNode;
- LayoutPoint m_point;
LayoutPoint m_localPoint; // A point in the local coordinate space of m_innerNonSharedNode's renderer. Allows us to efficiently
// determine where inside the renderer we hit on subsequent operations.
RefPtr<Element> m_innerURLElement;
RefPtr<Scrollbar> m_scrollbar;
bool m_isOverWidget; // Returns true if we are over a widget (and not in the border/padding area of a RenderWidget for example).
- bool m_isRectBased;
- int m_topPadding;
- int m_rightPadding;
- int m_bottomPadding;
- int m_leftPadding;
+
ShadowContentFilterPolicy m_shadowContentFilterPolicy;
-
+
RenderRegion* m_region; // The region we're inside.
mutable OwnPtr<NodeSet> m_rectBasedTestResult;
@@ -162,7 +184,7 @@ private:
// y = p.y() - topPadding
// width = leftPadding + rightPadding + 1
// height = topPadding + bottomPadding + 1
-inline IntRect HitTestResult::rectForPoint(const LayoutPoint& point) const
+inline IntRect HitTestPoint::rectForPoint(const LayoutPoint& point) const
{
return rectForPoint(point, m_topPadding, m_rightPadding, m_bottomPadding, m_leftPadding);
}
diff --git a/Source/WebCore/rendering/InlineFlowBox.cpp b/Source/WebCore/rendering/InlineFlowBox.cpp
index cbd685d69..58c97dd69 100644
--- a/Source/WebCore/rendering/InlineFlowBox.cpp
+++ b/Source/WebCore/rendering/InlineFlowBox.cpp
@@ -517,8 +517,8 @@ void InlineFlowBox::computeLogicalBoxHeights(RootInlineBox* rootBox, LayoutUnit&
if (isRootInlineBox()) {
// Examine our root box.
- LayoutUnit ascent = 0;
- LayoutUnit descent = 0;
+ int ascent = 0;
+ int descent = 0;
rootBox->ascentAndDescentForBox(rootBox, textBoxDataMap, ascent, descent, affectsAscent, affectsDescent);
if (strictMode || hasTextChildren() || (!checkChildren && hasTextDescendants())) {
if (maxAscent < ascent || !setMaxAscent) {
@@ -549,8 +549,8 @@ void InlineFlowBox::computeLogicalBoxHeights(RootInlineBox* rootBox, LayoutUnit&
// root box's baseline, and it is positive if the child box's baseline is below the root box's baseline.
curr->setLogicalTop(rootBox->verticalPositionForBox(curr, verticalPositionCache));
- LayoutUnit ascent = 0;
- LayoutUnit descent = 0;
+ int ascent = 0;
+ int descent = 0;
rootBox->ascentAndDescentForBox(curr, textBoxDataMap, ascent, descent, affectsAscent, affectsDescent);
LayoutUnit boxHeight = ascent + descent;
diff --git a/Source/WebCore/rendering/InlineTextBox.cpp b/Source/WebCore/rendering/InlineTextBox.cpp
index 9550edb59..aafecbf6e 100644
--- a/Source/WebCore/rendering/InlineTextBox.cpp
+++ b/Source/WebCore/rendering/InlineTextBox.cpp
@@ -807,6 +807,22 @@ void InlineTextBox::selectionStartEnd(int& sPos, int& ePos)
ePos = min(endPos - m_start, (int)m_len);
}
+void alignSelectionRectToDevicePixels(LayoutRect& rect)
+{
+ LayoutUnit maxX = floorToInt(rect.maxX());
+ rect.setX(floorToInt(rect.x()));
+ rect.setWidth(maxX - rect.x());
+}
+
+#if !ENABLE(SUBPIXEL_LAYOUT)
+void alignSelectionRectToDevicePixels(FloatRect& rect)
+{
+ float maxX = floorf(rect.maxX());
+ rect.setX(floorf(rect.x()));
+ rect.setWidth(roundf(maxX - rect.x()));
+}
+#endif
+
void InlineTextBox::paintSelection(GraphicsContext* context, const FloatPoint& boxOrigin, RenderStyle* style, const Font& font, Color textColor)
{
if (context->paintingDisabled())
@@ -844,15 +860,18 @@ void InlineTextBox::paintSelection(GraphicsContext* context, const FloatPoint& b
LayoutUnit selectionBottom = root()->selectionBottom();
LayoutUnit selectionTop = root()->selectionTopAdjustedForPrecedingBlock();
- int deltaY = renderer()->style()->isFlippedLinesWritingMode() ? selectionBottom - logicalBottom() : logicalTop() - selectionTop;
- int selHeight = max<LayoutUnit>(0, selectionBottom - selectionTop);
+ LayoutUnit deltaY = renderer()->style()->isFlippedLinesWritingMode() ? selectionBottom - logicalBottom() : logicalTop() - selectionTop;
+ LayoutUnit selHeight = max<LayoutUnit>(0, selectionBottom - selectionTop);
+#if ENABLE(SUBPIXEL_LAYOUT)
+ LayoutPoint localOrigin(boxOrigin.x(), boxOrigin.y() - deltaY);
+ LayoutRect clipRect(localOrigin, LayoutSize(m_logicalWidth, selHeight));
+ alignSelectionRectToDevicePixels(clipRect);
+#else
FloatPoint localOrigin(boxOrigin.x(), boxOrigin.y() - deltaY);
-
FloatRect clipRect(localOrigin, FloatSize(m_logicalWidth, selHeight));
- float maxX = floorf(clipRect.maxX());
- clipRect.setX(floorf(clipRect.x()));
- clipRect.setWidth(maxX - clipRect.x());
+ alignSelectionRectToDevicePixels(clipRect);
+#endif
context->clip(clipRect);
context->drawHighlightForText(font, textRun, localOrigin, selHeight, c, style->colorSpace(), sPos, ePos);
diff --git a/Source/WebCore/rendering/InlineTextBox.h b/Source/WebCore/rendering/InlineTextBox.h
index 1b7a3ad03..a3c08987c 100644
--- a/Source/WebCore/rendering/InlineTextBox.h
+++ b/Source/WebCore/rendering/InlineTextBox.h
@@ -213,6 +213,11 @@ inline RenderText* InlineTextBox::textRenderer() const
return toRenderText(renderer());
}
+void alignSelectionRectToDevicePixels(LayoutRect&);
+#if !ENABLE(SUBPIXEL_LAYOUT)
+void alignSelectionRectToDevicePixels(FloatRect&);
+#endif
+
} // namespace WebCore
#endif // InlineTextBox_h
diff --git a/Source/WebCore/rendering/LayoutState.cpp b/Source/WebCore/rendering/LayoutState.cpp
index 1fbfc0cdd..5f780dca0 100644
--- a/Source/WebCore/rendering/LayoutState.cpp
+++ b/Source/WebCore/rendering/LayoutState.cpp
@@ -196,16 +196,18 @@ void LayoutState::clearPaginationInformation()
m_columnInfo = m_next->m_columnInfo;
}
-LayoutUnit LayoutState::pageLogicalOffset(LayoutUnit childLogicalOffset) const
+LayoutUnit LayoutState::pageLogicalOffset(RenderBox* child, LayoutUnit childLogicalOffset) const
{
- return m_layoutOffset.height() + childLogicalOffset - m_pageOffset.height();
+ if (child->isHorizontalWritingMode())
+ return m_layoutOffset.height() + childLogicalOffset - m_pageOffset.height();
+ return m_layoutOffset.width() + childLogicalOffset - m_pageOffset.width();
}
-void LayoutState::addForcedColumnBreak(LayoutUnit childLogicalOffset)
+void LayoutState::addForcedColumnBreak(RenderBox* child, LayoutUnit childLogicalOffset)
{
if (!m_columnInfo || m_columnInfo->columnHeight())
return;
- m_columnInfo->addForcedBreak(pageLogicalOffset(childLogicalOffset));
+ m_columnInfo->addForcedBreak(pageLogicalOffset(child, childLogicalOffset));
}
void LayoutState::propagateLineGridInfo(RenderBox* renderer)
diff --git a/Source/WebCore/rendering/LayoutState.h b/Source/WebCore/rendering/LayoutState.h
index e1df24b4e..81d61e9cd 100644
--- a/Source/WebCore/rendering/LayoutState.h
+++ b/Source/WebCore/rendering/LayoutState.h
@@ -74,9 +74,9 @@ public:
// The page logical offset is the object's offset from the top of the page in the page progression
// direction (so an x-offset in vertical text and a y-offset for horizontal text).
- LayoutUnit pageLogicalOffset(LayoutUnit childLogicalOffset) const;
+ LayoutUnit pageLogicalOffset(RenderBox*, LayoutUnit childLogicalOffset) const;
- void addForcedColumnBreak(LayoutUnit childLogicalOffset);
+ void addForcedColumnBreak(RenderBox*, LayoutUnit childLogicalOffset);
LayoutUnit pageLogicalHeight() const { return m_pageLogicalHeight; }
bool pageLogicalHeightChanged() const { return m_pageLogicalHeightChanged; }
diff --git a/Source/WebCore/rendering/RenderBlock.cpp b/Source/WebCore/rendering/RenderBlock.cpp
index 4c2899e0f..c3017a425 100755
--- a/Source/WebCore/rendering/RenderBlock.cpp
+++ b/Source/WebCore/rendering/RenderBlock.cpp
@@ -932,6 +932,14 @@ void RenderBlock::addChildIgnoringAnonymousColumnBlocks(RenderObject* newChild,
}
RenderBox::addChild(newChild, beforeChild);
+
+ // Handle positioning of run-ins.
+ if (newChild->isRunIn())
+ moveRunInUnderSiblingBlockIfNeeded(newChild);
+ else if (RenderObject* prevSibling = newChild->previousSibling()) {
+ if (prevSibling->isRunIn())
+ moveRunInUnderSiblingBlockIfNeeded(prevSibling);
+ }
if (madeBoxesNonInline && parent() && isAnonymousBlock() && parent()->isRenderBlock())
toRenderBlock(parent())->removeLeftoverAnonymousBlock(this);
@@ -1038,6 +1046,13 @@ void RenderBlock::makeChildrenNonInline(RenderObject *insertionPoint)
if (!child)
return;
+ // Since we are going to have block children, we have to move
+ // back the run-in to its original place.
+ if (child->isRunIn()) {
+ moveRunInToOriginalPosition(child);
+ child = firstChild();
+ }
+
deleteLineBoxTree();
while (child) {
@@ -1503,7 +1518,7 @@ void RenderBlock::layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeigh
statePusher.pop();
if (renderView->layoutState()->m_pageLogicalHeight)
- setPageLogicalOffset(renderView->layoutState()->pageLogicalOffset(logicalTop()));
+ setPageLogicalOffset(renderView->layoutState()->pageLogicalOffset(this, logicalTop()));
updateLayerTransform();
@@ -1724,8 +1739,7 @@ bool RenderBlock::handleSpecialChild(RenderBox* child, const MarginInfo& marginI
{
// Handle in the given order
return handlePositionedChild(child, marginInfo)
- || handleFloatingChild(child, marginInfo)
- || handleRunInChild(child);
+ || handleFloatingChild(child, marginInfo);
}
@@ -1749,77 +1763,115 @@ bool RenderBlock::handleFloatingChild(RenderBox* child, const MarginInfo& margin
return false;
}
-bool RenderBlock::handleRunInChild(RenderBox* child)
+static void destroyRunIn(RenderBoxModelObject* runIn)
{
- // See if we have a run-in element with inline children. If the
- // children aren't inline, then just treat the run-in as a normal
- // block.
- if (!child->isRunIn() || !child->childrenInline())
- return false;
+ ASSERT(runIn->isRunIn());
+ ASSERT(!runIn->firstChild());
+
+ // If it is a block run-in, delete its line box tree as well. This is needed as our
+ // children got moved and our line box tree is no longer valid.
+ if (runIn->isRenderBlock())
+ toRenderBlock(runIn)->deleteLineBoxTree();
+ runIn->destroy();
+}
+
+RenderBoxModelObject* RenderBlock::createReplacementRunIn(RenderBoxModelObject* runIn)
+{
+ ASSERT(runIn->isRunIn());
+
+ // First we destroy any :before/:after content. It will be regenerated by the new run-in.
+ // Exception is if the run-in itself is generated.
+ if (runIn->style()->styleType() != BEFORE && runIn->style()->styleType() != AFTER) {
+ RenderObject* generatedContent;
+ if (runIn->getCachedPseudoStyle(BEFORE) && (generatedContent = runIn->beforePseudoElementRenderer()))
+ generatedContent->destroy();
+ if (runIn->getCachedPseudoStyle(AFTER) && (generatedContent = runIn->afterPseudoElementRenderer()))
+ generatedContent->destroy();
+ }
+
+ bool newRunInShouldBeBlock = !runIn->isRenderBlock();
+ Node* runInNode = runIn->node();
+ RenderBoxModelObject* newRunIn = 0;
+ if (newRunInShouldBeBlock)
+ newRunIn = new (renderArena()) RenderBlock(runInNode ? runInNode : document());
+ else
+ newRunIn = new (renderArena()) RenderInline(runInNode ? runInNode : document());
+ newRunIn->setStyle(runIn->style());
+
+ runIn->moveAllChildrenTo(newRunIn, true);
+
+ // If the run-in had an element, we need to set the new renderer.
+ if (runInNode)
+ runInNode->setRenderer(newRunIn);
+
+ return newRunIn;
+}
+
+void RenderBlock::moveRunInUnderSiblingBlockIfNeeded(RenderObject* runIn)
+{
+ ASSERT(runIn->isRunIn());
+
+ // See if we have inline children. If the children aren't inline,
+ // then just treat the run-in as a normal block.
+ if (!runIn->childrenInline())
+ return;
// FIXME: We don't handle non-block elements with run-in for now.
- if (!child->isRenderBlock())
- return false;
+ if (!runIn->isRenderBlock())
+ return;
- // Run-in child shouldn't intrude into the sibling block if it is part of a
+ // We shouldn't run in into the sibling block if we are part of a
// continuation chain. In that case, treat it as a normal block.
- if (child->isElementContinuation() || child->virtualContinuation())
- return false;
+ if (runIn->isElementContinuation() || runIn->virtualContinuation())
+ return;
// 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 = child->node();
+ Node* runInNode = runIn->node();
if (runInNode && runInNode->hasTagName(selectTag))
- return false;
+ return;
- RenderBlock* blockRunIn = toRenderBlock(child);
- RenderObject* curr = blockRunIn->nextSibling();
- if (!curr || !curr->isRenderBlock() || !curr->childrenInline() || curr->isRunIn() || curr->isAnonymous() || curr->isFloatingOrPositioned())
- return false;
+ RenderObject* curr = runIn->nextSibling();
+ if (!curr || !curr->isRenderBlock() || !curr->childrenInline())
+ return;
- RenderBlock* currBlock = toRenderBlock(curr);
+ // Per CSS3, "A run-in cannot run in to a block that already starts with a
+ // run-in or that itself is a run-in".
+ if (curr->isRunIn() || (curr->firstChild() && curr->firstChild()->isRunIn()))
+ return;
- // First we destroy any :before/:after content. It will be regenerated by the new inline.
- // Exception is if the run-in itself is generated.
- if (child->style()->styleType() != BEFORE && child->style()->styleType() != AFTER) {
- RenderObject* generatedContent;
- if (child->getCachedPseudoStyle(BEFORE) && (generatedContent = child->beforePseudoElementRenderer()))
- generatedContent->destroy();
- if (child->getCachedPseudoStyle(AFTER) && (generatedContent = child->afterPseudoElementRenderer()))
- generatedContent->destroy();
- }
+ if (curr->isAnonymous() || curr->isFloatingOrPositioned())
+ return;
- // Remove the old child.
- children()->removeChildNode(this, blockRunIn);
+ RenderBoxModelObject* oldRunIn = toRenderBoxModelObject(runIn);
+ RenderBoxModelObject* newRunIn = createReplacementRunIn(oldRunIn);
+ destroyRunIn(oldRunIn);
- // Create an inline.
- RenderInline* inlineRunIn = new (renderArena()) RenderInline(runInNode ? runInNode : document());
- inlineRunIn->setStyle(blockRunIn->style());
+ // Now insert the new child under |curr| block. Use addChild instead of insertChildNode
+ // since it handles correct placement of the children, especially where we cannot insert
+ // anything before the first child. e.g. details tag. See https://bugs.webkit.org/show_bug.cgi?id=58228.
+ curr->addChild(newRunIn, curr->firstChild());
+}
- // Move the nodes from the old child to the new child
- for (RenderObject* runInChild = blockRunIn->firstChild(); runInChild;) {
- RenderObject* nextSibling = runInChild->nextSibling();
- blockRunIn->children()->removeChildNode(blockRunIn, runInChild);
- inlineRunIn->addChild(runInChild); // Use addChild instead of appendChildNode since it handles correct placement of the children relative to :after-generated content.
- runInChild = nextSibling;
- }
+void RenderBlock::moveRunInToOriginalPosition(RenderObject* runIn)
+{
+ ASSERT(runIn->isRunIn());
- // Now insert the new child under |currBlock|. Use addChild instead of insertChildNode since it handles correct placement of the children, esp where we cannot insert
- // anything before the first child. e.g. details tag. See https://bugs.webkit.org/show_bug.cgi?id=58228.
- currBlock->addChild(inlineRunIn, currBlock->firstChild());
-
- // If the run-in had an element, we need to set the new renderer.
- if (runInNode)
- runInNode->setRenderer(inlineRunIn);
+ // If we don't have a parent, there is nothing to move. This might
+ // happen if |this| got detached from parent after |runIn| run into |this|.
+ if (!parent())
+ return;
+
+ // An intruded run-in needs to be an inline.
+ if (!runIn->isRenderInline())
+ return;
- // Destroy the block run-in, which includes deleting its line box tree.
- blockRunIn->deleteLineBoxTree();
- blockRunIn->destroy();
+ RenderBoxModelObject* oldRunIn = toRenderBoxModelObject(runIn);
+ RenderBoxModelObject* newRunIn = createReplacementRunIn(oldRunIn);
+ destroyRunIn(oldRunIn);
- // The block acts like an inline, so just null out its
- // position.
-
- return true;
+ // Add the run-in block as our previous sibling.
+ parent()->addChild(newRunIn, this);
}
LayoutUnit RenderBlock::collapseMargins(RenderBox* child, MarginInfo& marginInfo)
@@ -2478,7 +2530,7 @@ void RenderBlock::markForPaginationRelayoutIfNeeded()
if (needsLayout())
return;
- if (view()->layoutState()->pageLogicalHeightChanged() || (view()->layoutState()->pageLogicalHeight() && view()->layoutState()->pageLogicalOffset(logicalTop()) != pageLogicalOffset()))
+ if (view()->layoutState()->pageLogicalHeightChanged() || (view()->layoutState()->pageLogicalHeight() && view()->layoutState()->pageLogicalOffset(this, logicalTop()) != pageLogicalOffset()))
setChildNeedsLayout(true, MarkOnlyThis);
}
@@ -2621,6 +2673,7 @@ void RenderBlock::paintColumnContents(PaintInfo& paintInfo, const LayoutPoint& p
if (!colCount)
return;
LayoutUnit currLogicalTopOffset = 0;
+ LayoutUnit colGap = columnGap();
for (unsigned i = 0; i < colCount; i++) {
// For each rect, we clip to the rect, and then we adjust our coords.
LayoutRect colRect = columnRectAt(colInfo, i);
@@ -2639,10 +2692,19 @@ void RenderBlock::paintColumnContents(PaintInfo& paintInfo, const LayoutPoint& p
if (!info.rect.isEmpty()) {
GraphicsContextStateSaver stateSaver(*context);
+ LayoutRect clipRect(colRect);
+ if (i < colCount - 1) {
+ if (isHorizontalWritingMode())
+ clipRect.expand(colGap / 2, 0);
+ else
+ clipRect.expand(0, colGap / 2);
+ }
// Each strip pushes a clip, since column boxes are specified as being
// like overflow:hidden.
- context->clip(colRect);
+ // FIXME: Content and column rules that extend outside column boxes at the edges of the multi-column element
+ // are clipped according to the 'overflow' property.
+ context->clip(clipRect);
// Adjust our x and y when painting.
LayoutPoint adjustedPaintOffset = paintOffset + offset;
@@ -3295,6 +3357,7 @@ LayoutRect RenderBlock::logicalLeftSelectionGap(RenderBlock* rootBlock, const La
return LayoutRect();
LayoutRect gapRect = rootBlock->logicalRectToPhysicalRect(rootBlockPhysicalPosition, LayoutRect(rootBlockLogicalLeft, rootBlockLogicalTop, rootBlockLogicalWidth, logicalHeight));
+ alignSelectionRectToDevicePixels(gapRect);
if (paintInfo)
paintInfo->context->fillRect(gapRect, selObj->selectionBackgroundColor(), selObj->style()->colorSpace());
return gapRect;
@@ -3311,6 +3374,7 @@ LayoutRect RenderBlock::logicalRightSelectionGap(RenderBlock* rootBlock, const L
return LayoutRect();
LayoutRect gapRect = rootBlock->logicalRectToPhysicalRect(rootBlockPhysicalPosition, LayoutRect(rootBlockLogicalLeft, rootBlockLogicalTop, rootBlockLogicalWidth, logicalHeight));
+ alignSelectionRectToDevicePixels(gapRect);
if (paintInfo)
paintInfo->context->fillRect(gapRect, selObj->selectionBackgroundColor(), selObj->style()->colorSpace());
return gapRect;
@@ -4168,9 +4232,8 @@ LayoutUnit RenderBlock::addOverhangingFloats(RenderBlock* child, bool makeChildP
if (logicalBottom > logicalHeight()) {
// If the object is not in the list, we add it now.
if (!containsFloat(r->m_renderer)) {
- LayoutUnit leftOffset = isHorizontalWritingMode() ? -childLogicalLeft : -childLogicalTop;
- LayoutUnit topOffset = isHorizontalWritingMode() ? -childLogicalTop : -childLogicalLeft;
- FloatingObject* floatingObj = new FloatingObject(r->type(), LayoutRect(r->x() - leftOffset, r->y() - topOffset, r->width(), r->height()));
+ LayoutSize offset = isHorizontalWritingMode() ? LayoutSize(-childLogicalLeft, -childLogicalTop) : LayoutSize(-childLogicalTop, -childLogicalLeft);
+ FloatingObject* floatingObj = new FloatingObject(r->type(), LayoutRect(r->frameRect().location() - offset, r->frameRect().size()));
floatingObj->m_renderer = r->m_renderer;
// The nearest enclosing layer always paints the float (so that zindex and stacking
@@ -4237,10 +4300,8 @@ void RenderBlock::addIntrudingFloats(RenderBlock* prev, LayoutUnit logicalLeftOf
FloatingObject* r = *prevIt;
if (logicalBottomForFloat(r) > logicalTopOffset) {
if (!m_floatingObjects || !m_floatingObjects->set().contains(r)) {
- LayoutUnit leftOffset = isHorizontalWritingMode() ? logicalLeftOffset : logicalTopOffset;
- LayoutUnit topOffset = isHorizontalWritingMode() ? logicalTopOffset : logicalLeftOffset;
-
- FloatingObject* floatingObj = new FloatingObject(r->type(), LayoutRect(r->x() - leftOffset, r->y() - topOffset, r->width(), r->height()));
+ LayoutSize offset = isHorizontalWritingMode() ? LayoutSize(logicalLeftOffset, logicalTopOffset) : LayoutSize(logicalTopOffset, logicalLeftOffset);
+ FloatingObject* floatingObj = new FloatingObject(r->type(), LayoutRect(r->frameRect().location() - offset, r->frameRect().size()));
// Applying the child's margin makes no sense in the case where the child was passed in.
// since this margin was added already through the modification of the |logicalLeftOffset| variable
@@ -4931,7 +4992,7 @@ bool RenderBlock::layoutColumns(bool hasSpecifiedPageLogicalHeight, LayoutUnit p
// maximum page break distance.
if (!pageLogicalHeight) {
LayoutUnit distanceBetweenBreaks = max<LayoutUnit>(colInfo->maximumDistanceBetweenForcedBreaks(),
- view()->layoutState()->pageLogicalOffset(borderBefore() + paddingBefore() + contentLogicalHeight()) - colInfo->forcedBreakOffset());
+ view()->layoutState()->pageLogicalOffset(this, borderBefore() + paddingBefore() + contentLogicalHeight()) - colInfo->forcedBreakOffset());
columnHeight = max(colInfo->minimumColumnHeight(), distanceBetweenBreaks);
}
} else if (contentLogicalHeight() > boundedMultiply(pageLogicalHeight, desiredColumnCount)) {
@@ -5167,7 +5228,8 @@ void RenderBlock::computePreferredLogicalWidths()
updateFirstLetter();
RenderStyle* styleToUse = style();
- if (!isTableCell() && styleToUse->logicalWidth().isFixed() && styleToUse->logicalWidth().value() >= 0 && style()->marqueeBehavior() != MALTERNATE)
+ if (!isTableCell() && styleToUse->logicalWidth().isFixed() && styleToUse->logicalWidth().value() >= 0
+ && style()->marqueeBehavior() != MALTERNATE && !(isDeprecatedFlexItem() && !styleToUse->logicalWidth().intValue()))
m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = computeContentBoxLogicalWidth(styleToUse->logicalWidth().value());
else {
m_minPreferredLogicalWidth = 0;
@@ -5701,7 +5763,7 @@ bool RenderBlock::hasLineIfEmpty() const
if (!node())
return false;
- if (node()->rendererIsEditable() && node()->rootEditableElement() == node())
+ if (node()->isRootEditableElement())
return true;
if (node()->isShadowRoot() && (node()->shadowHost()->hasTagName(inputTag)))
@@ -5890,58 +5952,6 @@ static inline bool shouldSkipForFirstLetter(UChar c)
return isSpaceOrNewline(c) || c == noBreakSpace || isPunctuationForFirstLetter(c);
}
-RenderObject* RenderBlock::findLastObjectWithFirstLetterText(RenderObject* child, RenderObject* &firstLetterBlock)
-{
- while (child) {
- RenderObject* nextChild = child->nextSibling();
- // Style and skip over any objects such as quotes or punctuation
- child = findLastObjectAfterFirstLetterPunctuation(child, firstLetterBlock);
- if (child)
- break;
- child = nextChild;
- }
- return child;
-}
-
-RenderObject* RenderBlock::findLastObjectAfterFirstLetterPunctuation(RenderObject* child, RenderObject* &firstLetterBlock)
-{
- if (child->isText()) {
- // CSS 2.1 http://www.w3.org/TR/CSS21/selector.html#first-letter
- // "The first letter must occur on the first formatted line."
- if (child->isBR())
- return child;
-
- // If child is a single punctuation mark or a Render Quote then style it as first-letter now and keep looking for further text,
- bool textQuote = toRenderText(child)->textLength() == 1 && isPunctuationForFirstLetter(toRenderText(child)->characters()[0]);
- if (child->isQuote() || textQuote)
- addFirstLetter(child, firstLetterBlock);
- else if (!toRenderText(child)->isAllCollapsibleWhitespace())
- return child;
- return 0;
- }
-
- if (child->isListMarker())
- return 0;
-
- if (child->isFloatingOrPositioned()) {
- // Floats and positioned objects do not inherit their style from parents so if it is styled
- // inspect its children for text, otherwise move on to its sibling.
- if (child->style()->styleType() == FIRST_LETTER)
- return findLastObjectWithFirstLetterText(child->firstChild(), firstLetterBlock);
- return 0;
- }
-
- if (child->isReplaced() || child->isRenderButton() || child->isMenuList())
- return child;
-
- if (child->style()->hasPseudoStyle(FIRST_LETTER) && child->canHaveChildren()) {
- // We found a lower-level node with first-letter, which supersedes the higher-level style.
- firstLetterBlock = child;
- return findLastObjectWithFirstLetterText(child->firstChild(), firstLetterBlock);
- }
- return findLastObjectWithFirstLetterText(child->firstChild(), firstLetterBlock);
-}
-
static inline RenderObject* findFirstLetterBlock(RenderBlock* start)
{
RenderObject* firstLetterBlock = start;
@@ -6091,36 +6101,47 @@ void RenderBlock::updateFirstLetter()
if (!firstLetterBlock)
return;
- // Check each sibling and drill into its inlines until we find a text node that is not all whitespace
- // or is a line break.
- RenderObject* firstLetterObject = firstLetterBlock->firstChild();
-
- firstLetterObject = findLastObjectWithFirstLetterText(firstLetterObject, firstLetterBlock);
+ // Drill into inlines looking for our first text child.
+ RenderObject* currChild = firstLetterBlock->firstChild();
+ while (currChild) {
+ if (currChild->isText())
+ break;
+ if (currChild->isListMarker())
+ currChild = currChild->nextSibling();
+ else if (currChild->isFloatingOrPositioned()) {
+ if (currChild->style()->styleType() == FIRST_LETTER) {
+ currChild = currChild->firstChild();
+ break;
+ }
+ currChild = currChild->nextSibling();
+ } else if (currChild->isReplaced() || currChild->isRenderButton() || currChild->isMenuList())
+ break;
+ else if (currChild->style()->hasPseudoStyle(FIRST_LETTER) && canHaveGeneratedChildren(currChild)) {
+ // We found a lower-level node with first-letter, which supersedes the higher-level style
+ firstLetterBlock = currChild;
+ currChild = currChild->firstChild();
+ } else
+ currChild = currChild->firstChild();
+ }
- if (!firstLetterObject)
+ if (!currChild)
return;
-
- addFirstLetter(firstLetterObject, firstLetterBlock);
-}
-
-void RenderBlock::addFirstLetter(RenderObject* firstLetterObject, RenderObject* &firstLetterBlock)
-{
// If the child already has style, then it has already been created, so we just want
// to update it.
- if (firstLetterObject->parent()->style()->styleType() == FIRST_LETTER) {
- updateFirstLetterStyle(firstLetterBlock, firstLetterObject);
+ if (currChild->parent()->style()->styleType() == FIRST_LETTER) {
+ updateFirstLetterStyle(firstLetterBlock, currChild);
return;
}
- if (!firstLetterObject->isText() || firstLetterObject->isBR())
+ if (!currChild->isText() || currChild->isBR())
return;
// Our layout state is not valid for the repaints we are going to trigger by
// adding and removing children of firstLetterContainer.
LayoutStateDisabler layoutStateDisabler(view());
- createFirstLetterRenderer(firstLetterBlock, firstLetterObject);
+ createFirstLetterRenderer(firstLetterBlock, currChild);
}
// Helper methods for obtaining the last line, computing line counts and heights for line counts
@@ -6635,7 +6656,7 @@ LayoutUnit RenderBlock::applyBeforeBreak(RenderBox* child, LayoutUnit logicalOff
|| (checkRegionBreaks && child->style()->regionBreakBefore() == PBALWAYS);
if (checkBeforeAlways && inNormalFlow(child) && hasNextPage(logicalOffset, IncludePageBoundary)) {
if (checkColumnBreaks)
- view()->layoutState()->addForcedColumnBreak(logicalOffset);
+ view()->layoutState()->addForcedColumnBreak(child, logicalOffset);
return nextPageLogicalTop(logicalOffset, IncludePageBoundary);
}
return logicalOffset;
@@ -6652,7 +6673,7 @@ LayoutUnit RenderBlock::applyAfterBreak(RenderBox* child, LayoutUnit logicalOffs
if (checkAfterAlways && inNormalFlow(child) && hasNextPage(logicalOffset, IncludePageBoundary)) {
marginInfo.setMarginAfterQuirk(true); // Cause margins to be discarded for any following content.
if (checkColumnBreaks)
- view()->layoutState()->addForcedColumnBreak(logicalOffset);
+ view()->layoutState()->addForcedColumnBreak(child, logicalOffset);
return nextPageLogicalTop(logicalOffset, IncludePageBoundary);
}
return logicalOffset;
@@ -6776,7 +6797,9 @@ void RenderBlock::adjustLinePositionForPagination(RootInlineBox* lineBox, Layout
lineBox->setPaginationStrut(0);
LayoutUnit pageLogicalHeight = pageLogicalHeightForOffset(logicalOffset);
bool hasUniformPageLogicalHeight = !inRenderFlowThread() || enclosingRenderFlowThread()->regionsHaveUniformLogicalHeight();
- if (!pageLogicalHeight || (hasUniformPageLogicalHeight && lineHeight > pageLogicalHeight)
+ // If lineHeight is greater than pageLogicalHeight, but logicalVisualOverflow.height() still fits, we are
+ // still going to add a strut, so that the visible overflow fits on a single page.
+ if (!pageLogicalHeight || (hasUniformPageLogicalHeight && logicalVisualOverflow.height() > pageLogicalHeight)
|| !hasNextPage(logicalOffset))
return;
LayoutUnit remainingLogicalHeight = pageRemainingLogicalHeightForOffset(logicalOffset, ExcludePageBoundary);
@@ -6784,6 +6807,10 @@ void RenderBlock::adjustLinePositionForPagination(RootInlineBox* lineBox, Layout
// If we have a non-uniform page height, then we have to shift further possibly.
if (!hasUniformPageLogicalHeight && !pushToNextPageWithMinimumLogicalHeight(remainingLogicalHeight, logicalOffset, lineHeight))
return;
+ if (lineHeight > pageLogicalHeight) {
+ // Split the top margin in order to avoid splitting the visible part of the line.
+ remainingLogicalHeight -= min(lineHeight - pageLogicalHeight, max(ZERO_LAYOUT_UNIT, logicalVisualOverflow.y() - lineBox->lineTopWithLeading()));
+ }
LayoutUnit totalLogicalHeight = lineHeight + max(ZERO_LAYOUT_UNIT, logicalOffset);
LayoutUnit pageLogicalHeightAtNewOffset = hasUniformPageLogicalHeight ? pageLogicalHeight : pageLogicalHeightForOffset(logicalOffset + remainingLogicalHeight);
if (lineBox == firstRootBox() && totalLogicalHeight < pageLogicalHeightAtNewOffset && !isPositioned() && !isTableCell())
@@ -7197,8 +7224,8 @@ inline void RenderBlock::FloatingObjects::decreaseObjectsCount(FloatingObject::T
inline RenderBlock::FloatingObjectInterval RenderBlock::FloatingObjects::intervalForFloatingObject(FloatingObject* floatingObject)
{
if (m_horizontalWritingMode)
- return RenderBlock::FloatingObjectInterval(floatingObject->pixelSnappedY(), floatingObject->pixelSnappedMaxY(), floatingObject);
- return RenderBlock::FloatingObjectInterval(floatingObject->pixelSnappedX(), floatingObject->pixelSnappedMaxX(), floatingObject);
+ return RenderBlock::FloatingObjectInterval(floatingObject->frameRect().pixelSnappedY(), floatingObject->frameRect().pixelSnappedMaxY(), floatingObject);
+ return RenderBlock::FloatingObjectInterval(floatingObject->frameRect().pixelSnappedX(), floatingObject->frameRect().pixelSnappedMaxX(), floatingObject);
}
void RenderBlock::FloatingObjects::addPlacedObject(FloatingObject* floatingObject)
@@ -7342,7 +7369,7 @@ String ValueToString<int>::string(const int value)
String ValueToString<RenderBlock::FloatingObject*>::string(const RenderBlock::FloatingObject* floatingObject)
{
- return String::format("%p (%dx%d %dx%d)", floatingObject, floatingObject->pixelSnappedX(), floatingObject->pixelSnappedY(), floatingObject->pixelSnappedMaxX(), floatingObject->pixelSnappedMaxY());
+ return String::format("%p (%dx%d %dx%d)", floatingObject, floatingObject->frameRect().pixelSnappedX(), floatingObject->frameRect().pixelSnappedY(), floatingObject->frameRect().pixelSnappedMaxX(), floatingObject->frameRect().pixelSnappedMaxY());
}
#endif
diff --git a/Source/WebCore/rendering/RenderBlock.h b/Source/WebCore/rendering/RenderBlock.h
index a3cc33ea6..df4a6a2f0 100644
--- a/Source/WebCore/rendering/RenderBlock.h
+++ b/Source/WebCore/rendering/RenderBlock.h
@@ -505,9 +505,6 @@ private:
void createFirstLetterRenderer(RenderObject* firstLetterBlock, RenderObject* currentChild);
void updateFirstLetterStyle(RenderObject* firstLetterBlock, RenderObject* firstLetterContainer);
- RenderObject* findLastObjectWithFirstLetterText(RenderObject* child, RenderObject* &firstLetterBlock);
- RenderObject* findLastObjectAfterFirstLetterPunctuation(RenderObject* child, RenderObject* &firstLetterBlock);
- void addFirstLetter(RenderObject* firstLetterObject, RenderObject* &firstLetterBlock);
struct FloatWithRect {
FloatWithRect(RenderBox* f)
@@ -574,13 +571,6 @@ private:
inline LayoutUnit width() const { return m_frameRect.width(); }
inline LayoutUnit height() const { return m_frameRect.height(); }
- inline int pixelSnappedX() const { ASSERT(isPlaced()); return m_frameRect.pixelSnappedX(); }
- inline int pixelSnappedMaxX() const { ASSERT(isPlaced()); return m_frameRect.pixelSnappedMaxX(); }
- inline int pixelSnappedY() const { ASSERT(isPlaced()); return m_frameRect.pixelSnappedY(); }
- inline int pixelSnappedMaxY() const { ASSERT(isPlaced()); return m_frameRect.pixelSnappedMaxY(); }
- inline int pixelSnappedWidth() const { return m_frameRect.pixelSnappedWidth(); }
- inline int pixelSnappedHeight() const { return m_frameRect.pixelSnappedHeight(); }
-
void setX(LayoutUnit x) { ASSERT(!isInPlacedTree()); m_frameRect.setX(x); }
void setY(LayoutUnit y) { ASSERT(!isInPlacedTree()); m_frameRect.setY(y); }
void setWidth(LayoutUnit width) { ASSERT(!isInPlacedTree()); m_frameRect.setWidth(width); }
@@ -622,11 +612,10 @@ private:
LayoutUnit logicalRightForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->maxX() : child->maxY(); }
LayoutUnit logicalWidthForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->width() : child->height(); }
- int pixelSnappedLogicalTopForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->pixelSnappedY() : child->pixelSnappedX(); }
- int pixelSnappedLogicalBottomForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->pixelSnappedMaxY() : child->pixelSnappedMaxX(); }
- int pixelSnappedLogicalLeftForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->pixelSnappedX() : child->pixelSnappedY(); }
- int pixelSnappedLogicalRightForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->pixelSnappedMaxX() : child->pixelSnappedMaxY(); }
- int pixelSnappedLogicalWidthForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->pixelSnappedWidth() : child->pixelSnappedHeight(); }
+ int pixelSnappedLogicalTopForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->frameRect().pixelSnappedY() : child->frameRect().pixelSnappedX(); }
+ int pixelSnappedLogicalBottomForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->frameRect().pixelSnappedMaxY() : child->frameRect().pixelSnappedMaxX(); }
+ int pixelSnappedLogicalLeftForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->frameRect().pixelSnappedX() : child->frameRect().pixelSnappedY(); }
+ int pixelSnappedLogicalRightForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->frameRect().pixelSnappedMaxX() : child->frameRect().pixelSnappedMaxY(); }
void setLogicalTopForFloat(FloatingObject* child, LayoutUnit logicalTop)
{
@@ -911,7 +900,11 @@ private:
bool handleSpecialChild(RenderBox* child, const MarginInfo&);
bool handleFloatingChild(RenderBox* child, const MarginInfo&);
bool handlePositionedChild(RenderBox* child, const MarginInfo&);
- bool handleRunInChild(RenderBox* child);
+
+ RenderBoxModelObject* createReplacementRunIn(RenderBoxModelObject* runIn);
+ void moveRunInUnderSiblingBlockIfNeeded(RenderObject* runIn);
+ void moveRunInToOriginalPosition(RenderObject* runIn);
+
LayoutUnit collapseMargins(RenderBox* child, MarginInfo&);
LayoutUnit clearFloatsIfNeeded(RenderBox* child, MarginInfo&, LayoutUnit oldTopPosMargin, LayoutUnit oldTopNegMargin, LayoutUnit yPos);
LayoutUnit estimateLogicalTopPosition(RenderBox* child, const MarginInfo&, LayoutUnit& estimateWithoutPagination);
diff --git a/Source/WebCore/rendering/RenderBlockLineLayout.cpp b/Source/WebCore/rendering/RenderBlockLineLayout.cpp
index 362d31fc7..922e72fa5 100755
--- a/Source/WebCore/rendering/RenderBlockLineLayout.cpp
+++ b/Source/WebCore/rendering/RenderBlockLineLayout.cpp
@@ -2668,7 +2668,7 @@ void RenderBlock::addOverflowFromInlineChildren()
{
LayoutUnit endPadding = hasOverflowClip() ? paddingEnd() : ZERO_LAYOUT_UNIT;
// FIXME: Need to find another way to do this, since scrollbars could show when we don't want them to.
- if (hasOverflowClip() && !endPadding && node() && node()->rendererIsEditable() && node() == node()->rootEditableElement() && style()->isLeftToRightDirection())
+ if (hasOverflowClip() && !endPadding && node() && node()->isRootEditableElement() && style()->isLeftToRightDirection())
endPadding = 1;
for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) {
addLayoutOverflow(curr->paddedLayoutOverflowRect(endPadding));
diff --git a/Source/WebCore/rendering/RenderBox.cpp b/Source/WebCore/rendering/RenderBox.cpp
index 199deb6b2..cf6615b22 100644
--- a/Source/WebCore/rendering/RenderBox.cpp
+++ b/Source/WebCore/rendering/RenderBox.cpp
@@ -4019,29 +4019,6 @@ bool RenderBox::hasRelativeLogicalHeight() const
|| style()->logicalMaxHeight().isPercent();
}
-void RenderBox::moveChildTo(RenderBox* toBox, RenderObject* child, RenderObject* beforeChild, bool fullRemoveInsert)
-{
- ASSERT(this == child->parent());
- ASSERT(!beforeChild || toBox == beforeChild->parent());
- if (fullRemoveInsert && toBox->isRenderBlock()) {
- // Takes care of adding the new child correctly if toBlock and fromBlock
- // have different kind of children (block vs inline).
- toBox->addChild(virtualChildren()->removeChildNode(this, child), beforeChild);
- } else
- toBox->virtualChildren()->insertChildNode(toBox, virtualChildren()->removeChildNode(this, child, fullRemoveInsert), beforeChild, fullRemoveInsert);
-}
-
-void RenderBox::moveChildrenTo(RenderBox* toBox, RenderObject* startChild, RenderObject* endChild, RenderObject* beforeChild, bool fullRemoveInsert)
-{
- ASSERT(!beforeChild || toBox == beforeChild->parent());
- for (RenderObject* child = startChild; child && child != endChild; ) {
- // Save our next sibling as moveChildTo will clear it.
- RenderObject* nextSibling = child->nextSibling();
- moveChildTo(toBox, child, beforeChild, fullRemoveInsert);
- child = nextSibling;
- }
-}
-
static void markBoxForRelayoutAfterSplit(RenderBox* box)
{
// FIXME: The table code should handle that automatically. If not,
diff --git a/Source/WebCore/rendering/RenderBox.h b/Source/WebCore/rendering/RenderBox.h
index 9f00a44e3..94fc105a6 100644
--- a/Source/WebCore/rendering/RenderBox.h
+++ b/Source/WebCore/rendering/RenderBox.h
@@ -73,6 +73,9 @@ public:
LayoutUnit logicalWidth() const { return style()->isHorizontalWritingMode() ? width() : height(); }
LayoutUnit logicalHeight() const { return style()->isHorizontalWritingMode() ? height() : width(); }
+ int pixelSnappedLogicalHeight() const { return style()->isHorizontalWritingMode() ? pixelSnappedHeight() : pixelSnappedWidth(); }
+ int pixelSnappedLogicalWidth() const { return style()->isHorizontalWritingMode() ? pixelSnappedWidth() : pixelSnappedHeight(); }
+
void setLogicalLeft(LayoutUnit left)
{
if (style()->isHorizontalWritingMode())
@@ -524,30 +527,6 @@ protected:
void paintRootBoxFillLayers(const PaintInfo&);
- // These functions are only used internally to manipulate the render tree structure via remove/insert/appendChildNode.
- // Since they are typically called only to move objects around within anonymous blocks (which only have layers in
- // the case of column spans), the default for fullRemoveInsert is false rather than true.
- void moveChildTo(RenderBox* toBox, RenderObject* child, RenderObject* beforeChild, bool fullRemoveInsert = false);
- void moveChildTo(RenderBox* to, RenderObject* child, bool fullRemoveInsert = false)
- {
- moveChildTo(to, child, 0, fullRemoveInsert);
- }
- void moveAllChildrenTo(RenderBox* toBox, bool fullRemoveInsert = false)
- {
- moveAllChildrenTo(toBox, 0, fullRemoveInsert);
- }
- void moveAllChildrenTo(RenderBox* toBox, RenderObject* beforeChild, bool fullRemoveInsert = false)
- {
- moveChildrenTo(toBox, firstChild(), 0, beforeChild, fullRemoveInsert);
- }
- // Move all of the kids from |startChild| up to but excluding |endChild|. 0 can be passed as the |endChild| to denote
- // that all the kids from |startChild| onwards should be moved.
- void moveChildrenTo(RenderBox* toBox, RenderObject* startChild, RenderObject* endChild, bool fullRemoveInsert = false)
- {
- moveChildrenTo(toBox, startChild, endChild, 0, fullRemoveInsert);
- }
- void moveChildrenTo(RenderBox* toBox, RenderObject* startChild, RenderObject* endChild, RenderObject* beforeChild, bool fullRemoveInsert = false);
-
RenderObject* splitAnonymousBoxesAroundChild(RenderObject* beforeChild);
private:
diff --git a/Source/WebCore/rendering/RenderBoxModelObject.cpp b/Source/WebCore/rendering/RenderBoxModelObject.cpp
index fcca1b3d5..b23ad9980 100644
--- a/Source/WebCore/rendering/RenderBoxModelObject.cpp
+++ b/Source/WebCore/rendering/RenderBoxModelObject.cpp
@@ -3017,4 +3017,27 @@ void RenderBoxModelObject::mapAbsoluteToLocalPoint(bool fixed, bool useTransform
transformState.move(containerOffset.width(), containerOffset.height(), preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
}
+void RenderBoxModelObject::moveChildTo(RenderBoxModelObject* toBoxModelObject, RenderObject* child, RenderObject* beforeChild, bool fullRemoveInsert)
+{
+ ASSERT(this == child->parent());
+ ASSERT(!beforeChild || toBoxModelObject == beforeChild->parent());
+ if (fullRemoveInsert && (toBoxModelObject->isRenderBlock() || toBoxModelObject->isRenderInline())) {
+ // Takes care of adding the new child correctly if toBlock and fromBlock
+ // have different kind of children (block vs inline).
+ toBoxModelObject->addChild(virtualChildren()->removeChildNode(this, child), beforeChild);
+ } else
+ toBoxModelObject->virtualChildren()->insertChildNode(toBoxModelObject, virtualChildren()->removeChildNode(this, child, fullRemoveInsert), beforeChild, fullRemoveInsert);
+}
+
+void RenderBoxModelObject::moveChildrenTo(RenderBoxModelObject* toBoxModelObject, RenderObject* startChild, RenderObject* endChild, RenderObject* beforeChild, bool fullRemoveInsert)
+{
+ ASSERT(!beforeChild || toBoxModelObject == beforeChild->parent());
+ for (RenderObject* child = startChild; child && child != endChild; ) {
+ // Save our next sibling as moveChildTo will clear it.
+ RenderObject* nextSibling = child->nextSibling();
+ moveChildTo(toBoxModelObject, child, beforeChild, fullRemoveInsert);
+ child = nextSibling;
+ }
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/rendering/RenderBoxModelObject.h b/Source/WebCore/rendering/RenderBoxModelObject.h
index 6c88f0fbf..d0883a5ee 100644
--- a/Source/WebCore/rendering/RenderBoxModelObject.h
+++ b/Source/WebCore/rendering/RenderBoxModelObject.h
@@ -246,6 +246,30 @@ public:
RenderObject* firstLetterRemainingText() const;
void setFirstLetterRemainingText(RenderObject*);
+ // These functions are only used internally to manipulate the render tree structure via remove/insert/appendChildNode.
+ // Since they are typically called only to move objects around within anonymous blocks (which only have layers in
+ // the case of column spans), the default for fullRemoveInsert is false rather than true.
+ void moveChildTo(RenderBoxModelObject* toBoxModelObject, RenderObject* child, RenderObject* beforeChild, bool fullRemoveInsert = false);
+ void moveChildTo(RenderBoxModelObject* toBoxModelObject, RenderObject* child, bool fullRemoveInsert = false)
+ {
+ moveChildTo(toBoxModelObject, child, 0, fullRemoveInsert);
+ }
+ void moveAllChildrenTo(RenderBoxModelObject* toBoxModelObject, bool fullRemoveInsert = false)
+ {
+ moveAllChildrenTo(toBoxModelObject, 0, fullRemoveInsert);
+ }
+ void moveAllChildrenTo(RenderBoxModelObject* toBoxModelObject, RenderObject* beforeChild, bool fullRemoveInsert = false)
+ {
+ moveChildrenTo(toBoxModelObject, firstChild(), 0, beforeChild, fullRemoveInsert);
+ }
+ // Move all of the kids from |startChild| up to but excluding |endChild|. 0 can be passed as the |endChild| to denote
+ // that all the kids from |startChild| onwards should be moved.
+ void moveChildrenTo(RenderBoxModelObject* toBoxModelObject, RenderObject* startChild, RenderObject* endChild, bool fullRemoveInsert = false)
+ {
+ moveChildrenTo(toBoxModelObject, startChild, endChild, 0, fullRemoveInsert);
+ }
+ void moveChildrenTo(RenderBoxModelObject* toBoxModelObject, RenderObject* startChild, RenderObject* endChild, RenderObject* beforeChild, bool fullRemoveInsert = false);
+
private:
virtual bool isBoxModelObject() const { return true; }
diff --git a/Source/WebCore/rendering/RenderDeprecatedFlexibleBox.cpp b/Source/WebCore/rendering/RenderDeprecatedFlexibleBox.cpp
index b956d3946..7fae3c40f 100644
--- a/Source/WebCore/rendering/RenderDeprecatedFlexibleBox.cpp
+++ b/Source/WebCore/rendering/RenderDeprecatedFlexibleBox.cpp
@@ -301,7 +301,7 @@ void RenderDeprecatedFlexibleBox::layoutBlock(bool relayoutChildren, LayoutUnit)
updateLayerTransform();
if (view()->layoutState()->pageLogicalHeight())
- setPageLogicalOffset(view()->layoutState()->pageLogicalOffset(logicalTop()));
+ setPageLogicalOffset(view()->layoutState()->pageLogicalOffset(this, logicalTop()));
// Update our scrollbars if we're overflow:auto/scroll/hidden now that we know if
// we overflow or not.
diff --git a/Source/WebCore/rendering/RenderEmbeddedObject.cpp b/Source/WebCore/rendering/RenderEmbeddedObject.cpp
index 55cfcfd4d..315c16f8a 100644
--- a/Source/WebCore/rendering/RenderEmbeddedObject.cpp
+++ b/Source/WebCore/rendering/RenderEmbeddedObject.cpp
@@ -102,11 +102,28 @@ bool RenderEmbeddedObject::allowsAcceleratedCompositing() const
}
#endif
+static String unavailablePluginReplacementText(RenderEmbeddedObject::PluginUnavailabilityReason pluginUnavailabilityReason)
+{
+ switch (pluginUnavailabilityReason) {
+ case RenderEmbeddedObject::PluginMissing:
+ return missingPluginText();
+ case RenderEmbeddedObject::PluginCrashed:
+ return crashedPluginText();
+ case RenderEmbeddedObject::InsecurePluginVersion:
+ return insecurePluginVersionText();
+ }
+
+ ASSERT_NOT_REACHED();
+ return String();
+}
+
void RenderEmbeddedObject::setPluginUnavailabilityReason(PluginUnavailabilityReason pluginUnavailabilityReason)
{
ASSERT(!m_showsUnavailablePluginIndicator);
m_showsUnavailablePluginIndicator = true;
m_pluginUnavailabilityReason = pluginUnavailabilityReason;
+
+ m_unavailablePluginReplacementText = unavailablePluginReplacementText(pluginUnavailabilityReason);
}
bool RenderEmbeddedObject::showsUnavailablePluginIndicator() const
@@ -193,8 +210,8 @@ bool RenderEmbeddedObject::getReplacementTextGeometry(const LayoutPoint& accumul
fontDescription.setComputedSize(fontDescription.specifiedSize());
font = Font(fontDescription, 0, 0);
font.update(0);
-
- run = TextRun(unavailablePluginReplacementText());
+
+ run = TextRun(m_unavailablePluginReplacementText);
textWidth = font.width(run);
replacementTextRect.setSize(FloatSize(textWidth + replacementTextRoundedRectLeftRightTextMargin * 2, replacementTextRoundedRectHeight));
@@ -207,21 +224,6 @@ bool RenderEmbeddedObject::getReplacementTextGeometry(const LayoutPoint& accumul
return true;
}
-String RenderEmbeddedObject::unavailablePluginReplacementText() const
-{
- switch (m_pluginUnavailabilityReason) {
- case PluginMissing:
- return missingPluginText();
- case PluginCrashed:
- return crashedPluginText();
- case InsecurePluginVersion:
- return insecurePluginVersionText();
- }
-
- ASSERT_NOT_REACHED();
- return String();
-}
-
void RenderEmbeddedObject::layout()
{
ASSERT(needsLayout());
diff --git a/Source/WebCore/rendering/RenderEmbeddedObject.h b/Source/WebCore/rendering/RenderEmbeddedObject.h
index 3564ff287..1e0bffb30 100644
--- a/Source/WebCore/rendering/RenderEmbeddedObject.h
+++ b/Source/WebCore/rendering/RenderEmbeddedObject.h
@@ -78,12 +78,12 @@ private:
bool isInUnavailablePluginIndicator(MouseEvent*) const;
bool isInUnavailablePluginIndicator(const LayoutPoint&) const;
bool getReplacementTextGeometry(const LayoutPoint& accumulatedOffset, FloatRect& contentRect, Path&, FloatRect& replacementTextRect, Font&, TextRun&, float& textWidth) const;
- String unavailablePluginReplacementText() const;
bool m_hasFallbackContent; // FIXME: This belongs on HTMLObjectElement.
bool m_showsUnavailablePluginIndicator;
PluginUnavailabilityReason m_pluginUnavailabilityReason;
+ String m_unavailablePluginReplacementText;
bool m_unavailablePluginIndicatorIsPressed;
bool m_mouseDownWasInUnavailablePluginIndicator;
};
diff --git a/Source/WebCore/rendering/RenderFlowThread.cpp b/Source/WebCore/rendering/RenderFlowThread.cpp
index 393964ade..2e04a6bf9 100644
--- a/Source/WebCore/rendering/RenderFlowThread.cpp
+++ b/Source/WebCore/rendering/RenderFlowThread.cpp
@@ -292,16 +292,16 @@ void RenderFlowThread::paintIntoRegion(PaintInfo& paintInfo, RenderRegion* regio
// RenderFlowThread should start painting its content in a position that is offset
// from the region rect's current position. The amount of offset is equal to the location of
// region in flow coordinates.
- LayoutPoint renderFlowThreadOffset;
+ IntPoint renderFlowThreadOffset;
if (style()->isFlippedBlocksWritingMode()) {
LayoutRect flippedRegionRect(regionRect);
flipForWritingMode(flippedRegionRect);
- renderFlowThreadOffset = LayoutPoint(paintOffset - flippedRegionRect.location());
+ renderFlowThreadOffset = roundedIntPoint(paintOffset - flippedRegionRect.location());
} else
- renderFlowThreadOffset = LayoutPoint(paintOffset - regionRect.location());
+ renderFlowThreadOffset = roundedIntPoint(paintOffset - regionRect.location());
context->translate(renderFlowThreadOffset.x(), renderFlowThreadOffset.y());
- info.rect.moveBy(-roundedIntPoint(renderFlowThreadOffset));
+ info.rect.moveBy(-renderFlowThreadOffset);
layer()->paint(context, info.rect, 0, 0, region, RenderLayer::PaintLayerTemporaryClipRects);
diff --git a/Source/WebCore/rendering/RenderFrameBase.cpp b/Source/WebCore/rendering/RenderFrameBase.cpp
index 046288bff..aa82870d4 100644
--- a/Source/WebCore/rendering/RenderFrameBase.cpp
+++ b/Source/WebCore/rendering/RenderFrameBase.cpp
@@ -38,13 +38,26 @@ RenderFrameBase::RenderFrameBase(Element* element)
{
}
-void RenderFrameBase::layoutWithFlattening(bool fixedWidth, bool fixedHeight)
+inline bool shouldExpandFrame(LayoutUnit width, LayoutUnit height, bool hasFixedWidth, bool hasFixedHeight)
+{
+ // If the size computed to zero never expand.
+ if (!width || !height)
+ return false;
+ // Really small fixed size frames can't be meant to be scrolled and are there probably by mistake. Avoid expanding.
+ static unsigned smallestUsefullyScrollableDimension = 8;
+ if (hasFixedWidth && width < LayoutUnit(smallestUsefullyScrollableDimension))
+ return false;
+ if (hasFixedHeight && height < LayoutUnit(smallestUsefullyScrollableDimension))
+ return false;
+ return true;
+}
+
+void RenderFrameBase::layoutWithFlattening(bool hasFixedWidth, bool hasFixedHeight)
{
FrameView* childFrameView = static_cast<FrameView*>(widget());
RenderView* childRoot = childFrameView ? static_cast<RenderView*>(childFrameView->frame()->contentRenderer()) : 0;
- // Do not expand frames which has zero width or height
- if (!width() || !height() || !childRoot) {
+ if (!childRoot || !shouldExpandFrame(width(), height(), hasFixedWidth, hasFixedHeight)) {
updateWidgetPosition();
if (childFrameView)
childFrameView->layout();
@@ -69,7 +82,7 @@ void RenderFrameBase::layoutWithFlattening(bool fixedWidth, bool fixedHeight)
int vBorder = borderTop() + borderBottom();
// make sure minimum preferred width is enforced
- if (isScrollable || !fixedWidth) {
+ if (isScrollable || !hasFixedWidth) {
setWidth(max(width(), childRoot->minPreferredLogicalWidth() + hBorder));
// update again to pass the new width to the child frame
updateWidgetPosition();
@@ -77,9 +90,9 @@ void RenderFrameBase::layoutWithFlattening(bool fixedWidth, bool fixedHeight)
}
// expand the frame by setting frame height = content height
- if (isScrollable || !fixedHeight || childRoot->isFrameSet())
+ if (isScrollable || !hasFixedHeight || childRoot->isFrameSet())
setHeight(max<LayoutUnit>(height(), childFrameView->contentsHeight() + vBorder));
- if (isScrollable || !fixedWidth || childRoot->isFrameSet())
+ if (isScrollable || !hasFixedWidth || childRoot->isFrameSet())
setWidth(max<LayoutUnit>(width(), childFrameView->contentsWidth() + hBorder));
updateWidgetPosition();
diff --git a/Source/WebCore/rendering/RenderFrameSet.cpp b/Source/WebCore/rendering/RenderFrameSet.cpp
index ac449a240..7c89d8db8 100644
--- a/Source/WebCore/rendering/RenderFrameSet.cpp
+++ b/Source/WebCore/rendering/RenderFrameSet.cpp
@@ -667,7 +667,7 @@ bool RenderFrameSet::flattenFrameSet() const
void RenderFrameSet::startResizing(GridAxis& axis, int position)
{
int split = hitTestSplit(axis, position);
- if (split == noSplit || !axis.m_allowBorder[split] || axis.m_preventResize[split]) {
+ if (split == noSplit || axis.m_preventResize[split]) {
axis.m_splitBeingResized = noSplit;
return;
}
@@ -746,13 +746,13 @@ bool RenderFrameSet::isResizingColumn() const
bool RenderFrameSet::canResizeRow(const IntPoint& p) const
{
int r = hitTestSplit(m_rows, p.y());
- return r != noSplit && m_rows.m_allowBorder[r] && !m_rows.m_preventResize[r];
+ return r != noSplit && !m_rows.m_preventResize[r];
}
bool RenderFrameSet::canResizeColumn(const IntPoint& p) const
{
int c = hitTestSplit(m_cols, p.x());
- return c != noSplit && m_cols.m_allowBorder[c] && !m_cols.m_preventResize[c];
+ return c != noSplit && !m_cols.m_preventResize[c];
}
int RenderFrameSet::splitPosition(const GridAxis& axis, int split) const
diff --git a/Source/WebCore/rendering/RenderImage.cpp b/Source/WebCore/rendering/RenderImage.cpp
index 09d4e0d31..7049f8b50 100644
--- a/Source/WebCore/rendering/RenderImage.cpp
+++ b/Source/WebCore/rendering/RenderImage.cpp
@@ -141,7 +141,10 @@ void RenderImage::styleDidChange(StyleDifference diff, const RenderStyle* oldSty
void RenderImage::imageChanged(WrappedImagePtr newImage, const IntRect* rect)
{
- if (documentBeingDestroyed())
+ // FIXME (86669): Instead of the RenderImage determining whether its document is in the page
+ // cache, the RenderImage should remove itself as a client when its document is put into the
+ // page cache.
+ if (documentBeingDestroyed() || document()->inPageCache())
return;
if (hasBoxDecorations() || hasMask())
diff --git a/Source/WebCore/rendering/RenderInline.cpp b/Source/WebCore/rendering/RenderInline.cpp
index 6804383ed..38a874b4a 100644
--- a/Source/WebCore/rendering/RenderInline.cpp
+++ b/Source/WebCore/rendering/RenderInline.cpp
@@ -932,14 +932,7 @@ LayoutRect RenderInline::clippedOverflowRectForRepaint(RenderBoxModelObject* rep
if (!firstLineBoxIncludingCulling() && !continuation())
return LayoutRect();
- // Find our leftmost position.
- LayoutRect boundingBox(linesVisualOverflowBoundingBox());
- LayoutUnit left = boundingBox.x();
- LayoutUnit top = boundingBox.y();
-
- // Now invalidate a rectangle.
- LayoutUnit ow = style() ? style()->outlineSize() : 0;
-
+ LayoutRect repaintRect(linesVisualOverflowBoundingBox());
bool hitRepaintContainer = false;
// We need to add in the relative position offsets of any inlines (including us) up to our
@@ -952,45 +945,41 @@ LayoutRect RenderInline::clippedOverflowRectForRepaint(RenderBoxModelObject* rep
break;
}
if (inlineFlow->style()->position() == RelativePosition && inlineFlow->hasLayer())
- toRenderInline(inlineFlow)->layer()->relativePositionOffset(left, top);
+ repaintRect.move(toRenderInline(inlineFlow)->layer()->relativePositionOffset());
}
- LayoutRect r(-ow + left, -ow + top, boundingBox.width() + ow * 2, boundingBox.height() + ow * 2);
+ LayoutUnit outlineSize = style()->outlineSize();
+ repaintRect.inflate(outlineSize);
if (hitRepaintContainer || !cb)
- return r;
+ return repaintRect;
if (cb->hasColumns())
- cb->adjustRectForColumns(r);
+ cb->adjustRectForColumns(repaintRect);
if (cb->hasOverflowClip()) {
// cb->height() is inaccurate if we're in the middle of a layout of |cb|, so use the
// layer's size instead. Even if the layer's size is wrong, the layer itself will repaint
// anyway if its size does change.
- LayoutRect repaintRect(r);
repaintRect.move(-cb->scrolledContentOffset()); // For overflow:auto/scroll/hidden.
LayoutRect boxRect(LayoutPoint(), cb->cachedSizeForOverflowClip());
- r = intersection(repaintRect, boxRect);
+ repaintRect.intersect(boxRect);
}
- cb->computeRectForRepaint(repaintContainer, r);
+ cb->computeRectForRepaint(repaintContainer, repaintRect);
- if (ow) {
+ if (outlineSize) {
for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
- if (!curr->isText()) {
- LayoutRect childRect = curr->rectWithOutlineForRepaint(repaintContainer, ow);
- r.unite(childRect);
- }
+ if (!curr->isText())
+ repaintRect.unite(curr->rectWithOutlineForRepaint(repaintContainer, outlineSize));
}
- if (continuation() && !continuation()->isInline() && continuation()->parent()) {
- LayoutRect contRect = continuation()->rectWithOutlineForRepaint(repaintContainer, ow);
- r.unite(contRect);
- }
+ if (continuation() && !continuation()->isInline() && continuation()->parent())
+ repaintRect.unite(continuation()->rectWithOutlineForRepaint(repaintContainer, outlineSize));
}
- return r;
+ return repaintRect;
}
LayoutRect RenderInline::rectWithOutlineForRepaint(RenderBoxModelObject* repaintContainer, LayoutUnit outlineWidth) const
diff --git a/Source/WebCore/rendering/RenderLayer.cpp b/Source/WebCore/rendering/RenderLayer.cpp
index 1c1103ce9..a82d9369d 100644
--- a/Source/WebCore/rendering/RenderLayer.cpp
+++ b/Source/WebCore/rendering/RenderLayer.cpp
@@ -452,11 +452,16 @@ void RenderLayer::updateLayerPositions(LayoutPoint* offsetFromRoot, UpdateLayerP
*offsetFromRoot = oldOffsetFromRoot;
}
-LayoutRect RenderLayer::repaintRectIncludingDescendants() const
+LayoutRect RenderLayer::repaintRectIncludingNonCompositingDescendants() const
{
LayoutRect repaintRect = m_repaintRect;
- for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
- repaintRect.unite(child->repaintRectIncludingDescendants());
+ for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
+ // Don't include repaint rects for composited child layers; they will paint themselves and have a different origin.
+ if (child->isComposited())
+ continue;
+
+ repaintRect.unite(child->repaintRectIncludingNonCompositingDescendants());
+ }
return repaintRect;
}
@@ -736,17 +741,19 @@ bool RenderLayer::update3DTransformedDescendantStatus()
if (m_3DTransformedDescendantStatusDirty) {
m_has3DTransformedDescendant = false;
+ updateZOrderLists();
+
// Transformed or preserve-3d descendants can only be in the z-order lists, not
// in the normal flow list, so we only need to check those.
- if (m_posZOrderList) {
- for (unsigned i = 0; i < m_posZOrderList->size(); ++i)
- m_has3DTransformedDescendant |= m_posZOrderList->at(i)->update3DTransformedDescendantStatus();
+ if (Vector<RenderLayer*>* positiveZOrderList = posZOrderList()) {
+ for (unsigned i = 0; i < positiveZOrderList->size(); ++i)
+ m_has3DTransformedDescendant |= positiveZOrderList->at(i)->update3DTransformedDescendantStatus();
}
// Now check our negative z-index children.
- if (m_negZOrderList) {
- for (unsigned i = 0; i < m_negZOrderList->size(); ++i)
- m_has3DTransformedDescendant |= m_negZOrderList->at(i)->update3DTransformedDescendantStatus();
+ if (Vector<RenderLayer*>* negativeZOrderList = negZOrderList()) {
+ for (unsigned i = 0; i < negativeZOrderList->size(); ++i)
+ m_has3DTransformedDescendant |= negativeZOrderList->at(i)->update3DTransformedDescendantStatus();
}
m_3DTransformedDescendantStatusDirty = false;
@@ -2211,16 +2218,19 @@ PassRefPtr<Scrollbar> RenderLayer::createScrollbar(ScrollbarOrientation orientat
void RenderLayer::destroyScrollbar(ScrollbarOrientation orientation)
{
RefPtr<Scrollbar>& scrollbar = orientation == HorizontalScrollbar ? m_hBar : m_vBar;
- if (scrollbar) {
+ if (!scrollbar)
+ return;
+
+ if (!scrollbar->isCustomScrollbar()) {
if (orientation == HorizontalScrollbar)
willRemoveHorizontalScrollbar(scrollbar.get());
else
willRemoveVerticalScrollbar(scrollbar.get());
-
- scrollbar->removeFromParent();
- scrollbar->disconnectFromScrollableArea();
- scrollbar = 0;
}
+
+ scrollbar->removeFromParent();
+ scrollbar->disconnectFromScrollableArea();
+ scrollbar = 0;
}
bool RenderLayer::scrollsOverflow() const
@@ -2432,13 +2442,12 @@ void RenderLayer::computeScrollDimensions()
m_scrollDimensionsDirty = false;
- m_scrollOverflow.setWidth(overflowLeft() - box->borderLeft());
- m_scrollOverflow.setHeight(overflowTop() - box->borderTop());
-
m_scrollSize.setWidth(overflowRight() - overflowLeft());
m_scrollSize.setHeight(overflowBottom() - overflowTop());
- setScrollOrigin(IntPoint(-m_scrollOverflow.width(), -m_scrollOverflow.height()));
+ int scrollableLeftOverflow = overflowLeft() - box->borderLeft();
+ int scrollableTopOverflow = overflowTop() - box->borderTop();
+ setScrollOrigin(IntPoint(-scrollableLeftOverflow, -scrollableTopOverflow));
}
bool RenderLayer::hasHorizontalOverflow() const
@@ -2887,7 +2896,7 @@ void RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* context,
// but we need to ensure that we don't cache clip rects computed with the wrong root in this case.
if (context->updatingControlTints() || (paintBehavior & PaintBehaviorFlattenCompositingLayers))
paintFlags |= PaintLayerTemporaryClipRects;
- else if (!backing()->paintsIntoWindow() && !backing()->paintsIntoCompositedAncestor() && !shouldDoSoftwarePaint(this, paintFlags & PaintLayerPaintingReflection) && !rootLayer->containsDirtyOverlayScrollbars()) {
+ else if (!backing()->paintsIntoWindow() && !backing()->paintsIntoCompositedAncestor() && !shouldDoSoftwarePaint(this, paintFlags & PaintLayerPaintingReflection) && !(rootLayer->containsDirtyOverlayScrollbars() && (paintFlags & PaintLayerPaintingOverlayScrollbars))) {
// If this RenderLayer should paint into its backing, that will be done via RenderLayerBacking::paintIntoLayer().
return;
}
@@ -3080,7 +3089,7 @@ void RenderLayer::paintLayerContents(RenderLayer* rootLayer, GraphicsContext* co
}
// Now walk the sorted list of children with negative z-indices.
- paintList(m_negZOrderList, rootLayer, context, paintDirtyRect, paintBehavior, paintingRoot, region, overlapTestRequests, localPaintFlags);
+ paintList(negZOrderList(), rootLayer, context, paintDirtyRect, paintBehavior, paintingRoot, region, overlapTestRequests, localPaintFlags);
}
if (localPaintFlags & PaintLayerPaintingCompositingForegroundPhase) {
@@ -3127,7 +3136,7 @@ void RenderLayer::paintLayerContents(RenderLayer* rootLayer, GraphicsContext* co
paintList(m_normalFlowList, rootLayer, context, paintDirtyRect, paintBehavior, paintingRoot, region, overlapTestRequests, localPaintFlags);
// Now walk the sorted list of children with positive z-indices.
- paintList(m_posZOrderList, rootLayer, context, paintDirtyRect, paintBehavior, paintingRoot, region, overlapTestRequests, localPaintFlags);
+ paintList(posZOrderList(), rootLayer, context, paintDirtyRect, paintBehavior, paintingRoot, region, overlapTestRequests, localPaintFlags);
}
if ((localPaintFlags & PaintLayerPaintingCompositingMaskPhase) && shouldPaintContent && renderer()->hasMask() && !selectionOnly) {
@@ -3546,7 +3555,7 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* cont
RenderLayer* candidateLayer = 0;
// Begin by walking our list of positive layers from highest z-index down to the lowest z-index.
- RenderLayer* hitLayer = hitTestList(m_posZOrderList, rootLayer, request, result, hitTestRect, hitTestPoint,
+ RenderLayer* hitLayer = hitTestList(posZOrderList(), rootLayer, request, result, hitTestRect, hitTestPoint,
localTransformState.get(), zOffsetForDescendantsPtr, zOffset, unflattenedTransformState.get(), depthSortDescendants);
if (hitLayer) {
if (!depthSortDescendants)
@@ -3566,7 +3575,7 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* cont
// Next we want to see if the mouse pos is inside the child RenderObjects of the layer.
if (fgRect.intersects(hitTestArea) && isSelfPaintingLayer()) {
// Hit test with a temporary HitTestResult, because we only want to commit to 'result' if we know we're frontmost.
- HitTestResult tempResult(result.point(), result.topPadding(), result.rightPadding(), result.bottomPadding(), result.leftPadding(), result.shadowContentFilterPolicy());
+ HitTestResult tempResult(result.hitTestPoint(), result.shadowContentFilterPolicy());
if (hitTestContents(request, tempResult, layerBounds, hitTestPoint, HitTestDescendants) &&
isHitCandidate(this, false, zOffsetForContentsPtr, unflattenedTransformState.get())) {
if (result.isRectBasedTest())
@@ -3582,7 +3591,7 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* cont
}
// Now check our negative z-index children.
- hitLayer = hitTestList(m_negZOrderList, rootLayer, request, result, hitTestRect, hitTestPoint,
+ hitLayer = hitTestList(negZOrderList(), rootLayer, request, result, hitTestRect, hitTestPoint,
localTransformState.get(), zOffsetForDescendantsPtr, zOffset, unflattenedTransformState.get(), depthSortDescendants);
if (hitLayer) {
if (!depthSortDescendants)
@@ -3595,7 +3604,7 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* cont
return candidateLayer;
if (bgRect.intersects(hitTestArea) && isSelfPaintingLayer()) {
- HitTestResult tempResult(result.point(), result.topPadding(), result.rightPadding(), result.bottomPadding(), result.leftPadding(), result.shadowContentFilterPolicy());
+ HitTestResult tempResult(result.hitTestPoint(), result.shadowContentFilterPolicy());
if (hitTestContents(request, tempResult, layerBounds, hitTestPoint, HitTestSelf) &&
isHitCandidate(this, false, zOffsetForContentsPtr, unflattenedTransformState.get())) {
if (result.isRectBasedTest())
@@ -3651,7 +3660,7 @@ RenderLayer* RenderLayer::hitTestList(Vector<RenderLayer*>* list, RenderLayer* r
for (int i = list->size() - 1; i >= 0; --i) {
RenderLayer* childLayer = list->at(i);
RenderLayer* hitLayer = 0;
- HitTestResult tempResult(result.point(), result.topPadding(), result.rightPadding(), result.bottomPadding(), result.leftPadding(), result.shadowContentFilterPolicy());
+ HitTestResult tempResult(result.hitTestPoint(), result.shadowContentFilterPolicy());
if (childLayer->isPaginated())
hitLayer = hitTestPaginatedChildLayer(childLayer, rootLayer, request, tempResult, hitTestRect, hitTestPoint, transformState, zOffsetForDescendants);
else
@@ -4140,8 +4149,13 @@ IntRect RenderLayer::calculateLayerBounds(const RenderLayer* layer, const Render
{
if (!layer->isSelfPaintingLayer())
return IntRect();
-
+
LayoutRect boundingBoxRect = layer->localBoundingBox();
+ if (layer->renderer()->isBox())
+ layer->renderBox()->flipForWritingMode(boundingBoxRect);
+ else
+ layer->renderer()->containingBlock()->flipForWritingMode(boundingBoxRect);
+
if (layer->renderer()->isRoot()) {
// If the root layer becomes composited (e.g. because some descendant with negative z-index is composited),
// then it has to be big enough to cover the viewport in order to display the background. This is akin
diff --git a/Source/WebCore/rendering/RenderLayer.h b/Source/WebCore/rendering/RenderLayer.h
index 9b34e7f66..860a37290 100644
--- a/Source/WebCore/rendering/RenderLayer.h
+++ b/Source/WebCore/rendering/RenderLayer.h
@@ -369,7 +369,6 @@ public:
void updateTransform();
- void relativePositionOffset(LayoutUnit& relX, LayoutUnit& relY) const { relX += m_relativeOffset.width(); relY += m_relativeOffset.height(); }
const LayoutSize& relativePositionOffset() const { return m_relativeOffset; }
void clearClipRectsIncludingDescendants();
@@ -394,6 +393,8 @@ public:
return m_posZOrderList;
}
+ bool hasNegativeZOrderList() const { return negZOrderList() && negZOrderList()->size(); }
+
Vector<RenderLayer*>* negZOrderList() const
{
ASSERT(!m_zOrderListsDirty);
@@ -511,7 +512,7 @@ public:
// Return a cached repaint rect, computed relative to the layer renderer's containerForRepaint.
LayoutRect repaintRect() const { return m_repaintRect; }
- LayoutRect repaintRectIncludingDescendants() const;
+ LayoutRect repaintRectIncludingNonCompositingDescendants() const;
enum UpdateLayerPositionsAfterScrollFlag {
NoFlag = 0,
@@ -635,7 +636,7 @@ private:
void updateScrollbarsAfterLayout();
friend IntSize RenderBox::scrolledContentOffset() const;
- IntSize scrolledContentOffset() const { return scrollOffset() + m_scrollOverflow; }
+ IntSize scrolledContentOffset() const { return m_scrollOffset; }
// The normal operator new is disallowed on all render objects.
void* operator new(size_t) throw();
@@ -883,11 +884,9 @@ protected:
// The layer's width/height
IntSize m_layerSize;
- // Our scroll offsets if the view is scrolled.
+ // This is the (scroll) offset from scrollOrigin().
IntSize m_scrollOffset;
- IntSize m_scrollOverflow;
-
// The width/height of our scrolled area.
LayoutSize m_scrollSize;
diff --git a/Source/WebCore/rendering/RenderLayerBacking.cpp b/Source/WebCore/rendering/RenderLayerBacking.cpp
index 524aaf30a..ee39912a9 100644
--- a/Source/WebCore/rendering/RenderLayerBacking.cpp
+++ b/Source/WebCore/rendering/RenderLayerBacking.cpp
@@ -54,6 +54,8 @@
#include "StyleResolver.h"
#include "TiledBacking.h"
+#include <wtf/CurrentTime.h>
+
#if ENABLE(CSS_FILTERS)
#include "FilterEffectRenderer.h"
#endif
@@ -323,6 +325,8 @@ bool RenderLayerBacking::updateGraphicsLayerConfiguration()
RenderLayerCompositor* compositor = this->compositor();
RenderObject* renderer = this->renderer();
+ m_owningLayer->updateZOrderLists();
+
bool layerConfigChanged = false;
if (updateForegroundLayer(compositor->needsContentsCompositingLayer(m_owningLayer)))
layerConfigChanged = true;
@@ -1206,6 +1210,9 @@ void RenderLayerBacking::paintContents(const GraphicsLayer* graphicsLayer, Graph
// We have to use the same root as for hit testing, because both methods can compute and cache clipRects.
paintIntoLayer(m_owningLayer, &context, dirtyRect, PaintBehaviorNormal, paintingPhase, renderer());
+ if (m_usingTiledCacheLayer)
+ m_owningLayer->renderer()->frame()->view()->setLastPaintTime(currentTime());
+
InspectorInstrumentation::didPaint(cookie);
} else if (graphicsLayer == layerForHorizontalScrollbar()) {
paintScrollbar(m_owningLayer->horizontalScrollbar(), context, clip);
diff --git a/Source/WebCore/rendering/RenderLayerCompositor.cpp b/Source/WebCore/rendering/RenderLayerCompositor.cpp
index fbed9ae9a..06c62c342 100644
--- a/Source/WebCore/rendering/RenderLayerCompositor.cpp
+++ b/Source/WebCore/rendering/RenderLayerCompositor.cpp
@@ -576,7 +576,7 @@ IntRect RenderLayerCompositor::calculateCompositedBounds(const RenderLayer* laye
{
if (!canBeComposited(layer))
return IntRect();
- return pixelSnappedIntRect(RenderLayer::calculateLayerBounds(layer, ancestorLayer));
+ return RenderLayer::calculateLayerBounds(layer, ancestorLayer);
}
void RenderLayerCompositor::layerWasAdded(RenderLayer* /*parent*/, RenderLayer* /*child*/)
@@ -1748,7 +1748,7 @@ bool RenderLayerCompositor::isRunningAcceleratedTransformAnimation(RenderObject*
// object.
bool RenderLayerCompositor::needsContentsCompositingLayer(const RenderLayer* layer) const
{
- return (layer->m_negZOrderList && layer->m_negZOrderList->size() > 0);
+ return layer->hasNegativeZOrderList();
}
bool RenderLayerCompositor::requiresScrollLayer(RootLayerAttachment attachment) const
@@ -1982,6 +1982,9 @@ void RenderLayerCompositor::updateOverflowControlsLayers()
#ifndef NDEBUG
m_layerForHorizontalScrollbar->setName("horizontal scrollbar");
#endif
+ #if PLATFORM(MAC) && USE(CA)
+ m_layerForHorizontalScrollbar->setAcceleratesDrawing(acceleratedDrawingEnabled());
+ #endif
m_overflowControlsHostLayer->addChild(m_layerForHorizontalScrollbar.get());
if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
@@ -2001,6 +2004,9 @@ void RenderLayerCompositor::updateOverflowControlsLayers()
#ifndef NDEBUG
m_layerForVerticalScrollbar->setName("vertical scrollbar");
#endif
+ #if PLATFORM(MAC) && USE(CA)
+ m_layerForVerticalScrollbar->setAcceleratesDrawing(acceleratedDrawingEnabled());
+ #endif
m_overflowControlsHostLayer->addChild(m_layerForVerticalScrollbar.get());
if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
@@ -2020,6 +2026,9 @@ void RenderLayerCompositor::updateOverflowControlsLayers()
#ifndef NDEBUG
m_layerForScrollCorner->setName("scroll corner");
#endif
+ #if PLATFORM(MAC) && USE(CA)
+ m_layerForScrollCorner->setAcceleratesDrawing(acceleratedDrawingEnabled());
+ #endif
m_overflowControlsHostLayer->addChild(m_layerForScrollCorner.get());
}
} else if (m_layerForScrollCorner) {
diff --git a/Source/WebCore/rendering/RenderObject.cpp b/Source/WebCore/rendering/RenderObject.cpp
index 13f62f431..8a3094443 100755
--- a/Source/WebCore/rendering/RenderObject.cpp
+++ b/Source/WebCore/rendering/RenderObject.cpp
@@ -56,6 +56,7 @@
#include "RenderRegion.h"
#include "RenderRuby.h"
#include "RenderRubyText.h"
+#include "RenderScrollbarPart.h"
#include "RenderTableCaption.h"
#include "RenderTableCell.h"
#include "RenderTableCol.h"
@@ -189,8 +190,8 @@ RenderObject* RenderObject::createObject(Node* node, RenderStyle* style)
case BOX:
case INLINE_BOX:
return new (arena) RenderDeprecatedFlexibleBox(node);
- case FLEXBOX:
- case INLINE_FLEXBOX:
+ case FLEX:
+ case INLINE_FLEX:
return new (arena) RenderFlexibleBox(node);
}
@@ -698,6 +699,8 @@ void RenderObject::setLayerNeedsFullRepaintForPositionedMovementLayout()
RenderBlock* RenderObject::containingBlock() const
{
RenderObject* o = parent();
+ if (!o && isRenderScrollbarPart())
+ o = toRenderScrollbarPart(this)->rendererOwningScrollbar();
if (!isText() && m_style->position() == FixedPosition) {
while (o && !o->isRenderView() && !(o->hasTransform() && o->isRenderBlock()))
o = o->parent();
diff --git a/Source/WebCore/rendering/RenderObject.h b/Source/WebCore/rendering/RenderObject.h
index 6af6e9a2f..9269df1a9 100644
--- a/Source/WebCore/rendering/RenderObject.h
+++ b/Source/WebCore/rendering/RenderObject.h
@@ -355,6 +355,7 @@ public:
virtual bool isRenderFlowThread() const { return false; }
virtual bool isRenderNamedFlowThread() const { return false; }
+ virtual bool isRenderScrollbarPart() const { return false; }
bool canHaveRegionStyle() const { return isRenderBlock() && !isAnonymous() && !isRenderFlowThread(); }
bool isRoot() const { return document()->documentElement() == m_node; }
@@ -840,7 +841,7 @@ public:
virtual bool isFlexingChildren() const { return false; }
virtual bool isStretchingChildren() const { return false; }
- // Virtual function helper for the new FlexibleBox Layout (display: -webkit-flexbox).
+ // Virtual function helper for the new FlexibleBox Layout (display: -webkit-flex).
virtual bool isFlexibleBox() const { return false; }
bool isFlexibleBoxIncludingDeprecated() const
diff --git a/Source/WebCore/rendering/RenderQuote.cpp b/Source/WebCore/rendering/RenderQuote.cpp
index 45e5991e7..c4dd0c9d8 100644
--- a/Source/WebCore/rendering/RenderQuote.cpp
+++ b/Source/WebCore/rendering/RenderQuote.cpp
@@ -250,7 +250,7 @@ PassRefPtr<StringImpl> RenderQuote::originalText() const
switch (m_type) {
case NO_OPEN_QUOTE:
case NO_CLOSE_QUOTE:
- return String("").impl();
+ return emptyString().impl();
case CLOSE_QUOTE:
if (index)
--index;
diff --git a/Source/WebCore/rendering/RenderScrollbar.cpp b/Source/WebCore/rendering/RenderScrollbar.cpp
index 68d4a3bee..f8e33c650 100644
--- a/Source/WebCore/rendering/RenderScrollbar.cpp
+++ b/Source/WebCore/rendering/RenderScrollbar.cpp
@@ -270,11 +270,9 @@ void RenderScrollbar::updateScrollbarPart(ScrollbarPart partType, bool destroy)
RenderScrollbarPart* partRenderer = m_parts.get(partType);
if (!partRenderer && needRenderer) {
partRenderer = new (owningRenderer()->renderArena()) RenderScrollbarPart(owningRenderer()->document(), this, partType);
- partRenderer->setParent(owningRenderer());
m_parts.set(partType, partRenderer);
} else if (partRenderer && !needRenderer) {
m_parts.remove(partType);
- partRenderer->setParent(0);
partRenderer->destroy();
partRenderer = 0;
}
diff --git a/Source/WebCore/rendering/RenderScrollbarPart.cpp b/Source/WebCore/rendering/RenderScrollbarPart.cpp
index 1a45be2de..0343ea21d 100644
--- a/Source/WebCore/rendering/RenderScrollbarPart.cpp
+++ b/Source/WebCore/rendering/RenderScrollbarPart.cpp
@@ -184,4 +184,11 @@ void RenderScrollbarPart::paintIntoRect(GraphicsContext* graphicsContext, const
paint(paintInfo, paintOffset);
}
+RenderObject* RenderScrollbarPart::rendererOwningScrollbar() const
+{
+ if (!m_scrollbar)
+ return 0;
+ return m_scrollbar->owningRenderer();
+}
+
}
diff --git a/Source/WebCore/rendering/RenderScrollbarPart.h b/Source/WebCore/rendering/RenderScrollbarPart.h
index f481f5a2c..8c7a871fc 100644
--- a/Source/WebCore/rendering/RenderScrollbarPart.h
+++ b/Source/WebCore/rendering/RenderScrollbarPart.h
@@ -35,8 +35,6 @@ class RenderScrollbar;
class RenderScrollbarPart : public RenderBlock {
public:
- friend class RenderScrollbar;
-
RenderScrollbarPart(Node*, RenderScrollbar* = 0, ScrollbarPart = NoPart);
virtual ~RenderScrollbarPart();
@@ -55,6 +53,9 @@ public:
virtual LayoutUnit marginLeft() const { ASSERT(isIntegerValue(m_marginLeft)); return m_marginLeft; }
virtual LayoutUnit marginRight() const { ASSERT(isIntegerValue(m_marginRight)); return m_marginRight; }
+ virtual bool isRenderScrollbarPart() const { return true; }
+ RenderObject* rendererOwningScrollbar() const;
+
protected:
virtual void styleWillChange(StyleDifference diff, const RenderStyle* newStyle);
virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
@@ -71,6 +72,21 @@ private:
ScrollbarPart m_part;
};
+inline RenderScrollbarPart* toRenderScrollbarPart(RenderObject* object)
+{
+ ASSERT(!object || object->isRenderScrollbarPart());
+ return static_cast<RenderScrollbarPart*>(object);
+}
+
+inline const RenderScrollbarPart* toRenderScrollbarPart(const RenderObject* object)
+{
+ ASSERT(!object || object->isRenderScrollbarPart());
+ return static_cast<const RenderScrollbarPart*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderScrollbarPart(const RenderScrollbarPart*);
+
} // namespace WebCore
#endif // RenderScrollbarPart_h
diff --git a/Source/WebCore/rendering/RenderTable.cpp b/Source/WebCore/rendering/RenderTable.cpp
index e7ada7044..28172ef94 100644
--- a/Source/WebCore/rendering/RenderTable.cpp
+++ b/Source/WebCore/rendering/RenderTable.cpp
@@ -456,7 +456,7 @@ void RenderTable::layout()
statePusher.pop();
if (view()->layoutState()->pageLogicalHeight())
- setPageLogicalOffset(view()->layoutState()->pageLogicalOffset(logicalTop()));
+ setPageLogicalOffset(view()->layoutState()->pageLogicalOffset(this, logicalTop()));
bool didFullRepaint = repainter.repaintAfterLayout();
// Repaint with our new bounds if they are different from our old bounds.
@@ -1215,18 +1215,41 @@ void RenderTable::updateFirstLetter()
{
}
-LayoutUnit RenderTable::firstLineBoxBaseline() const
+enum LineBox { FirstLineBox, LastLineBox };
+
+static LayoutUnit getLineBoxBaseline(const RenderTable* table, LineBox lineBox)
{
- if (isWritingModeRoot())
+ if (table->isWritingModeRoot())
return -1;
- recalcSectionsIfNeeded();
+ table->recalcSectionsIfNeeded();
- const RenderTableSection* topNonEmptySection = this->topNonEmptySection();
+ const RenderTableSection* topNonEmptySection = table->topNonEmptySection();
if (!topNonEmptySection)
return -1;
- return topNonEmptySection->logicalTop() + topNonEmptySection->firstLineBoxBaseline();
+ LayoutUnit baseline = topNonEmptySection->firstLineBoxBaseline();
+ 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.
+ 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)
diff --git a/Source/WebCore/rendering/RenderTable.h b/Source/WebCore/rendering/RenderTable.h
index b61c95dc1..1396eeb57 100644
--- a/Source/WebCore/rendering/RenderTable.h
+++ b/Source/WebCore/rendering/RenderTable.h
@@ -237,7 +237,8 @@ private:
virtual void computePreferredLogicalWidths();
virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const LayoutPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction);
- virtual LayoutUnit firstLineBoxBaseline() const;
+ virtual LayoutUnit firstLineBoxBaseline() const OVERRIDE;
+ virtual LayoutUnit lastLineBoxBaseline() const OVERRIDE;
virtual RenderBlock* firstLineBlock() const;
virtual void updateFirstLetter();
diff --git a/Source/WebCore/rendering/RenderTableCell.cpp b/Source/WebCore/rendering/RenderTableCell.cpp
index ec33a7c9f..fb0fe9200 100644
--- a/Source/WebCore/rendering/RenderTableCell.cpp
+++ b/Source/WebCore/rendering/RenderTableCell.cpp
@@ -186,6 +186,7 @@ void RenderTableCell::updateLogicalWidth(LayoutUnit w)
void RenderTableCell::layout()
{
+ updateFirstLetter();
layoutBlock(cellWidthChanged());
setCellWidthChanged(false);
}
@@ -604,7 +605,7 @@ CollapsedBorderValue RenderTableCell::computeCollapsedBeforeBorder(IncludeBorder
return result;
// (6) Previous row group's after border.
- currSection = table->sectionAbove(currSection);
+ currSection = table->sectionAbove(currSection, SkipEmptySections);
if (currSection) {
result = chooseBorder(CollapsedBorderValue(currSection->style()->borderAfter(), includeColor ? currSection->style()->visitedDependentColor(afterColorProperty) : Color(), BROWGROUP), result);
if (!result.exists())
@@ -682,7 +683,7 @@ CollapsedBorderValue RenderTableCell::computeCollapsedAfterBorder(IncludeBorderC
return result;
// (6) Following row group's before border.
- currSection = table->sectionBelow(currSection);
+ currSection = table->sectionBelow(currSection, SkipEmptySections);
if (currSection) {
result = chooseBorder(result, CollapsedBorderValue(currSection->style()->borderBefore(), includeColor ? currSection->style()->visitedDependentColor(beforeColorProperty) : Color(), BROWGROUP));
if (!result.exists())
diff --git a/Source/WebCore/rendering/RenderTableRow.cpp b/Source/WebCore/rendering/RenderTableRow.cpp
index d9889008b..3caa7b4f3 100644
--- a/Source/WebCore/rendering/RenderTableRow.cpp
+++ b/Source/WebCore/rendering/RenderTableRow.cpp
@@ -148,7 +148,7 @@ void RenderTableRow::layout()
for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
if (child->isTableCell()) {
RenderTableCell* cell = toRenderTableCell(child);
- if (!cell->needsLayout() && paginated && view()->layoutState()->pageLogicalHeight() && view()->layoutState()->pageLogicalOffset(cell->logicalTop()) != cell->pageLogicalOffset())
+ if (!cell->needsLayout() && paginated && view()->layoutState()->pageLogicalHeight() && view()->layoutState()->pageLogicalOffset(cell, cell->logicalTop()) != cell->pageLogicalOffset())
cell->setChildNeedsLayout(true, MarkOnlyThis);
if (child->needsLayout()) {
diff --git a/Source/WebCore/rendering/RenderTableSection.cpp b/Source/WebCore/rendering/RenderTableSection.cpp
index a6f544ab5..7f44a75a0 100644
--- a/Source/WebCore/rendering/RenderTableSection.cpp
+++ b/Source/WebCore/rendering/RenderTableSection.cpp
@@ -370,7 +370,7 @@ int RenderTableSection::calcRowLogicalHeight()
// find out the baseline
EVerticalAlign va = cell->style()->verticalAlign();
- if (va == BASELINE || va == TEXT_BOTTOM || va == TEXT_TOP || va == SUPER || va == SUB) {
+ if (va == BASELINE || va == TEXT_BOTTOM || va == TEXT_TOP || va == SUPER || va == SUB || va == LENGTH) {
LayoutUnit baselinePosition = cell->cellBaselinePosition();
if (baselinePosition > cell->borderBefore() + cell->paddingBefore()) {
m_grid[r].baseline = max(m_grid[r].baseline, baselinePosition - cell->intrinsicPaddingBefore());
@@ -609,7 +609,7 @@ void RenderTableSection::layoutRows()
// If the baseline moved, we may have to update the data for our row. Find out the new baseline.
EVerticalAlign va = cell->style()->verticalAlign();
- if (va == BASELINE || va == TEXT_BOTTOM || va == TEXT_TOP || va == SUPER || va == SUB) {
+ if (va == BASELINE || va == TEXT_BOTTOM || va == TEXT_TOP || va == SUPER || va == SUB || va == LENGTH) {
LayoutUnit baseline = cell->cellBaselinePosition();
if (baseline > cell->borderBefore() + cell->paddingBefore())
m_grid[r].baseline = max(m_grid[r].baseline, baseline);
@@ -618,7 +618,7 @@ void RenderTableSection::layoutRows()
int oldIntrinsicPaddingBefore = cell->intrinsicPaddingBefore();
int oldIntrinsicPaddingAfter = cell->intrinsicPaddingAfter();
- int logicalHeightWithoutIntrinsicPadding = cell->logicalHeight() - oldIntrinsicPaddingBefore - oldIntrinsicPaddingAfter;
+ int logicalHeightWithoutIntrinsicPadding = cell->pixelSnappedLogicalHeight() - oldIntrinsicPaddingBefore - oldIntrinsicPaddingAfter;
int intrinsicPaddingBefore = 0;
switch (cell->style()->verticalAlign()) {
@@ -626,6 +626,7 @@ void RenderTableSection::layoutRows()
case SUPER:
case TEXT_TOP:
case TEXT_BOTTOM:
+ case LENGTH:
case BASELINE: {
LayoutUnit b = cell->cellBaselinePosition();
if (b > cell->borderBefore() + cell->paddingBefore())
@@ -661,7 +662,7 @@ void RenderTableSection::layoutRows()
if (intrinsicPaddingBefore != oldIntrinsicPaddingBefore || intrinsicPaddingAfter != oldIntrinsicPaddingAfter)
cell->setNeedsLayout(true, MarkOnlyThis);
- if (!cell->needsLayout() && view()->layoutState()->pageLogicalHeight() && view()->layoutState()->pageLogicalOffset(cell->logicalTop()) != cell->pageLogicalOffset())
+ if (!cell->needsLayout() && view()->layoutState()->pageLogicalHeight() && view()->layoutState()->pageLogicalOffset(cell, cell->logicalTop()) != cell->pageLogicalOffset())
cell->setChildNeedsLayout(true, MarkOnlyThis);
cell->layoutIfNeeded();
@@ -949,7 +950,8 @@ LayoutUnit RenderTableSection::firstLineBoxBaseline() const
for (size_t i = 0; i < firstRow.size(); ++i) {
const CellStruct& cs = firstRow.at(i);
const RenderTableCell* cell = cs.primaryCell();
- if (cell)
+ // Only cells with content have a baseline
+ if (cell && cell->contentLogicalHeight())
firstLineBaseline = max(firstLineBaseline, cell->logicalTop() + cell->paddingBefore() + cell->borderBefore() + cell->contentLogicalHeight());
}
diff --git a/Source/WebCore/rendering/RenderTextControl.cpp b/Source/WebCore/rendering/RenderTextControl.cpp
index ddc647570..8b138352e 100644
--- a/Source/WebCore/rendering/RenderTextControl.cpp
+++ b/Source/WebCore/rendering/RenderTextControl.cpp
@@ -208,6 +208,9 @@ bool RenderTextControl::hasValidAvgCharWidth(AtomicString family)
{
static HashSet<AtomicString>* fontFamiliesWithInvalidCharWidthMap = 0;
+ if (family.isEmpty())
+ return false;
+
if (!fontFamiliesWithInvalidCharWidthMap) {
fontFamiliesWithInvalidCharWidthMap = new HashSet<AtomicString>;
diff --git a/Source/WebCore/rendering/RenderThemeMac.h b/Source/WebCore/rendering/RenderThemeMac.h
index 22a614a0c..ebbb2352c 100644
--- a/Source/WebCore/rendering/RenderThemeMac.h
+++ b/Source/WebCore/rendering/RenderThemeMac.h
@@ -219,7 +219,7 @@ private:
NSMenu* searchMenuTemplate() const;
NSSliderCell* sliderThumbHorizontal() const;
NSSliderCell* sliderThumbVertical() const;
- NSTextFieldCell* textField(bool useNewGradient) const;
+ NSTextFieldCell* textField() const;
#if ENABLE(METER_TAG)
NSLevelIndicatorStyle levelIndicatorStyleFor(ControlPart) const;
diff --git a/Source/WebCore/rendering/RenderThemeMac.mm b/Source/WebCore/rendering/RenderThemeMac.mm
index 5e2d26738..28096e670 100644
--- a/Source/WebCore/rendering/RenderThemeMac.mm
+++ b/Source/WebCore/rendering/RenderThemeMac.mm
@@ -734,18 +734,22 @@ bool RenderThemeMac::paintTextField(RenderObject* o, const PaintInfo& paintInfo,
{
LocalCurrentGraphicsContext localContext(paintInfo.context);
- bool useNewGradient = true;
#if defined(BUILDING_ON_LION) || defined(BUILDING_ON_SNOW_LEOPARD)
- // See comment in RenderThemeMac::textField() for a complete explanation of this.
- useNewGradient = WebCore::deviceScaleFactor(o->frame()) != 1;
- if (useNewGradient) {
- useNewGradient = o->style()->hasAppearance()
- && o->style()->visitedDependentColor(CSSPropertyBackgroundColor) == Color::white
- && !o->style()->hasBackgroundImage();
+ bool useNSTextFieldCell = o->style()->hasAppearance()
+ && o->style()->visitedDependentColor(CSSPropertyBackgroundColor) == Color::white
+ && !o->style()->hasBackgroundImage();
+
+ // We do not use NSTextFieldCell to draw styled text fields on Lion and SnowLeopard because
+ // there are a number of bugs on those platforms that require NSTextFieldCell to be in charge
+ // of painting its own background. We need WebCore to paint styled backgrounds, so we'll use
+ // this WebCoreSystemInterface function instead.
+ if (!useNSTextFieldCell) {
+ wkDrawBezeledTextFieldCell(r, isEnabled(o) && !isReadOnlyControl(o));
+ return false;
}
#endif
- NSTextFieldCell* textField = this->textField(useNewGradient);
+ NSTextFieldCell *textField = this->textField();
GraphicsContextStateSaver stateSaver(*paintInfo.context);
@@ -2164,7 +2168,7 @@ NSSliderCell* RenderThemeMac::sliderThumbVertical() const
return m_sliderThumbVertical.get();
}
-NSTextFieldCell* RenderThemeMac::textField(bool useNewGradient) const
+NSTextFieldCell* RenderThemeMac::textField() const
{
if (!m_textField) {
m_textField.adoptNS([[WebCoreTextFieldCell alloc] initTextCell:@""]);
@@ -2173,27 +2177,15 @@ NSTextFieldCell* RenderThemeMac::textField(bool useNewGradient) const
[m_textField.get() setFocusRingType:NSFocusRingTypeExterior];
#if defined(BUILDING_ON_LION) || defined(BUILDING_ON_SNOW_LEOPARD)
[m_textField.get() setDrawsBackground:YES];
+ [m_textField.get() setBackgroundColor:[NSColor whiteColor]];
#else
- UNUSED_PARAM(useNewGradient);
+ // Post-Lion, WebCore can be in charge of paintinng the background thanks to
+ // the workaround in place for <rdar://problem/11385461>, which is implemented
+ // above as _coreUIDrawOptionsWithFrame.
[m_textField.get() setDrawsBackground:NO];
#endif
}
-#if defined(BUILDING_ON_LION) || defined(BUILDING_ON_SNOW_LEOPARD)
- // This is a workaround for <rdar://problem/11385461> on Lion and SnowLeopard. Newer versions of the
- // OS can always use the newer version of the text field with the workaround above in
- // _coreUIDrawOptionsWithFrame. With this workaround for older OS's, when the deviceScaleFactor is 1,
- // we have an old-school gradient bezel in text fields whether they are styled or not. This is fine and
- // matches shipping Safari. When the deviceScaleFactor is greater than 1, text fields will have newer,
- // AppKit-matching gradients that look much more appropriate at the higher resolutions. However, if the
- // text field is styled in any way, we'll revert to the old-school bezel, which doesn't look great in
- // HiDPI, but it looks better than the CSS border, which is the only alternative until 11385461 is resolved.
- if (useNewGradient)
- [m_textField.get() setBackgroundColor:[NSColor whiteColor]];
- else
- [m_textField.get() setBackgroundColor:[NSColor clearColor]];
-#endif
-
return m_textField.get();
}
diff --git a/Source/WebCore/rendering/RenderView.cpp b/Source/WebCore/rendering/RenderView.cpp
index 4a3a2bc83..43ac53039 100644
--- a/Source/WebCore/rendering/RenderView.cpp
+++ b/Source/WebCore/rendering/RenderView.cpp
@@ -400,7 +400,7 @@ IntRect RenderView::selectionBounds(bool clipToVisibleContent) const
{
document()->updateStyleIfNeeded();
- typedef HashMap<RenderObject*, RenderSelectionInfo*> SelectionMap;
+ typedef HashMap<RenderObject*, OwnPtr<RenderSelectionInfo> > SelectionMap;
SelectionMap selectedObjects;
RenderObject* os = m_selectionStart;
@@ -408,13 +408,13 @@ IntRect RenderView::selectionBounds(bool clipToVisibleContent) const
while (os && os != stop) {
if ((os->canBeSelectionLeaf() || os == m_selectionStart || os == m_selectionEnd) && os->selectionState() != SelectionNone) {
// Blocks are responsible for painting line gaps and margin gaps. They must be examined as well.
- selectedObjects.set(os, new RenderSelectionInfo(os, clipToVisibleContent));
+ selectedObjects.set(os, adoptPtr(new RenderSelectionInfo(os, clipToVisibleContent)));
RenderBlock* cb = os->containingBlock();
while (cb && !cb->isRenderView()) {
- RenderSelectionInfo* blockInfo = selectedObjects.get(cb);
+ OwnPtr<RenderSelectionInfo>& blockInfo = selectedObjects.add(cb, nullptr).iterator->second;
if (blockInfo)
break;
- selectedObjects.set(cb, new RenderSelectionInfo(cb, clipToVisibleContent));
+ blockInfo = adoptPtr(new RenderSelectionInfo(cb, clipToVisibleContent));
cb = cb->containingBlock();
}
}
@@ -426,7 +426,7 @@ IntRect RenderView::selectionBounds(bool clipToVisibleContent) const
LayoutRect selRect;
SelectionMap::iterator end = selectedObjects.end();
for (SelectionMap::iterator i = selectedObjects.begin(); i != end; ++i) {
- RenderSelectionInfo* info = i->second;
+ RenderSelectionInfo* info = i->second.get();
// RenderSelectionInfo::rect() is in the coordinates of the repaintContainer, so map to page coordinates.
LayoutRect currRect = info->rect();
if (RenderBoxModelObject* repaintContainer = info->repaintContainer()) {
@@ -434,7 +434,6 @@ IntRect RenderView::selectionBounds(bool clipToVisibleContent) const
currRect = absQuad.enclosingBoundingBox();
}
selRect.unite(currRect);
- delete info;
}
return pixelSnappedIntRect(selRect);
}
@@ -472,14 +471,14 @@ void RenderView::setSelection(RenderObject* start, int startPos, RenderObject* e
int oldEndPos = m_selectionEndPos;
// Objects each have a single selection rect to examine.
- typedef HashMap<RenderObject*, RenderSelectionInfo*> SelectedObjectMap;
+ typedef HashMap<RenderObject*, OwnPtr<RenderSelectionInfo> > SelectedObjectMap;
SelectedObjectMap oldSelectedObjects;
SelectedObjectMap newSelectedObjects;
// Blocks contain selected objects and fill gaps between them, either on the left, right, or in between lines and blocks.
// In order to get the repaint rect right, we have to examine left, middle, and right rects individually, since otherwise
// the union of those rects might remain the same even when changes have occurred.
- typedef HashMap<RenderBlock*, RenderBlockSelectionInfo*> SelectedBlockMap;
+ typedef HashMap<RenderBlock*, OwnPtr<RenderBlockSelectionInfo> > SelectedBlockMap;
SelectedBlockMap oldSelectedBlocks;
SelectedBlockMap newSelectedBlocks;
@@ -488,14 +487,14 @@ void RenderView::setSelection(RenderObject* start, int startPos, RenderObject* e
while (os && os != stop) {
if ((os->canBeSelectionLeaf() || os == m_selectionStart || os == m_selectionEnd) && os->selectionState() != SelectionNone) {
// Blocks are responsible for painting line gaps and margin gaps. They must be examined as well.
- oldSelectedObjects.set(os, new RenderSelectionInfo(os, true));
+ oldSelectedObjects.set(os, adoptPtr(new RenderSelectionInfo(os, true)));
if (blockRepaintMode == RepaintNewXOROld) {
RenderBlock* cb = os->containingBlock();
while (cb && !cb->isRenderView()) {
- RenderBlockSelectionInfo* blockInfo = oldSelectedBlocks.get(cb);
+ OwnPtr<RenderBlockSelectionInfo>& blockInfo = oldSelectedBlocks.add(cb, nullptr).iterator->second;
if (blockInfo)
break;
- oldSelectedBlocks.set(cb, new RenderBlockSelectionInfo(cb));
+ blockInfo = adoptPtr(new RenderBlockSelectionInfo(cb));
cb = cb->containingBlock();
}
}
@@ -542,13 +541,13 @@ void RenderView::setSelection(RenderObject* start, int startPos, RenderObject* e
o = start;
while (o && o != stop) {
if ((o->canBeSelectionLeaf() || o == start || o == end) && o->selectionState() != SelectionNone) {
- newSelectedObjects.set(o, new RenderSelectionInfo(o, true));
+ newSelectedObjects.set(o, adoptPtr(new RenderSelectionInfo(o, true)));
RenderBlock* cb = o->containingBlock();
while (cb && !cb->isRenderView()) {
- RenderBlockSelectionInfo* blockInfo = newSelectedBlocks.get(cb);
+ OwnPtr<RenderBlockSelectionInfo>& blockInfo = newSelectedBlocks.add(cb, nullptr).iterator->second;
if (blockInfo)
break;
- newSelectedBlocks.set(cb, new RenderBlockSelectionInfo(cb));
+ blockInfo = adoptPtr(new RenderBlockSelectionInfo(cb));
cb = cb->containingBlock();
}
}
@@ -556,15 +555,8 @@ void RenderView::setSelection(RenderObject* start, int startPos, RenderObject* e
o = o->nextInPreOrder();
}
- if (!m_frameView || blockRepaintMode == RepaintNothing) {
- // We built the maps, but we aren't going to use them.
- // We need to delete the values, otherwise they'll all leak!
- deleteAllValues(oldSelectedObjects);
- deleteAllValues(newSelectedObjects);
- deleteAllValues(oldSelectedBlocks);
- deleteAllValues(newSelectedBlocks);
+ if (!m_frameView || blockRepaintMode == RepaintNothing)
return;
- }
m_frameView->beginDeferredRepaints();
@@ -572,7 +564,7 @@ void RenderView::setSelection(RenderObject* start, int startPos, RenderObject* e
for (SelectedObjectMap::iterator i = oldSelectedObjects.begin(); i != oldObjectsEnd; ++i) {
RenderObject* obj = i->first;
RenderSelectionInfo* newInfo = newSelectedObjects.get(obj);
- RenderSelectionInfo* oldInfo = i->second;
+ RenderSelectionInfo* oldInfo = i->second.get();
if (!newInfo || oldInfo->rect() != newInfo->rect() || oldInfo->state() != newInfo->state() ||
(m_selectionStart == obj && oldStartPos != m_selectionStartPos) ||
(m_selectionEnd == obj && oldEndPos != m_selectionEndPos)) {
@@ -580,44 +572,34 @@ void RenderView::setSelection(RenderObject* start, int startPos, RenderObject* e
if (newInfo) {
newInfo->repaint();
newSelectedObjects.remove(obj);
- delete newInfo;
}
}
- delete oldInfo;
}
// Any new objects that remain were not found in the old objects dict, and so they need to be updated.
SelectedObjectMap::iterator newObjectsEnd = newSelectedObjects.end();
- for (SelectedObjectMap::iterator i = newSelectedObjects.begin(); i != newObjectsEnd; ++i) {
- RenderSelectionInfo* newInfo = i->second;
- newInfo->repaint();
- delete newInfo;
- }
+ for (SelectedObjectMap::iterator i = newSelectedObjects.begin(); i != newObjectsEnd; ++i)
+ i->second->repaint();
// Have any of the old blocks changed?
SelectedBlockMap::iterator oldBlocksEnd = oldSelectedBlocks.end();
for (SelectedBlockMap::iterator i = oldSelectedBlocks.begin(); i != oldBlocksEnd; ++i) {
RenderBlock* block = i->first;
RenderBlockSelectionInfo* newInfo = newSelectedBlocks.get(block);
- RenderBlockSelectionInfo* oldInfo = i->second;
+ RenderBlockSelectionInfo* oldInfo = i->second.get();
if (!newInfo || oldInfo->rects() != newInfo->rects() || oldInfo->state() != newInfo->state()) {
oldInfo->repaint();
if (newInfo) {
newInfo->repaint();
newSelectedBlocks.remove(block);
- delete newInfo;
}
}
- delete oldInfo;
}
// Any new blocks that remain were not found in the old blocks dict, and so they need to be updated.
SelectedBlockMap::iterator newBlocksEnd = newSelectedBlocks.end();
- for (SelectedBlockMap::iterator i = newSelectedBlocks.begin(); i != newBlocksEnd; ++i) {
- RenderBlockSelectionInfo* newInfo = i->second;
- newInfo->repaint();
- delete newInfo;
- }
+ for (SelectedBlockMap::iterator i = newSelectedBlocks.begin(); i != newBlocksEnd; ++i)
+ i->second->repaint();
m_frameView->endDeferredRepaints();
}
diff --git a/Source/WebCore/rendering/RootInlineBox.cpp b/Source/WebCore/rendering/RootInlineBox.cpp
index 9b973b3b2..bcbe7bd89 100644
--- a/Source/WebCore/rendering/RootInlineBox.cpp
+++ b/Source/WebCore/rendering/RootInlineBox.cpp
@@ -708,7 +708,7 @@ LayoutRect RootInlineBox::paddedLayoutOverflowRect(LayoutUnit endPadding) const
return lineLayoutOverflow;
}
-static void setAscentAndDescent(LayoutUnit& ascent, LayoutUnit& descent, LayoutUnit newAscent, LayoutUnit newDescent, bool& ascentDescentSet)
+static void setAscentAndDescent(int& ascent, int& descent, int newAscent, int newDescent, bool& ascentDescentSet)
{
if (!ascentDescentSet) {
ascentDescentSet = true;
@@ -720,7 +720,7 @@ static void setAscentAndDescent(LayoutUnit& ascent, LayoutUnit& descent, LayoutU
}
}
-void RootInlineBox::ascentAndDescentForBox(InlineBox* box, GlyphOverflowAndFallbackFontsMap& textBoxDataMap, LayoutUnit& ascent, LayoutUnit& descent,
+void RootInlineBox::ascentAndDescentForBox(InlineBox* box, GlyphOverflowAndFallbackFontsMap& textBoxDataMap, int& ascent, int& descent,
bool& affectsAscent, bool& affectsDescent) const
{
bool ascentDescentSet = false;
@@ -757,11 +757,11 @@ void RootInlineBox::ascentAndDescentForBox(InlineBox* box, GlyphOverflowAndFallb
usedFonts->append(box->renderer()->style(isFirstLineStyle())->font().primaryFont());
for (size_t i = 0; i < usedFonts->size(); ++i) {
const FontMetrics& fontMetrics = usedFonts->at(i)->fontMetrics();
- LayoutUnit usedFontAscent = fontMetrics.ascent(baselineType());
- LayoutUnit usedFontDescent = fontMetrics.descent(baselineType());
- LayoutUnit halfLeading = (fontMetrics.lineSpacing() - fontMetrics.height()) / 2;
- LayoutUnit usedFontAscentAndLeading = usedFontAscent + halfLeading;
- LayoutUnit usedFontDescentAndLeading = fontMetrics.lineSpacing() - usedFontAscentAndLeading;
+ int usedFontAscent = fontMetrics.ascent(baselineType());
+ int usedFontDescent = fontMetrics.descent(baselineType());
+ int halfLeading = (fontMetrics.lineSpacing() - fontMetrics.height()) / 2;
+ int usedFontAscentAndLeading = usedFontAscent + halfLeading;
+ int usedFontDescentAndLeading = fontMetrics.lineSpacing() - usedFontAscentAndLeading;
if (includeFont) {
setAscentAndDescent(ascent, descent, usedFontAscent, usedFontDescent, ascentDescentSet);
setUsedFont = true;
@@ -779,8 +779,8 @@ void RootInlineBox::ascentAndDescentForBox(InlineBox* box, GlyphOverflowAndFallb
// If leading is included for the box, then we compute that box.
if (includeLeading && !setUsedFontWithLeading) {
- LayoutUnit ascentWithLeading = box->baselinePosition(baselineType());
- LayoutUnit descentWithLeading = box->lineHeight() - ascentWithLeading;
+ int ascentWithLeading = box->baselinePosition(baselineType());
+ int descentWithLeading = box->lineHeight() - ascentWithLeading;
setAscentAndDescent(ascent, descent, ascentWithLeading, descentWithLeading, ascentDescentSet);
// Examine the font box for inline flows and text boxes to see if any part of it is above the baseline.
@@ -792,8 +792,8 @@ void RootInlineBox::ascentAndDescentForBox(InlineBox* box, GlyphOverflowAndFallb
}
if (includeFontForBox(box) && !setUsedFont) {
- LayoutUnit fontAscent = box->renderer()->style(isFirstLineStyle())->fontMetrics().ascent();
- LayoutUnit fontDescent = box->renderer()->style(isFirstLineStyle())->fontMetrics().descent();
+ int fontAscent = box->renderer()->style(isFirstLineStyle())->fontMetrics().ascent();
+ int fontDescent = box->renderer()->style(isFirstLineStyle())->fontMetrics().descent();
setAscentAndDescent(ascent, descent, fontAscent, fontDescent, ascentDescentSet);
affectsAscent = fontAscent - box->logicalTop() > 0;
affectsDescent = fontDescent + box->logicalTop() > 0;
diff --git a/Source/WebCore/rendering/RootInlineBox.h b/Source/WebCore/rendering/RootInlineBox.h
index 49aed00da..2edbddb2c 100644
--- a/Source/WebCore/rendering/RootInlineBox.h
+++ b/Source/WebCore/rendering/RootInlineBox.h
@@ -151,7 +151,7 @@ public:
LayoutRect paddedLayoutOverflowRect(LayoutUnit endPadding) const;
- void ascentAndDescentForBox(InlineBox*, GlyphOverflowAndFallbackFontsMap&, LayoutUnit& ascent, LayoutUnit& descent, bool& affectsAscent, bool& affectsDescent) const;
+ void ascentAndDescentForBox(InlineBox*, GlyphOverflowAndFallbackFontsMap&, int& ascent, int& descent, bool& affectsAscent, bool& affectsDescent) const;
LayoutUnit verticalPositionForBox(InlineBox*, VerticalPositionCache&);
bool includeLeadingForBox(InlineBox*) const;
bool includeFontForBox(InlineBox*) const;
diff --git a/Source/WebCore/rendering/mathml/RenderMathMLFenced.cpp b/Source/WebCore/rendering/mathml/RenderMathMLFenced.cpp
index 4297dd7ff..351f99e84 100644
--- a/Source/WebCore/rendering/mathml/RenderMathMLFenced.cpp
+++ b/Source/WebCore/rendering/mathml/RenderMathMLFenced.cpp
@@ -48,6 +48,7 @@ RenderMathMLFenced::RenderMathMLFenced(Element* element)
: RenderMathMLRow(element)
, m_open(OpeningBraceChar)
, m_close(ClosingBraceChar)
+ , m_closeFenceRenderer(0)
{
}
@@ -94,49 +95,67 @@ void RenderMathMLFenced::makeFences()
RenderObject* openFence = new (renderArena()) RenderMathMLOperator(node(), m_open);
openFence->setStyle(createOperatorStyle());
RenderBlock::addChild(openFence, firstChild());
- RenderObject* closeFence = new (renderArena()) RenderMathMLOperator(node(), m_close);
- closeFence->setStyle(createOperatorStyle());
- RenderBlock::addChild(closeFence);
+ m_closeFenceRenderer = new (renderArena()) RenderMathMLOperator(node(), m_close);
+ m_closeFenceRenderer->setStyle(createOperatorStyle());
+ RenderBlock::addChild(m_closeFenceRenderer);
}
-void RenderMathMLFenced::addChild(RenderObject* child, RenderObject*)
+void RenderMathMLFenced::addChild(RenderObject* child, RenderObject* beforeChild)
{
// make the fences if the render object is empty
if (isEmpty())
updateFromElement();
+ // FIXME: Adding or removing a child should possibly cause all later separators to shift places if they're different,
+ // as later child positions change by +1 or -1.
+
+ RenderObject* separatorRenderer = 0;
if (m_separators.get()) {
unsigned int count = 0;
for (Node* position = child->node(); position; position = position->previousSibling()) {
- if (position->nodeType() == Node::ELEMENT_NODE)
+ if (position->isElementNode())
count++;
}
-
- if (count > 1) {
+ if (!beforeChild) {
+ // We're adding at the end (before the closing fence), so a new separator would go before the new child, not after it.
+ --count;
+ }
+ // |count| is now the number of element children that will be before our new separator, i.e. it's the 1-based index of the separator.
+
+ if (count > 0) {
UChar separator;
// Use the last separator if we've run out of specified separators.
- if ((count - 1) >= m_separators.get()->length())
+ if (count > m_separators.get()->length())
separator = (*m_separators.get())[m_separators.get()->length() - 1];
else
- separator = (*m_separators.get())[count - 2];
+ separator = (*m_separators.get())[count - 1];
- RenderObject* separatorObj = new (renderArena()) RenderMathMLOperator(node(), separator);
- separatorObj->setStyle(createOperatorStyle());
- RenderBlock::addChild(separatorObj, lastChild());
+ separatorRenderer = new (renderArena()) RenderMathMLOperator(node(), separator);
+ separatorRenderer->setStyle(createOperatorStyle());
}
}
// If we have a block, we'll wrap it in an inline-block.
if (child->isBlockFlow() && child->style()->display() != INLINE_BLOCK) {
// Block objects wrapper.
-
RenderBlock* block = createAlmostAnonymousBlock(INLINE_BLOCK);
- RenderBlock::addChild(block, lastChild());
- block->addChild(child);
- } else
- RenderBlock::addChild(child, lastChild());
+ block->addChild(child);
+ child = block;
+ }
+
+ if (beforeChild) {
+ // Adding |x| before an existing |y| e.g. in element (y) - first insert our new child |x|, then its separator, to get (x, y).
+ RenderBlock::addChild(child, beforeChild);
+ if (separatorRenderer)
+ RenderBlock::addChild(separatorRenderer, beforeChild);
+ } else {
+ // Adding |y| at the end of an existing element e.g. (x) - insert the separator first before the closing fence, then |y|, to get (x, y).
+ if (separatorRenderer)
+ RenderBlock::addChild(separatorRenderer, m_closeFenceRenderer);
+ RenderBlock::addChild(child, m_closeFenceRenderer);
+ }
}
}
diff --git a/Source/WebCore/rendering/mathml/RenderMathMLFenced.h b/Source/WebCore/rendering/mathml/RenderMathMLFenced.h
index b2bca9971..75324dcdc 100644
--- a/Source/WebCore/rendering/mathml/RenderMathMLFenced.h
+++ b/Source/WebCore/rendering/mathml/RenderMathMLFenced.h
@@ -47,6 +47,8 @@ private:
UChar m_open;
UChar m_close;
RefPtr<StringImpl> m_separators;
+
+ RenderObject* m_closeFenceRenderer;
};
}
diff --git a/Source/WebCore/rendering/mathml/RenderMathMLRoot.cpp b/Source/WebCore/rendering/mathml/RenderMathMLRoot.cpp
index e6d5165a9..efeed1a1f 100644
--- a/Source/WebCore/rendering/mathml/RenderMathMLRoot.cpp
+++ b/Source/WebCore/rendering/mathml/RenderMathMLRoot.cpp
@@ -31,15 +31,12 @@
#include "RenderMathMLRoot.h"
#include "GraphicsContext.h"
-#include "MathMLNames.h"
#include "PaintInfo.h"
using namespace std;
namespace WebCore {
-using namespace MathMLNames;
-
// FIXME: This whole file should be changed to work with various writing modes. See https://bugs.webkit.org/show_bug.cgi?id=48951.
// Threshold above which the radical shape is modified to look nice with big bases (em)
@@ -54,8 +51,10 @@ const float gRadicalBottomPointXFront = 0.5f;
const int gRadicalBottomPointLower = 3;
// Horizontal position of the top left point of the radical "dip" (* frontWidth)
const float gRadicalDipLeftPointXFront = 0.8f;
-// Vertical position of the top left point of the radical "dip" (* baseHeight)
-const float gRadicalDipLeftPointYPos = 0.625f;
+// Vertical position of the top left point of a sqrt radical "dip" (* baseHeight)
+const float gSqrtRadicalDipLeftPointYPos = 0.5f;
+// Vertical position of the top left point of an nth root radical "dip" (* baseHeight)
+const float gRootRadicalDipLeftPointYPos = 0.625f;
// Vertical shift of the left end point of the radical (em)
const float gRadicalLeftEndYShiftEms = 0.05f;
// Additional bottom root padding if baseHeight > threshold (em)
@@ -81,6 +80,65 @@ RenderBoxModelObject* RenderMathMLRoot::index() const
return toRenderBoxModelObject(index);
}
+void RenderMathMLRoot::computePreferredLogicalWidths()
+{
+ ASSERT(preferredLogicalWidthsDirty() && needsLayout());
+
+ computeChildrenPreferredLogicalHeights();
+
+ int baseHeight = firstChild() ? roundToInt(preferredLogicalHeightAfterSizing(firstChild())) : 0;
+
+ int frontWidth = lroundf(gFrontWidthEms * style()->fontSize());
+
+ // Base height above which the shape of the root changes
+ float thresholdHeight = gThresholdBaseHeightEms * style()->fontSize();
+ if (baseHeight > thresholdHeight && thresholdHeight) {
+ float shift = min<float>((baseHeight - thresholdHeight) / thresholdHeight, 1.0f);
+ m_overbarLeftPointShift = static_cast<int>(shift * gRadicalBottomPointXFront * frontWidth);
+ m_intrinsicPaddingAfter = lroundf(gBigRootBottomPaddingEms * style()->fontSize());
+ } else {
+ m_overbarLeftPointShift = 0;
+ m_intrinsicPaddingAfter = 0;
+ }
+
+ int rootPad = lroundf(gSpaceAboveEms * style()->fontSize());
+ m_intrinsicPaddingBefore = rootPad;
+ m_indexTop = 0;
+ if (RenderBoxModelObject* index = this->index()) {
+ m_intrinsicPaddingStart = roundToInt(index->maxPreferredLogicalWidth()) + m_overbarLeftPointShift;
+
+ int indexHeight = roundToInt(preferredLogicalHeightAfterSizing(index));
+ int partDipHeight = lroundf((1 - gRootRadicalDipLeftPointYPos) * baseHeight);
+ int rootExtraTop = partDipHeight + indexHeight - (baseHeight + rootPad);
+ if (rootExtraTop > 0)
+ m_intrinsicPaddingBefore += rootExtraTop;
+ else
+ m_indexTop = - rootExtraTop;
+ } else
+ m_intrinsicPaddingStart = frontWidth;
+
+ RenderMathMLBlock::computePreferredLogicalWidths();
+
+ // Shrink our logical width to its probable value now without triggering unnecessary relayout of our children.
+ ASSERT(needsLayout() && logicalWidth() >= maxPreferredLogicalWidth());
+ setLogicalWidth(maxPreferredLogicalWidth());
+}
+
+void RenderMathMLRoot::layout()
+{
+ // Our computePreferredLogicalWidths() may change our logical width and then layout our children, which
+ // RenderBlock::layout()'s relayoutChildren logic isn't expecting.
+ if (preferredLogicalWidthsDirty())
+ computePreferredLogicalWidths();
+
+ RenderMathMLBlock::layout();
+
+ RenderBoxModelObject* index = this->index();
+ // If |index|, it should be a RenderBlock here, unless the user has overriden its { position: absolute }.
+ if (index && index->isBox())
+ toRenderBox(index)->setLogicalTop(m_indexTop);
+}
+
void RenderMathMLRoot::paint(PaintInfo& info, const LayoutPoint& paintOffset)
{
RenderMathMLBlock::paint(info, paintOffset);
@@ -88,24 +146,21 @@ void RenderMathMLRoot::paint(PaintInfo& info, const LayoutPoint& paintOffset)
if (info.context->paintingDisabled())
return;
- if (!index())
- return;
+ IntPoint adjustedPaintOffset = roundedIntPoint(paintOffset + location() + contentBoxRect().location());
- IntPoint adjustedPaintOffset = roundedIntPoint(paintOffset + location() + computedCSSContentBoxRect().location());
+ int startX = adjustedPaintOffset.x();
+ int frontWidth = lroundf(gFrontWidthEms * style()->fontSize());
+ int overbarWidth = roundToInt(getBoxModelObjectWidth(firstChild())) + m_overbarLeftPointShift;
int baseHeight = roundToInt(getBoxModelObjectHeight(firstChild()));
+ int rootPad = lroundf(gSpaceAboveEms * style()->fontSize());
+ adjustedPaintOffset.setY(adjustedPaintOffset.y() - rootPad);
- int overbarWidth = roundToInt(getBoxModelObjectWidth(firstChild())) + m_overbarLeftPointShift;
- int indexWidth = index()->pixelSnappedOffsetWidth();
- int frontWidth = static_cast<int>(roundf(gFrontWidthEms * style()->fontSize()));
- int startX = adjustedPaintOffset.x() + indexWidth + m_overbarLeftPointShift;
-
- int rootPad = static_cast<int>(roundf(gSpaceAboveEms * style()->fontSize()));
- adjustedPaintOffset.setY(adjustedPaintOffset.y() + m_intrinsicPaddingBefore - rootPad);
+ float radicalDipLeftPointYPos = (index() ? gRootRadicalDipLeftPointYPos : gSqrtRadicalDipLeftPointYPos) * baseHeight;
FloatPoint overbarLeftPoint(startX - m_overbarLeftPointShift, adjustedPaintOffset.y());
FloatPoint bottomPoint(startX - gRadicalBottomPointXFront * frontWidth, adjustedPaintOffset.y() + baseHeight + gRadicalBottomPointLower);
- FloatPoint dipLeftPoint(startX - gRadicalDipLeftPointXFront * frontWidth, adjustedPaintOffset.y() + gRadicalDipLeftPointYPos * baseHeight);
+ FloatPoint dipLeftPoint(startX - gRadicalDipLeftPointXFront * frontWidth, adjustedPaintOffset.y() + radicalDipLeftPointYPos);
FloatPoint leftEnd(startX - frontWidth, dipLeftPoint.y() + gRadicalLeftEndYShiftEms * style()->fontSize());
GraphicsContextStateSaver stateSaver(*info.context);
@@ -153,46 +208,6 @@ void RenderMathMLRoot::paint(PaintInfo& info, const LayoutPoint& paintOffset)
info.context->strokePath(line);
}
-void RenderMathMLRoot::layout()
-{
- RenderBlock::layout();
-
- if (!index())
- return;
-
- int baseHeight = roundToInt(getBoxModelObjectHeight(firstChild()));
-
- // Base height above which the shape of the root changes
- float thresholdHeight = gThresholdBaseHeightEms * style()->fontSize();
- if (baseHeight > thresholdHeight && thresholdHeight) {
- float shift = min<float>((baseHeight - thresholdHeight) / thresholdHeight, 1.0f);
- int frontWidth = static_cast<int>(roundf(gFrontWidthEms * style()->fontSize()));
- m_overbarLeftPointShift = static_cast<int>(shift * gRadicalBottomPointXFront * frontWidth);
- m_intrinsicPaddingAfter = static_cast<int>(roundf(gBigRootBottomPaddingEms * style()->fontSize()));
- } else {
- m_overbarLeftPointShift = 0;
- m_intrinsicPaddingAfter = 0;
- }
-
- RenderBoxModelObject* index = this->index();
-
- m_intrinsicPaddingStart = index->pixelSnappedOffsetWidth() + m_overbarLeftPointShift;
-
- int rootPad = static_cast<int>(roundf(gSpaceAboveEms * style()->fontSize()));
- int partDipHeight = static_cast<int>(roundf((1 - gRadicalDipLeftPointYPos) * baseHeight));
- int rootExtraTop = partDipHeight + index->pixelSnappedOffsetHeight() - (baseHeight + rootPad);
- m_intrinsicPaddingBefore = rootPad + max(rootExtraTop, 0);
-
- setNeedsLayout(true, MarkOnlyThis);
- setPreferredLogicalWidthsDirty(true, MarkOnlyThis); // FIXME: Can this really be right?
- // FIXME: Preferred logical widths are currently wrong the first time through, relying on layout() to set m_intrinsicPaddingStart.
- RenderBlock::layout();
-
- // |index| should be a RenderBlock here, unless the user has overriden its { position: absolute }.
- if (rootExtraTop < 0 && index->isBox())
- toRenderBox(index)->setLogicalTop(-rootExtraTop);
-}
-
}
#endif // ENABLE(MATHML)
diff --git a/Source/WebCore/rendering/mathml/RenderMathMLRoot.h b/Source/WebCore/rendering/mathml/RenderMathMLRoot.h
index 65ec82dc7..cd5d6e6e2 100644
--- a/Source/WebCore/rendering/mathml/RenderMathMLRoot.h
+++ b/Source/WebCore/rendering/mathml/RenderMathMLRoot.h
@@ -32,7 +32,7 @@
namespace WebCore {
-// Render base^(1/index), using radical notation.
+// Render base^(1/index), or sqrt(base) via the derived class RenderMathMLSquareRoot, using radical notation.
class RenderMathMLRoot : public RenderMathMLBlock {
public:
RenderMathMLRoot(Element*);
@@ -45,10 +45,13 @@ protected:
private:
virtual const char* renderName() const { return "RenderMathMLRoot"; }
+ virtual void computePreferredLogicalWidths() OVERRIDE;
+
// This may return 0 for a non-MathML index (which won't occur in valid MathML).
RenderBoxModelObject* index() const;
int m_overbarLeftPointShift;
+ int m_indexTop;
};
}
diff --git a/Source/WebCore/rendering/mathml/RenderMathMLSquareRoot.cpp b/Source/WebCore/rendering/mathml/RenderMathMLSquareRoot.cpp
index 86975dbfb..b4b07a2cf 100644
--- a/Source/WebCore/rendering/mathml/RenderMathMLSquareRoot.cpp
+++ b/Source/WebCore/rendering/mathml/RenderMathMLSquareRoot.cpp
@@ -30,45 +30,12 @@
#include "RenderMathMLSquareRoot.h"
-#include "GraphicsContext.h"
-#include "MathMLNames.h"
-#include "PaintInfo.h"
#include "RenderMathMLRow.h"
-using namespace std;
-
namespace WebCore {
-using namespace MathMLNames;
-
-// FIXME: This whole file should be changed to work with various writing modes. See https://bugs.webkit.org/show_bug.cgi?id=48951.
-
-// Threshold above which the radical shape is modified to look nice with big bases (em)
-const float gThresholdBaseHeightEms = 1.5f;
-// Normal width of the front of the radical sign, before the base & overbar (em)
-const float gFrontWidthEms = 0.75f;
-// Gap between the base and overbar (em)
-const float gSpaceAboveEms = 0.2f;
-// Horizontal position of the bottom point of the radical (* frontWidth)
-const float gRadicalBottomPointXFront = 0.5f;
-// Lower the radical sign's bottom point (px)
-const int gRadicalBottomPointLower = 3;
-// Horizontal position of the top left point of the radical "dip" (* frontWidth)
-const float gRadicalDipLeftPointXFront = 0.8f;
-// Vertical position of the top left point of the radical "dip" (* baseHeight)
-const float gRadicalDipLeftPointYPos = 0.5f;
-// Vertical shift of the left end point of the radical (em)
-const float gRadicalLeftEndYShiftEms = 0.05f;
-// Additional bottom root padding if baseHeight > threshold (em)
-const float gBigRootBottomPaddingEms = 0.2f;
-
-// Radical line thickness (em)
-const float gRadicalLineThicknessEms = 0.02f;
-// Radical thick line thickness (em)
-const float gRadicalThickLineThicknessEms = 0.1f;
-
RenderMathMLSquareRoot::RenderMathMLSquareRoot(Element* element)
- : RenderMathMLBlock(element)
+ : RenderMathMLRoot(element)
{
}
@@ -77,7 +44,7 @@ void RenderMathMLSquareRoot::addChild(RenderObject* newChild, RenderObject* befo
if (!firstChild()) {
RenderMathMLRow* newMRow = RenderMathMLRow::createAnonymousWithParentRenderer(this);
- RenderMathMLBlock::addChild(newMRow);
+ RenderMathMLRoot::addChild(newMRow);
// newMRow->isAnonymousBlock() is false because newMRow's display is INLINE_BLOCK,
// so we don't need to worry about removeLeftoverAnonymousBlock().
@@ -88,106 +55,6 @@ void RenderMathMLSquareRoot::addChild(RenderObject* newChild, RenderObject* befo
firstChild()->addChild(newChild, beforeChild);
}
-void RenderMathMLSquareRoot::computePreferredLogicalWidths()
-{
- m_intrinsicPaddingStart = static_cast<int>(roundf(gFrontWidthEms * style()->fontSize()));
-
- RenderMathMLBlock::computePreferredLogicalWidths();
-}
-
-void RenderMathMLSquareRoot::computeLogicalHeight()
-{
- int baseHeight = roundToInt(getBoxModelObjectHeight(firstChild()));
- float thresholdHeight = gThresholdBaseHeightEms * style()->fontSize();
- m_intrinsicPaddingAfter = baseHeight > thresholdHeight ? static_cast<int>(roundf(gBigRootBottomPaddingEms * style()->fontSize())) : 0;
- setLogicalHeight(baseHeight + borderAndPaddingLogicalHeight());
-
- RenderMathMLBlock::computeLogicalHeight();
-}
-
-void RenderMathMLSquareRoot::layout()
-{
- m_intrinsicPaddingBefore = static_cast<int>(roundf(gSpaceAboveEms * style()->fontSize()));
-
- RenderMathMLBlock::layout();
-}
-
-void RenderMathMLSquareRoot::paint(PaintInfo& info, const LayoutPoint& paintOffset)
-{
- RenderMathMLBlock::paint(info, paintOffset);
-
- if (info.context->paintingDisabled())
- return;
-
- IntPoint adjustedPaintOffset = roundedIntPoint(paintOffset + location() + computedCSSContentBoxRect().location());
-
- int baseHeight = roundToInt(getBoxModelObjectHeight(firstChild()));
- int overbarWidth = roundToInt(getBoxModelObjectWidth(firstChild()));
-
- int frontWidth = m_intrinsicPaddingStart;
- int overbarLeftPointShift = 0;
- // Base height above which the shape of the root changes
- float thresholdHeight = gThresholdBaseHeightEms * style()->fontSize();
-
- if (baseHeight > thresholdHeight && thresholdHeight) {
- float shift = min<float>((baseHeight - thresholdHeight) / thresholdHeight, 1.0f);
- overbarLeftPointShift = static_cast<int>(shift * gRadicalBottomPointXFront * frontWidth);
- }
-
- overbarWidth += overbarLeftPointShift;
-
- int startX = adjustedPaintOffset.x() + frontWidth;
-
- FloatPoint overbarLeftPoint(startX - overbarLeftPointShift, adjustedPaintOffset.y());
- FloatPoint bottomPoint(startX - gRadicalBottomPointXFront * frontWidth, adjustedPaintOffset.y() + baseHeight + gRadicalBottomPointLower);
- FloatPoint dipLeftPoint(startX - gRadicalDipLeftPointXFront * frontWidth, adjustedPaintOffset.y() + gRadicalDipLeftPointYPos * baseHeight);
- FloatPoint leftEnd(startX - frontWidth, dipLeftPoint.y() + gRadicalLeftEndYShiftEms * style()->fontSize());
-
- GraphicsContextStateSaver stateSaver(*info.context);
-
- info.context->setStrokeThickness(gRadicalLineThicknessEms * style()->fontSize());
- info.context->setStrokeStyle(SolidStroke);
- info.context->setStrokeColor(style()->visitedDependentColor(CSSPropertyColor), ColorSpaceDeviceRGB);
- info.context->setLineJoin(MiterJoin);
- info.context->setMiterLimit(style()->fontSize());
-
- Path root;
-
- root.moveTo(FloatPoint(overbarLeftPoint.x() + overbarWidth, adjustedPaintOffset.y()));
- // draw top
- root.addLineTo(overbarLeftPoint);
- // draw from top left corner to bottom point of radical
- root.addLineTo(bottomPoint);
- // draw from bottom point to top of left part of radical base "dip"
- root.addLineTo(dipLeftPoint);
- // draw to end
- root.addLineTo(leftEnd);
-
- info.context->strokePath(root);
-
- GraphicsContextStateSaver maskStateSaver(*info.context);
-
- // Build a mask to draw the thick part of the root.
- Path mask;
-
- mask.moveTo(overbarLeftPoint);
- mask.addLineTo(bottomPoint);
- mask.addLineTo(dipLeftPoint);
- mask.addLineTo(FloatPoint(2 * dipLeftPoint.x() - leftEnd.x(), 2 * dipLeftPoint.y() - leftEnd.y()));
-
- info.context->clip(mask);
-
- // Draw the thick part of the root.
- info.context->setStrokeThickness(gRadicalThickLineThicknessEms * style()->fontSize());
- info.context->setLineCap(SquareCap);
-
- Path line;
- line.moveTo(bottomPoint);
- line.addLineTo(dipLeftPoint);
-
- info.context->strokePath(line);
-}
-
}
#endif // ENABLE(MATHML)
diff --git a/Source/WebCore/rendering/mathml/RenderMathMLSquareRoot.h b/Source/WebCore/rendering/mathml/RenderMathMLSquareRoot.h
index ea6d324db..b0270efbb 100644
--- a/Source/WebCore/rendering/mathml/RenderMathMLSquareRoot.h
+++ b/Source/WebCore/rendering/mathml/RenderMathMLSquareRoot.h
@@ -28,12 +28,12 @@
#if ENABLE(MATHML)
-#include "RenderMathMLBlock.h"
+#include "RenderMathMLRoot.h"
namespace WebCore {
// Render sqrt(base), using radical notation.
-class RenderMathMLSquareRoot : public RenderMathMLBlock {
+class RenderMathMLSquareRoot : public RenderMathMLRoot {
public:
RenderMathMLSquareRoot(Element*);
@@ -43,12 +43,6 @@ private:
virtual const char* renderName() const { return "RenderMathMLSquareRoot"; }
virtual bool createsAnonymousWrapper() const OVERRIDE { return true; }
-
- virtual void computePreferredLogicalWidths() OVERRIDE;
- virtual void computeLogicalHeight() OVERRIDE;
- virtual void layout() OVERRIDE;
-
- virtual void paint(PaintInfo&, const LayoutPoint&) OVERRIDE;
};
}
diff --git a/Source/WebCore/rendering/style/RenderStyleConstants.h b/Source/WebCore/rendering/style/RenderStyleConstants.h
index 741acc6e5..a24ac9dc8 100644
--- a/Source/WebCore/rendering/style/RenderStyleConstants.h
+++ b/Source/WebCore/rendering/style/RenderStyleConstants.h
@@ -410,7 +410,7 @@ enum EDisplay {
TABLE_HEADER_GROUP, TABLE_FOOTER_GROUP, TABLE_ROW,
TABLE_COLUMN_GROUP, TABLE_COLUMN, TABLE_CELL,
TABLE_CAPTION, BOX, INLINE_BOX,
- FLEXBOX, INLINE_FLEXBOX,
+ FLEX, INLINE_FLEX,
#if ENABLE(CSS_GRID_LAYOUT)
GRID, INLINE_GRID,
#endif
diff --git a/Source/WebCore/rendering/svg/RenderSVGBlock.h b/Source/WebCore/rendering/svg/RenderSVGBlock.h
index ca000f50b..9ef55a919 100644
--- a/Source/WebCore/rendering/svg/RenderSVGBlock.h
+++ b/Source/WebCore/rendering/svg/RenderSVGBlock.h
@@ -34,13 +34,15 @@ public:
virtual LayoutRect visualOverflowRect() const;
+protected:
+ virtual void willBeDestroyed() OVERRIDE;
+
private:
virtual void setStyle(PassRefPtr<RenderStyle>);
virtual void updateBoxModelInfoFromStyle();
virtual void absoluteRects(Vector<IntRect>&, const LayoutPoint& accumulatedOffset) const;
- virtual void willBeDestroyed();
virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle);
virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
virtual void updateFromElement();
diff --git a/Source/WebCore/rendering/svg/RenderSVGInline.cpp b/Source/WebCore/rendering/svg/RenderSVGInline.cpp
index 98af8e958..77b4fe956 100644
--- a/Source/WebCore/rendering/svg/RenderSVGInline.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGInline.cpp
@@ -124,7 +124,22 @@ void RenderSVGInline::addChild(RenderObject* child, RenderObject* beforeChild)
{
RenderInline::addChild(child, beforeChild);
if (RenderSVGText* textRenderer = RenderSVGText::locateRenderSVGTextAncestor(this))
- textRenderer->subtreeChildAdded(child);
+ textRenderer->subtreeChildWasAdded(child);
+}
+
+void RenderSVGInline::removeChild(RenderObject* child)
+{
+ RenderSVGText* textRenderer = child->isSVGInlineText() ? RenderSVGText::locateRenderSVGTextAncestor(this) : 0;
+ if (!textRenderer) {
+ RenderInline::removeChild(child);
+ return;
+ }
+
+ RenderSVGInlineText* text = toRenderSVGInlineText(child);
+ Vector<SVGTextLayoutAttributes*, 2> affectedAttributes;
+ textRenderer->subtreeChildWillBeRemoved(text, affectedAttributes);
+ RenderInline::removeChild(child);
+ textRenderer->subtreeChildWasRemoved(affectedAttributes);
}
}
diff --git a/Source/WebCore/rendering/svg/RenderSVGInline.h b/Source/WebCore/rendering/svg/RenderSVGInline.h
index 8aa4ab875..172062196 100644
--- a/Source/WebCore/rendering/svg/RenderSVGInline.h
+++ b/Source/WebCore/rendering/svg/RenderSVGInline.h
@@ -57,7 +57,9 @@ private:
virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle);
virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
virtual void updateFromElement();
+
virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0);
+ virtual void removeChild(RenderObject*) OVERRIDE;
};
}
diff --git a/Source/WebCore/rendering/svg/RenderSVGInlineText.cpp b/Source/WebCore/rendering/svg/RenderSVGInlineText.cpp
index a0df4113e..eff707724 100644
--- a/Source/WebCore/rendering/svg/RenderSVGInlineText.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGInlineText.cpp
@@ -72,25 +72,11 @@ RenderSVGInlineText::RenderSVGInlineText(Node* n, PassRefPtr<StringImpl> string)
{
}
-void RenderSVGInlineText::willBeDestroyed()
-{
- RenderSVGText* textRenderer = RenderSVGText::locateRenderSVGTextAncestor(this);
- if (!textRenderer) {
- RenderText::willBeDestroyed();
- return;
- }
-
- Vector<SVGTextLayoutAttributes*> affectedAttributes;
- textRenderer->subtreeChildWillBeDestroyed(this, affectedAttributes);
- RenderText::willBeDestroyed();
- textRenderer->subtreeChildWasDestroyed(this, affectedAttributes);
-}
-
void RenderSVGInlineText::setTextInternal(PassRefPtr<StringImpl> text)
{
RenderText::setTextInternal(text);
if (RenderSVGText* textRenderer = RenderSVGText::locateRenderSVGTextAncestor(this))
- textRenderer->subtreeTextChanged(this);
+ textRenderer->subtreeTextDidChange(this);
}
void RenderSVGInlineText::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
@@ -115,7 +101,7 @@ void RenderSVGInlineText::styleDidChange(StyleDifference diff, const RenderStyle
// The text metrics may be influenced by style changes.
if (RenderSVGText* textRenderer = RenderSVGText::locateRenderSVGTextAncestor(this))
- textRenderer->subtreeStyleChanged(this);
+ textRenderer->subtreeStyleDidChange(this);
}
InlineTextBox* RenderSVGInlineText::createTextBox()
diff --git a/Source/WebCore/rendering/svg/RenderSVGInlineText.h b/Source/WebCore/rendering/svg/RenderSVGInlineText.h
index 51378fd07..ab81ca99f 100644
--- a/Source/WebCore/rendering/svg/RenderSVGInlineText.h
+++ b/Source/WebCore/rendering/svg/RenderSVGInlineText.h
@@ -48,7 +48,6 @@ public:
private:
virtual const char* renderName() const { return "RenderSVGInlineText"; }
- virtual void willBeDestroyed();
virtual void setTextInternal(PassRefPtr<StringImpl>);
virtual void styleDidChange(StyleDifference, const RenderStyle*);
diff --git a/Source/WebCore/rendering/svg/RenderSVGResource.cpp b/Source/WebCore/rendering/svg/RenderSVGResource.cpp
index 4fc5e2376..fd16ef29d 100644
--- a/Source/WebCore/rendering/svg/RenderSVGResource.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGResource.cpp
@@ -27,8 +27,10 @@
#include "Frame.h"
#include "FrameView.h"
+#include "RenderSVGResourceClipper.h"
#include "RenderSVGResourceContainer.h"
#include "RenderSVGResourceFilter.h"
+#include "RenderSVGResourceMasker.h"
#include "RenderSVGResourceSolidColor.h"
#include "SVGResources.h"
#include "SVGResourcesCache.h"
@@ -161,15 +163,21 @@ RenderSVGResourceSolidColor* RenderSVGResource::sharedSolidPaintingResource()
return s_sharedSolidPaintingResource;
}
-static inline void removeFromFilterCacheAndInvalidateDependencies(RenderObject* object, bool needsLayout)
+static inline void removeFromCacheAndInvalidateDependencies(RenderObject* object, bool needsLayout)
{
ASSERT(object);
-#if ENABLE(FILTERS)
if (SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(object)) {
+#if ENABLE(FILTERS)
if (RenderSVGResourceFilter* filter = resources->filter())
filter->removeClientFromCache(object);
- }
#endif
+ if (RenderSVGResourceMasker* masker = resources->masker())
+ masker->removeClientFromCache(object);
+
+ if (RenderSVGResourceClipper* clipper = resources->clipper())
+ clipper->removeClientFromCache(object);
+ }
+
if (!object->node() || !object->node()->isSVGElement())
return;
HashSet<SVGElement*>* dependencies = object->document()->accessSVGExtensions()->setOfElementsReferencingTarget(static_cast<SVGElement*>(object->node()));
@@ -191,12 +199,12 @@ void RenderSVGResource::markForLayoutAndParentResourceInvalidation(RenderObject*
if (needsLayout)
object->setNeedsLayout(true);
- removeFromFilterCacheAndInvalidateDependencies(object, needsLayout);
+ removeFromCacheAndInvalidateDependencies(object, needsLayout);
// Invalidate resources in ancestor chain, if needed.
RenderObject* current = object->parent();
while (current) {
- removeFromFilterCacheAndInvalidateDependencies(current, needsLayout);
+ removeFromCacheAndInvalidateDependencies(current, needsLayout);
if (current->isSVGResourceContainer()) {
// This will process the rest of the ancestors.
diff --git a/Source/WebCore/rendering/svg/RenderSVGText.cpp b/Source/WebCore/rendering/svg/RenderSVGText.cpp
index f0f0b9c32..2bb583cac 100644
--- a/Source/WebCore/rendering/svg/RenderSVGText.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGText.cpp
@@ -57,12 +57,17 @@ namespace WebCore {
RenderSVGText::RenderSVGText(SVGTextElement* node)
: RenderSVGBlock(node)
, m_needsReordering(false)
- , m_needsPositioningValuesUpdate(true)
+ , m_needsPositioningValuesUpdate(false)
, m_needsTransformUpdate(true)
- , m_needsTextMetricsUpdate(true)
+ , m_needsTextMetricsUpdate(false)
{
}
+RenderSVGText::~RenderSVGText()
+{
+ ASSERT(m_layoutAttributes.isEmpty());
+}
+
bool RenderSVGText::isChildAllowed(RenderObject* child, RenderStyle*) const
{
return child->isInline();
@@ -110,29 +115,19 @@ void RenderSVGText::mapLocalToContainer(RenderBoxModelObject* repaintContainer,
SVGRenderSupport::mapLocalToContainer(this, repaintContainer, transformState, wasFixed);
}
-void RenderSVGText::subtreeChildAdded(RenderObject* child)
+static inline void collectLayoutAttributes(RenderObject* text, Vector<SVGTextLayoutAttributes*>& attributes)
{
- ASSERT(child);
- if (m_needsPositioningValuesUpdate)
- return;
-
- // The positioning elements cache doesn't include the new 'child' yet. Clear the
- // cache, as the next buildLayoutAttributesForTextRenderer() call rebuilds it.
- invalidateTextPositioningElements();
-
- FontCachePurgePreventer fontCachePurgePreventer;
- for (RenderObject* descendant = child; descendant; descendant = descendant->nextInPreOrder(child)) {
+ for (RenderObject* descendant = text; descendant; descendant = descendant->nextInPreOrder(text)) {
if (descendant->isSVGInlineText())
- m_layoutAttributesBuilder.buildLayoutAttributesForTextRenderer(toRenderSVGInlineText(descendant));
+ attributes.append(toRenderSVGInlineText(descendant)->layoutAttributes());
}
-
- rebuildLayoutAttributes();
}
static inline bool findPreviousAndNextAttributes(RenderObject* start, RenderSVGInlineText* locateElement, bool& stopAfterNext, SVGTextLayoutAttributes*& previous, SVGTextLayoutAttributes*& next)
{
ASSERT(start);
ASSERT(locateElement);
+ // FIXME: Make this iterative.
for (RenderObject* child = start->firstChild(); child; child = child->nextSibling()) {
if (child->isSVGInlineText()) {
RenderSVGInlineText* text = toRenderSVGInlineText(child);
@@ -160,53 +155,70 @@ static inline bool findPreviousAndNextAttributes(RenderObject* start, RenderSVGI
return false;
}
-void RenderSVGText::subtreeChildWillBeDestroyed(RenderSVGInlineText* text, Vector<SVGTextLayoutAttributes*>& affectedAttributes)
+inline bool RenderSVGText::shouldHandleSubtreeMutations() const
{
- ASSERT(text);
-
- // The positioning elements cache depends on the size of each text renderer in the
- // subtree. If this changes, clear the cache. It's going to be rebuilt below.
- invalidateTextPositioningElements();
+ if (beingDestroyed() || !everHadLayout()) {
+ ASSERT(m_layoutAttributes.isEmpty());
+ ASSERT(!m_layoutAttributesBuilder.numberOfTextPositioningElements());
+ return false;
+ }
+ return true;
+}
- if (m_needsPositioningValuesUpdate)
+void RenderSVGText::subtreeChildWasAdded(RenderObject* child)
+{
+ ASSERT(child);
+ if (!shouldHandleSubtreeMutations() || documentBeingDestroyed())
return;
- // This logic requires that the 'text' child is still inserted in the tree.
- bool stopAfterNext = false;
- SVGTextLayoutAttributes* previous = 0;
- SVGTextLayoutAttributes* next = 0;
- findPreviousAndNextAttributes(this, text, stopAfterNext, previous, next);
- if (previous)
- affectedAttributes.append(previous);
- if (next)
- affectedAttributes.append(next);
-
- SVGTextLayoutAttributes* currentLayoutAttributes = text->layoutAttributes();
-
- size_t position = m_layoutAttributes.find(currentLayoutAttributes);
- ASSERT(position != notFound);
- m_layoutAttributes.remove(position);
+ // The positioning elements cache doesn't include the new 'child' yet. Clear the
+ // cache, as the next buildLayoutAttributesForTextRenderer() call rebuilds it.
+ m_layoutAttributesBuilder.clearTextPositioningElements();
- ASSERT(!m_layoutAttributes.contains(currentLayoutAttributes));
-}
+ // Detect changes in layout attributes and only measure those text parts that have changed!
+ Vector<SVGTextLayoutAttributes*> newLayoutAttributes;
+ collectLayoutAttributes(this, newLayoutAttributes);
+ if (newLayoutAttributes.isEmpty()) {
+ ASSERT(m_layoutAttributes.isEmpty());
+ return;
+ }
-static inline void recursiveCollectLayoutAttributes(RenderObject* start, Vector<SVGTextLayoutAttributes*>& attributes)
-{
- for (RenderObject* child = start->firstChild(); child; child = child->nextSibling()) {
- if (child->isSVGInlineText()) {
- attributes.append(toRenderSVGInlineText(child)->layoutAttributes());
- continue;
+ // Compare m_layoutAttributes with newLayoutAttributes to figure out which attribute got added.
+ size_t size = newLayoutAttributes.size();
+ SVGTextLayoutAttributes* attributes = 0;
+ for (size_t i = 0; i < size; ++i) {
+ attributes = newLayoutAttributes[i];
+ if (m_layoutAttributes.find(attributes) == notFound) {
+ // Every time this is invoked, there's only a single new entry in the newLayoutAttributes list, compared to the old in m_layoutAttributes.
+ bool stopAfterNext = false;
+ SVGTextLayoutAttributes* previous = 0;
+ SVGTextLayoutAttributes* next = 0;
+ ASSERT_UNUSED(child, attributes->context() == child);
+ findPreviousAndNextAttributes(this, attributes->context(), stopAfterNext, previous, next);
+
+ if (previous)
+ m_layoutAttributesBuilder.buildLayoutAttributesForTextRenderer(previous->context());
+ m_layoutAttributesBuilder.buildLayoutAttributesForTextRenderer(attributes->context());
+ if (next)
+ m_layoutAttributesBuilder.buildLayoutAttributesForTextRenderer(next->context());
+ break;
}
-
- recursiveCollectLayoutAttributes(child, attributes);
}
+
+#ifndef NDEBUG
+ // Verify that m_layoutAttributes only differs by a maximum of one entry.
+ for (size_t i = 0; i < size; ++i)
+ ASSERT(m_layoutAttributes.find(newLayoutAttributes[i]) != notFound || newLayoutAttributes[i] == attributes);
+#endif
+
+ m_layoutAttributes = newLayoutAttributes;
}
static inline void checkLayoutAttributesConsistency(RenderSVGText* text, Vector<SVGTextLayoutAttributes*>& expectedLayoutAttributes)
{
#ifndef NDEBUG
Vector<SVGTextLayoutAttributes*> newLayoutAttributes;
- recursiveCollectLayoutAttributes(text, newLayoutAttributes);
+ collectLayoutAttributes(text, newLayoutAttributes);
ASSERT(newLayoutAttributes == expectedLayoutAttributes);
#else
UNUSED_PARAM(text);
@@ -214,24 +226,67 @@ static inline void checkLayoutAttributesConsistency(RenderSVGText* text, Vector<
#endif
}
-void RenderSVGText::subtreeChildWasDestroyed(RenderSVGInlineText*, Vector<SVGTextLayoutAttributes*>& affectedAttributes)
+void RenderSVGText::willBeDestroyed()
{
- if (documentBeingDestroyed() || affectedAttributes.isEmpty())
+ m_layoutAttributes.clear();
+ m_layoutAttributesBuilder.clearTextPositioningElements();
+
+ RenderSVGBlock::willBeDestroyed();
+}
+
+void RenderSVGText::subtreeChildWillBeRemoved(RenderSVGInlineText* text, Vector<SVGTextLayoutAttributes*, 2>& affectedAttributes)
+{
+ ASSERT(text);
+ if (!shouldHandleSubtreeMutations())
return;
checkLayoutAttributesConsistency(this, m_layoutAttributes);
- size_t size = affectedAttributes.size();
- for (size_t i = 0; i < size; ++i)
- m_layoutAttributesBuilder.rebuildMetricsForTextRenderer(affectedAttributes[i]->context());
+ // The positioning elements cache depends on the size of each text renderer in the
+ // subtree. If this changes, clear the cache. It's going to be rebuilt below.
+ m_layoutAttributesBuilder.clearTextPositioningElements();
+ if (m_layoutAttributes.isEmpty())
+ return;
+
+ // This logic requires that the 'text' child is still inserted in the tree.
+ bool stopAfterNext = false;
+ SVGTextLayoutAttributes* previous = 0;
+ SVGTextLayoutAttributes* next = 0;
+ if (!documentBeingDestroyed())
+ findPreviousAndNextAttributes(this, text, stopAfterNext, previous, next);
+
+ if (previous)
+ affectedAttributes.append(previous);
+ if (next)
+ affectedAttributes.append(next);
+
+ size_t position = m_layoutAttributes.find(text->layoutAttributes());
+ ASSERT(position != notFound);
+ m_layoutAttributes.remove(position);
}
-void RenderSVGText::subtreeStyleChanged(RenderSVGInlineText* text)
+void RenderSVGText::subtreeChildWasRemoved(const Vector<SVGTextLayoutAttributes*, 2>& affectedAttributes)
+{
+ if (!shouldHandleSubtreeMutations() || documentBeingDestroyed()) {
+ ASSERT(affectedAttributes.isEmpty());
+ return;
+ }
+
+ // This is called immediately after subtreeChildWillBeDestroyed, once the RenderSVGInlineText::willBeDestroyed() method
+ // passes on to the base class, which removes us from the render tree. At this point we can update the layout attributes.
+ unsigned size = affectedAttributes.size();
+ for (unsigned i = 0; i < size; ++i)
+ m_layoutAttributesBuilder.buildLayoutAttributesForTextRenderer(affectedAttributes[i]->context());
+}
+
+void RenderSVGText::subtreeStyleDidChange(RenderSVGInlineText* text)
{
ASSERT(text);
- if (m_needsPositioningValuesUpdate)
+ if (!shouldHandleSubtreeMutations() || documentBeingDestroyed())
return;
+ checkLayoutAttributesConsistency(this, m_layoutAttributes);
+
// Only update the metrics cache, but not the text positioning element cache
// nor the layout attributes cached in the leaf #text renderers.
FontCachePurgePreventer fontCachePurgePreventer;
@@ -241,31 +296,37 @@ void RenderSVGText::subtreeStyleChanged(RenderSVGInlineText* text)
}
}
-void RenderSVGText::subtreeTextChanged(RenderSVGInlineText* text)
+void RenderSVGText::subtreeTextDidChange(RenderSVGInlineText* text)
{
ASSERT(text);
+ ASSERT(!beingDestroyed());
+ if (!everHadLayout()) {
+ ASSERT(m_layoutAttributes.isEmpty());
+ ASSERT(!m_layoutAttributesBuilder.numberOfTextPositioningElements());
+ return;
+ }
// The positioning elements cache depends on the size of each text renderer in the
// subtree. If this changes, clear the cache. It's going to be rebuilt below.
- invalidateTextPositioningElements();
-
- if (m_needsPositioningValuesUpdate)
- return;
+ m_layoutAttributesBuilder.clearTextPositioningElements();
- FontCachePurgePreventer fontCachePurgePreventer;
+ checkLayoutAttributesConsistency(this, m_layoutAttributes);
for (RenderObject* descendant = text; descendant; descendant = descendant->nextInPreOrder(text)) {
if (descendant->isSVGInlineText())
m_layoutAttributesBuilder.buildLayoutAttributesForTextRenderer(toRenderSVGInlineText(descendant));
}
}
-void RenderSVGText::invalidateTextPositioningElements()
+static inline void updateFontInAllDescendants(RenderObject* start, SVGTextLayoutAttributesBuilder* builder = 0)
{
- // Clear the text positioning elements. This should be called when either the children
- // of a DOM text element have changed, or the length of the text in any child element
- // has changed. Failure to clear may leave us with invalid elements, as other code paths
- // do not always cause the position elements to be marked invalid before use.
- m_layoutAttributesBuilder.clearTextPositioningElements();
+ for (RenderObject* descendant = start; descendant; descendant = descendant->nextInPreOrder(start)) {
+ if (!descendant->isSVGInlineText())
+ continue;
+ RenderSVGInlineText* text = toRenderSVGInlineText(descendant);
+ text->updateScaledFont();
+ if (builder)
+ builder->rebuildMetricsForTextRenderer(text);
+ }
}
void RenderSVGText::layout()
@@ -281,27 +342,43 @@ void RenderSVGText::layout()
updateCachedBoundariesInParents = true;
}
- // If the root layout size changed (eg. window size changes) or the positioning values change
- // or the transform to the root context has changed then recompute the on-screen font size.
- if (m_needsTextMetricsUpdate || SVGRenderSupport::findTreeRootObject(this)->isLayoutSizeChanged()) {
- for (RenderObject* descendant = this; descendant; descendant = descendant->nextInPreOrder(this)) {
- if (descendant->isSVGInlineText())
- toRenderSVGInlineText(descendant)->updateScaledFont();
- }
+ if (!everHadLayout()) {
+ // When laying out initially, collect all layout attributes, build the character data map,
+ // and propogate resulting SVGLayoutAttributes to all RenderSVGInlineText children in the subtree.
+ ASSERT(m_layoutAttributes.isEmpty());
+ collectLayoutAttributes(this, m_layoutAttributes);
+ updateFontInAllDescendants(this);
+ m_layoutAttributesBuilder.buildLayoutAttributesForForSubtree(this);
- rebuildAllLayoutAttributes();
- updateCachedBoundariesInParents = true;
+ m_needsReordering = true;
m_needsTextMetricsUpdate = false;
- }
+ m_needsPositioningValuesUpdate = false;
+ updateCachedBoundariesInParents = true;
+ } else if (m_needsPositioningValuesUpdate) {
+ // When the x/y/dx/dy/rotate lists change, recompute the layout attributes, and eventually
+ // update the on-screen font objects as well in all descendants.
+ if (m_needsTextMetricsUpdate) {
+ updateFontInAllDescendants(this);
+ m_needsTextMetricsUpdate = false;
+ }
- if (m_needsPositioningValuesUpdate) {
- // Perform SVG text layout phase one (see SVGTextLayoutAttributesBuilder for details).
- m_layoutAttributesBuilder.buildLayoutAttributesForWholeTree(this);
+ m_layoutAttributesBuilder.buildLayoutAttributesForForSubtree(this);
m_needsReordering = true;
m_needsPositioningValuesUpdate = false;
updateCachedBoundariesInParents = true;
+ } else if (m_needsTextMetricsUpdate || SVGRenderSupport::findTreeRootObject(this)->isLayoutSizeChanged()) {
+ // If the root layout size changed (eg. window size changes) or the transform to the root
+ // context has changed then recompute the on-screen font size.
+ updateFontInAllDescendants(this, &m_layoutAttributesBuilder);
+
+ ASSERT(!m_needsReordering);
+ ASSERT(!m_needsPositioningValuesUpdate);
+ m_needsTextMetricsUpdate = false;
+ updateCachedBoundariesInParents = true;
}
+ checkLayoutAttributesConsistency(this, m_layoutAttributes);
+
// Reduced version of RenderBlock::layoutBlock(), which only takes care of SVG text.
// All if branches that could cause early exit in RenderBlocks layoutBlock() method are turned into assertions.
ASSERT(!isInline());
@@ -437,7 +514,21 @@ FloatRect RenderSVGText::repaintRectInLocalCoordinates() const
void RenderSVGText::addChild(RenderObject* child, RenderObject* beforeChild)
{
RenderSVGBlock::addChild(child, beforeChild);
- subtreeChildAdded(child);
+ subtreeChildWasAdded(child);
+}
+
+void RenderSVGText::removeChild(RenderObject* child)
+{
+ if (!child->isSVGInlineText()) {
+ RenderSVGBlock::removeChild(child);
+ return;
+ }
+
+ RenderSVGInlineText* text = toRenderSVGInlineText(child);
+ Vector<SVGTextLayoutAttributes*, 2> affectedAttributes;
+ subtreeChildWillBeRemoved(text, affectedAttributes);
+ RenderSVGBlock::removeChild(child);
+ subtreeChildWasRemoved(affectedAttributes);
}
// Fix for <rdar://problem/8048875>. We should not render :first-line CSS Style
@@ -453,42 +544,6 @@ void RenderSVGText::updateFirstLetter()
{
}
-void RenderSVGText::rebuildAllLayoutAttributes()
-{
- m_layoutAttributes.clear();
- recursiveCollectLayoutAttributes(this, m_layoutAttributes);
- if (m_layoutAttributes.isEmpty())
- return;
-
- m_layoutAttributesBuilder.rebuildMetricsForWholeTree(this);
-}
-
-void RenderSVGText::rebuildLayoutAttributes()
-{
- if (m_layoutAttributes.isEmpty()) {
- rebuildAllLayoutAttributes();
- return;
- }
-
- // Detect changes in layout attributes and only measure those text parts that have changed!
- Vector<SVGTextLayoutAttributes*> newLayoutAttributes;
- recursiveCollectLayoutAttributes(this, newLayoutAttributes);
- if (newLayoutAttributes.isEmpty()) {
- m_layoutAttributes.clear();
- return;
- }
-
- // Compare m_layoutAttributes with newLayoutAttributes to figure out which attributes got added.
- size_t size = newLayoutAttributes.size();
- for (size_t i = 0; i < size; ++i) {
- SVGTextLayoutAttributes* attributes = newLayoutAttributes[i];
- if (m_layoutAttributes.find(attributes) == notFound)
- m_layoutAttributesBuilder.rebuildMetricsForTextRenderer(attributes->context());
- }
-
- m_layoutAttributes = newLayoutAttributes;
-}
-
}
#endif // ENABLE(SVG)
diff --git a/Source/WebCore/rendering/svg/RenderSVGText.h b/Source/WebCore/rendering/svg/RenderSVGText.h
index 23a0b6a9a..ee7b3d027 100644
--- a/Source/WebCore/rendering/svg/RenderSVGText.h
+++ b/Source/WebCore/rendering/svg/RenderSVGText.h
@@ -36,6 +36,7 @@ class RenderSVGInlineText;
class RenderSVGText : public RenderSVGBlock {
public:
RenderSVGText(SVGTextElement*);
+ virtual ~RenderSVGText();
virtual bool isChildAllowed(RenderObject*, RenderStyle*) const;
@@ -50,15 +51,11 @@ public:
bool needsReordering() const { return m_needsReordering; }
Vector<SVGTextLayoutAttributes*>& layoutAttributes() { return m_layoutAttributes; }
- void subtreeChildAdded(RenderObject*);
- void subtreeChildWillBeDestroyed(RenderSVGInlineText*, Vector<SVGTextLayoutAttributes*>& affectedAttributes);
- void subtreeChildWasDestroyed(RenderSVGInlineText*, Vector<SVGTextLayoutAttributes*>& affectedAttributes);
- void subtreeStyleChanged(RenderSVGInlineText*);
- void subtreeTextChanged(RenderSVGInlineText*);
-
- // Call this method when either the children of a DOM text element have changed, or the length of
- // the text in any child element has changed.
- void invalidateTextPositioningElements();
+ void subtreeChildWasAdded(RenderObject*);
+ void subtreeChildWillBeRemoved(RenderSVGInlineText*, Vector<SVGTextLayoutAttributes*, 2>& affectedAttributes);
+ void subtreeChildWasRemoved(const Vector<SVGTextLayoutAttributes*, 2>& affectedAttributes);
+ void subtreeStyleDidChange(RenderSVGInlineText*);
+ void subtreeTextDidChange(RenderSVGInlineText*);
private:
virtual const char* renderName() const { return "RenderSVGText"; }
@@ -80,6 +77,8 @@ private:
virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool useTransforms, bool fixed, TransformState&, ApplyContainerFlipOrNot = ApplyContainerFlip, bool* wasFixed = 0) const;
virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0);
+ virtual void removeChild(RenderObject*) OVERRIDE;
+ virtual void willBeDestroyed() OVERRIDE;
virtual FloatRect objectBoundingBox() const { return frameRect(); }
virtual FloatRect strokeBoundingBox() const;
@@ -91,8 +90,7 @@ private:
virtual RenderBlock* firstLineBlock() const;
virtual void updateFirstLetter();
- void rebuildAllLayoutAttributes();
- void rebuildLayoutAttributes();
+ bool shouldHandleSubtreeMutations() const;
bool m_needsReordering : 1;
bool m_needsPositioningValuesUpdate : 1;
diff --git a/Source/WebCore/rendering/svg/SVGRenderSupport.cpp b/Source/WebCore/rendering/svg/SVGRenderSupport.cpp
index b206cb6c2..ddc7c9155 100644
--- a/Source/WebCore/rendering/svg/SVGRenderSupport.cpp
+++ b/Source/WebCore/rendering/svg/SVGRenderSupport.cpp
@@ -197,8 +197,10 @@ void SVGRenderSupport::layoutChildren(RenderObject* start, bool selfNeedsLayout)
// When the layout size changed and when using relative values tell the RenderSVGShape to update its shape object
if (child->isSVGShape())
toRenderSVGShape(child)->setNeedsShapeUpdate();
- else if (child->isSVGText())
+ else if (child->isSVGText()) {
+ toRenderSVGText(child)->setNeedsTextMetricsUpdate();
toRenderSVGText(child)->setNeedsPositioningValuesUpdate();
+ }
needsLayout = true;
}
diff --git a/Source/WebCore/rendering/svg/SVGTextLayoutAttributesBuilder.cpp b/Source/WebCore/rendering/svg/SVGTextLayoutAttributesBuilder.cpp
index 067bf6bb9..be2a12fe9 100644
--- a/Source/WebCore/rendering/svg/SVGTextLayoutAttributesBuilder.cpp
+++ b/Source/WebCore/rendering/svg/SVGTextLayoutAttributesBuilder.cpp
@@ -41,41 +41,27 @@ void SVGTextLayoutAttributesBuilder::buildLayoutAttributesForTextRenderer(Render
if (!textRoot)
return;
- if (!buildLayoutAttributesIfNeeded(textRoot))
- return;
-
- m_metricsBuilder.buildMetricsAndLayoutAttributes(textRoot, text, m_characterDataMap);
-}
+ if (m_textPositions.isEmpty()) {
+ m_characterDataMap.clear();
-void SVGTextLayoutAttributesBuilder::buildLayoutAttributesForWholeTree(RenderSVGText* textRoot)
-{
- ASSERT(textRoot);
+ m_textLength = 0;
+ const UChar* lastCharacter = 0;
+ collectTextPositioningElements(textRoot, lastCharacter);
- if (!buildLayoutAttributesIfNeeded(textRoot))
- return;
+ if (!m_textLength)
+ return;
- m_metricsBuilder.buildMetricsAndLayoutAttributes(textRoot, 0, m_characterDataMap);
-}
+ buildCharacterDataMap(textRoot);
+ }
-void SVGTextLayoutAttributesBuilder::rebuildMetricsForTextRenderer(RenderSVGInlineText* text)
-{
- ASSERT(text);
- m_metricsBuilder.measureTextRenderer(text);
+ m_metricsBuilder.buildMetricsAndLayoutAttributes(textRoot, text, m_characterDataMap);
}
-void SVGTextLayoutAttributesBuilder::rebuildMetricsForWholeTree(RenderSVGText* textRoot)
+bool SVGTextLayoutAttributesBuilder::buildLayoutAttributesForForSubtree(RenderSVGText* textRoot)
{
ASSERT(textRoot);
- Vector<SVGTextLayoutAttributes*>& layoutAttributes = textRoot->layoutAttributes();
-
- size_t layoutAttributesSize = layoutAttributes.size();
- for (size_t i = 0; i < layoutAttributesSize; ++i)
- m_metricsBuilder.measureTextRenderer(layoutAttributes[i]->context());
-}
-bool SVGTextLayoutAttributesBuilder::buildLayoutAttributesIfNeeded(RenderSVGText* textRoot)
-{
- ASSERT(textRoot);
+ m_characterDataMap.clear();
if (m_textPositions.isEmpty()) {
m_textLength = 0;
@@ -83,14 +69,20 @@ bool SVGTextLayoutAttributesBuilder::buildLayoutAttributesIfNeeded(RenderSVGText
collectTextPositioningElements(textRoot, lastCharacter);
}
- m_characterDataMap.clear();
if (!m_textLength)
return false;
- buildLayoutAttributes(textRoot);
+ buildCharacterDataMap(textRoot);
+ m_metricsBuilder.buildMetricsAndLayoutAttributes(textRoot, 0, m_characterDataMap);
return true;
}
+void SVGTextLayoutAttributesBuilder::rebuildMetricsForTextRenderer(RenderSVGInlineText* text)
+{
+ ASSERT(text);
+ m_metricsBuilder.measureTextRenderer(text);
+}
+
static inline void processRenderSVGInlineText(RenderSVGInlineText* text, unsigned& atCharacter, const UChar*& lastCharacter)
{
if (text->style()->whiteSpace() == PRE) {
@@ -140,10 +132,8 @@ void SVGTextLayoutAttributesBuilder::collectTextPositioningElements(RenderObject
}
}
-void SVGTextLayoutAttributesBuilder::buildLayoutAttributes(RenderSVGText* textRoot)
+void SVGTextLayoutAttributesBuilder::buildCharacterDataMap(RenderSVGText* textRoot)
{
- ASSERT(m_textLength);
-
SVGTextPositioningElement* outermostTextElement = SVGTextPositioningElement::elementFromRenderer(textRoot);
ASSERT(outermostTextElement);
diff --git a/Source/WebCore/rendering/svg/SVGTextLayoutAttributesBuilder.h b/Source/WebCore/rendering/svg/SVGTextLayoutAttributesBuilder.h
index 45fad2400..7dac96f4d 100644
--- a/Source/WebCore/rendering/svg/SVGTextLayoutAttributesBuilder.h
+++ b/Source/WebCore/rendering/svg/SVGTextLayoutAttributesBuilder.h
@@ -43,14 +43,14 @@ class SVGTextLayoutAttributesBuilder {
WTF_MAKE_NONCOPYABLE(SVGTextLayoutAttributesBuilder);
public:
SVGTextLayoutAttributesBuilder();
- void buildLayoutAttributesForWholeTree(RenderSVGText*);
+ bool buildLayoutAttributesForForSubtree(RenderSVGText*);
void buildLayoutAttributesForTextRenderer(RenderSVGInlineText*);
- void rebuildMetricsForWholeTree(RenderSVGText*);
void rebuildMetricsForTextRenderer(RenderSVGInlineText*);
// Invoked whenever the underlying DOM tree changes, so that m_textPositions is rebuild.
void clearTextPositioningElements() { m_textPositions.clear(); }
+ unsigned numberOfTextPositioningElements() const { return m_textPositions.size(); }
private:
struct TextPosition {
@@ -66,9 +66,8 @@ private:
unsigned length;
};
- bool buildLayoutAttributesIfNeeded(RenderSVGText*);
+ void buildCharacterDataMap(RenderSVGText*);
void collectTextPositioningElements(RenderObject*, const UChar*& lastCharacter);
- void buildLayoutAttributes(RenderSVGText*);
void fillCharacterDataMap(const TextPosition&);
private:
diff --git a/Source/WebCore/rendering/svg/SVGTextMetricsBuilder.cpp b/Source/WebCore/rendering/svg/SVGTextMetricsBuilder.cpp
index c94f0c74a..81fc325a1 100644
--- a/Source/WebCore/rendering/svg/SVGTextMetricsBuilder.cpp
+++ b/Source/WebCore/rendering/svg/SVGTextMetricsBuilder.cpp
@@ -48,7 +48,7 @@ bool SVGTextMetricsBuilder::advance()
if (int(m_textPosition) >= m_run.charactersLength())
return false;
-#if PLATFORM(QT)
+#if PLATFORM(QT) && !HAVE(QRAWFONT)
advanceComplexText();
#else
if (m_isComplexText)
@@ -62,7 +62,7 @@ bool SVGTextMetricsBuilder::advance()
void SVGTextMetricsBuilder::advanceSimpleText()
{
-#if PLATFORM(QT)
+#if PLATFORM(QT) && !HAVE(QRAWFONT)
ASSERT_NOT_REACHED();
#else
unsigned metricsLength = m_simpleWidthIterator->advance(m_textPosition + 1);
@@ -115,7 +115,7 @@ void SVGTextMetricsBuilder::initializeMeasurementWithTextRenderer(RenderSVGInlin
m_run = SVGTextMetrics::constructTextRun(text, text->characters(), 0, text->textLength());
m_isComplexText = scaledFont.codePath(m_run) == Font::Complex;
-#if !PLATFORM(QT)
+#if !PLATFORM(QT) || HAVE(QRAWFONT)
if (m_isComplexText)
m_simpleWidthIterator.clear();
else