summaryrefslogtreecommitdiff
path: root/Source/WebCore/rendering
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@nokia.com>2012-05-07 11:21:11 +0200
committerSimon Hausmann <simon.hausmann@nokia.com>2012-05-07 11:21:11 +0200
commit2cf6c8816a73e0132bd8fa3b509d62d7c51b6e47 (patch)
tree988e8c5b116dd0466244ae2fe5af8ee9be926d76 /Source/WebCore/rendering
parentdd91e772430dc294e3bf478c119ef8d43c0a3358 (diff)
downloadqtwebkit-2cf6c8816a73e0132bd8fa3b509d62d7c51b6e47.tar.gz
Imported WebKit commit 7e538425aa020340619e927792f3d895061fb54b (http://svn.webkit.org/repository/webkit/trunk@116286)
Diffstat (limited to 'Source/WebCore/rendering')
-rw-r--r--Source/WebCore/rendering/AutoTableLayout.cpp24
-rw-r--r--Source/WebCore/rendering/ColumnInfo.h4
-rw-r--r--Source/WebCore/rendering/EllipsisBox.cpp12
-rw-r--r--Source/WebCore/rendering/FilterEffectObserver.h47
-rw-r--r--Source/WebCore/rendering/FilterEffectRenderer.cpp172
-rw-r--r--Source/WebCore/rendering/FilterEffectRenderer.h50
-rw-r--r--Source/WebCore/rendering/FixedTableLayout.cpp103
-rw-r--r--Source/WebCore/rendering/FlowThreadController.cpp125
-rw-r--r--Source/WebCore/rendering/FlowThreadController.h82
-rw-r--r--Source/WebCore/rendering/HitTestResult.cpp25
-rw-r--r--Source/WebCore/rendering/HitTestResult.h13
-rw-r--r--Source/WebCore/rendering/HitTestingTransformState.cpp2
-rw-r--r--Source/WebCore/rendering/HitTestingTransformState.h2
-rw-r--r--Source/WebCore/rendering/InlineBox.cpp40
-rw-r--r--Source/WebCore/rendering/InlineBox.h216
-rw-r--r--Source/WebCore/rendering/InlineFlowBox.cpp90
-rw-r--r--Source/WebCore/rendering/InlineFlowBox.h24
-rw-r--r--Source/WebCore/rendering/InlineTextBox.cpp98
-rw-r--r--Source/WebCore/rendering/InlineTextBox.h22
-rw-r--r--Source/WebCore/rendering/LayoutRepainter.cpp4
-rw-r--r--Source/WebCore/rendering/LayoutRepainter.h7
-rw-r--r--Source/WebCore/rendering/LayoutTypes.h103
-rw-r--r--Source/WebCore/rendering/PaintInfo.h4
-rw-r--r--Source/WebCore/rendering/RenderApplet.cpp4
-rw-r--r--Source/WebCore/rendering/RenderApplet.h2
-rw-r--r--Source/WebCore/rendering/RenderArena.cpp4
-rw-r--r--Source/WebCore/rendering/RenderArena.h2
-rw-r--r--Source/WebCore/rendering/RenderBR.cpp4
-rwxr-xr-xSource/WebCore/rendering/RenderBlock.cpp999
-rw-r--r--Source/WebCore/rendering/RenderBlock.h157
-rwxr-xr-xSource/WebCore/rendering/RenderBlockLineLayout.cpp60
-rw-r--r--Source/WebCore/rendering/RenderBox.cpp534
-rw-r--r--Source/WebCore/rendering/RenderBox.h108
-rw-r--r--Source/WebCore/rendering/RenderBoxModelObject.cpp467
-rw-r--r--Source/WebCore/rendering/RenderBoxModelObject.h65
-rw-r--r--Source/WebCore/rendering/RenderButton.cpp3
-rw-r--r--Source/WebCore/rendering/RenderButton.h2
-rw-r--r--Source/WebCore/rendering/RenderCounter.cpp7
-rw-r--r--Source/WebCore/rendering/RenderDeprecatedFlexibleBox.cpp45
-rw-r--r--Source/WebCore/rendering/RenderDeprecatedFlexibleBox.h2
-rw-r--r--Source/WebCore/rendering/RenderDetailsMarker.cpp13
-rw-r--r--Source/WebCore/rendering/RenderDetailsMarker.h4
-rw-r--r--Source/WebCore/rendering/RenderEmbeddedObject.cpp13
-rw-r--r--Source/WebCore/rendering/RenderFieldset.cpp21
-rw-r--r--Source/WebCore/rendering/RenderFieldset.h2
-rw-r--r--Source/WebCore/rendering/RenderFileUploadControl.cpp25
-rw-r--r--Source/WebCore/rendering/RenderFileUploadControl.h2
-rw-r--r--Source/WebCore/rendering/RenderFlexibleBox.cpp548
-rw-r--r--Source/WebCore/rendering/RenderFlexibleBox.h36
-rw-r--r--Source/WebCore/rendering/RenderFlowThread.cpp272
-rw-r--r--Source/WebCore/rendering/RenderFlowThread.h57
-rw-r--r--Source/WebCore/rendering/RenderFrameBase.cpp4
-rw-r--r--Source/WebCore/rendering/RenderFrameSet.cpp12
-rw-r--r--Source/WebCore/rendering/RenderFullScreen.cpp9
-rw-r--r--Source/WebCore/rendering/RenderFullScreen.h2
-rw-r--r--Source/WebCore/rendering/RenderHTMLCanvas.cpp2
-rw-r--r--Source/WebCore/rendering/RenderIFrame.cpp24
-rw-r--r--Source/WebCore/rendering/RenderIFrame.h4
-rw-r--r--Source/WebCore/rendering/RenderImage.cpp86
-rw-r--r--Source/WebCore/rendering/RenderImage.h5
-rw-r--r--Source/WebCore/rendering/RenderInline.cpp84
-rw-r--r--Source/WebCore/rendering/RenderInline.h10
-rw-r--r--Source/WebCore/rendering/RenderInputSpeech.cpp16
-rw-r--r--Source/WebCore/rendering/RenderInputSpeech.h2
-rw-r--r--Source/WebCore/rendering/RenderLayer.cpp788
-rw-r--r--Source/WebCore/rendering/RenderLayer.h177
-rw-r--r--Source/WebCore/rendering/RenderLayerBacking.cpp223
-rw-r--r--Source/WebCore/rendering/RenderLayerBacking.h37
-rw-r--r--Source/WebCore/rendering/RenderLayerCompositor.cpp495
-rw-r--r--Source/WebCore/rendering/RenderLayerCompositor.h44
-rw-r--r--Source/WebCore/rendering/RenderLayerFilterInfo.cpp145
-rw-r--r--Source/WebCore/rendering/RenderLayerFilterInfo.h100
-rw-r--r--Source/WebCore/rendering/RenderLineBoxList.cpp24
-rw-r--r--Source/WebCore/rendering/RenderListBox.cpp16
-rw-r--r--Source/WebCore/rendering/RenderListItem.cpp2
-rw-r--r--Source/WebCore/rendering/RenderListMarker.cpp44
-rw-r--r--Source/WebCore/rendering/RenderListMarker.h2
-rw-r--r--Source/WebCore/rendering/RenderMarquee.cpp10
-rw-r--r--Source/WebCore/rendering/RenderMedia.cpp6
-rw-r--r--Source/WebCore/rendering/RenderMedia.h1
-rw-r--r--Source/WebCore/rendering/RenderMediaControls.cpp160
-rw-r--r--Source/WebCore/rendering/RenderMediaControlsChromium.cpp3
-rw-r--r--Source/WebCore/rendering/RenderMenuList.cpp18
-rw-r--r--Source/WebCore/rendering/RenderMeter.cpp4
-rw-r--r--Source/WebCore/rendering/RenderMultiColumnBlock.cpp91
-rw-r--r--Source/WebCore/rendering/RenderMultiColumnBlock.h53
-rw-r--r--Source/WebCore/rendering/RenderMultiColumnFlowThread.cpp41
-rw-r--r--Source/WebCore/rendering/RenderMultiColumnFlowThread.h45
-rw-r--r--Source/WebCore/rendering/RenderMultiColumnSet.cpp41
-rw-r--r--Source/WebCore/rendering/RenderMultiColumnSet.h55
-rw-r--r--Source/WebCore/rendering/RenderNamedFlowThread.cpp288
-rw-r--r--Source/WebCore/rendering/RenderNamedFlowThread.h123
-rwxr-xr-xSource/WebCore/rendering/RenderObject.cpp182
-rw-r--r--Source/WebCore/rendering/RenderObject.h70
-rw-r--r--Source/WebCore/rendering/RenderObjectChildList.cpp175
-rw-r--r--Source/WebCore/rendering/RenderObjectChildList.h3
-rw-r--r--Source/WebCore/rendering/RenderRegion.cpp21
-rw-r--r--Source/WebCore/rendering/RenderRegion.h10
-rw-r--r--Source/WebCore/rendering/RenderRegionSet.cpp36
-rw-r--r--Source/WebCore/rendering/RenderRegionSet.h59
-rw-r--r--Source/WebCore/rendering/RenderReplaced.cpp195
-rw-r--r--Source/WebCore/rendering/RenderReplaced.h17
-rw-r--r--Source/WebCore/rendering/RenderRuby.cpp4
-rw-r--r--Source/WebCore/rendering/RenderRubyBase.cpp10
-rw-r--r--Source/WebCore/rendering/RenderRubyRun.cpp11
-rw-r--r--Source/WebCore/rendering/RenderScrollbar.cpp31
-rw-r--r--Source/WebCore/rendering/RenderScrollbarPart.cpp30
-rw-r--r--Source/WebCore/rendering/RenderScrollbarPart.h8
-rw-r--r--Source/WebCore/rendering/RenderSelectionInfo.h8
-rw-r--r--Source/WebCore/rendering/RenderSlider.cpp2
-rw-r--r--Source/WebCore/rendering/RenderTable.cpp173
-rw-r--r--Source/WebCore/rendering/RenderTable.h16
-rw-r--r--Source/WebCore/rendering/RenderTableCell.cpp69
-rw-r--r--Source/WebCore/rendering/RenderTableCell.h50
-rw-r--r--Source/WebCore/rendering/RenderTableCol.h2
-rw-r--r--Source/WebCore/rendering/RenderTableRow.cpp26
-rw-r--r--Source/WebCore/rendering/RenderTableRow.h28
-rw-r--r--Source/WebCore/rendering/RenderTableSection.cpp143
-rw-r--r--Source/WebCore/rendering/RenderTableSection.h23
-rw-r--r--Source/WebCore/rendering/RenderText.cpp65
-rw-r--r--Source/WebCore/rendering/RenderText.h40
-rw-r--r--Source/WebCore/rendering/RenderTextControl.cpp2
-rw-r--r--Source/WebCore/rendering/RenderTextControlSingleLine.cpp32
-rw-r--r--Source/WebCore/rendering/RenderTextFragment.cpp37
-rw-r--r--Source/WebCore/rendering/RenderTextFragment.h8
-rw-r--r--Source/WebCore/rendering/RenderTheme.cpp115
-rw-r--r--Source/WebCore/rendering/RenderTheme.h57
-rw-r--r--Source/WebCore/rendering/RenderThemeChromiumAndroid.cpp4
-rw-r--r--Source/WebCore/rendering/RenderThemeChromiumAndroid.h2
-rw-r--r--Source/WebCore/rendering/RenderThemeChromiumCommon.cpp40
-rw-r--r--Source/WebCore/rendering/RenderThemeChromiumCommon.h41
-rw-r--r--Source/WebCore/rendering/RenderThemeChromiumLinux.cpp2
-rw-r--r--Source/WebCore/rendering/RenderThemeChromiumLinux.h2
-rw-r--r--Source/WebCore/rendering/RenderThemeChromiumMac.h8
-rw-r--r--Source/WebCore/rendering/RenderThemeChromiumMac.mm15
-rw-r--r--Source/WebCore/rendering/RenderThemeChromiumSkia.cpp38
-rw-r--r--Source/WebCore/rendering/RenderThemeChromiumSkia.h21
-rw-r--r--Source/WebCore/rendering/RenderThemeChromiumWin.cpp18
-rw-r--r--Source/WebCore/rendering/RenderThemeChromiumWin.h4
-rw-r--r--Source/WebCore/rendering/RenderThemeMac.h42
-rw-r--r--Source/WebCore/rendering/RenderThemeMac.mm112
-rw-r--r--Source/WebCore/rendering/RenderThemeSafari.cpp40
-rw-r--r--Source/WebCore/rendering/RenderThemeSafari.h24
-rw-r--r--Source/WebCore/rendering/RenderThemeWin.cpp36
-rw-r--r--Source/WebCore/rendering/RenderThemeWin.h24
-rw-r--r--Source/WebCore/rendering/RenderThemeWinCE.cpp18
-rw-r--r--Source/WebCore/rendering/RenderThemeWinCE.h20
-rw-r--r--Source/WebCore/rendering/RenderTreeAsText.cpp86
-rw-r--r--Source/WebCore/rendering/RenderTreeAsText.h2
-rw-r--r--Source/WebCore/rendering/RenderVideo.cpp15
-rw-r--r--Source/WebCore/rendering/RenderView.cpp155
-rw-r--r--Source/WebCore/rendering/RenderView.h70
-rw-r--r--Source/WebCore/rendering/RenderWidget.cpp29
-rw-r--r--Source/WebCore/rendering/RenderWidget.h2
-rw-r--r--Source/WebCore/rendering/RenderingAllInOne.cpp1
-rw-r--r--Source/WebCore/rendering/RootInlineBox.cpp77
-rw-r--r--Source/WebCore/rendering/RootInlineBox.h22
-rw-r--r--Source/WebCore/rendering/mathml/RenderMathMLBlock.cpp174
-rw-r--r--Source/WebCore/rendering/mathml/RenderMathMLBlock.h40
-rw-r--r--Source/WebCore/rendering/mathml/RenderMathMLFenced.cpp6
-rw-r--r--Source/WebCore/rendering/mathml/RenderMathMLFraction.cpp46
-rw-r--r--Source/WebCore/rendering/mathml/RenderMathMLOperator.cpp125
-rw-r--r--Source/WebCore/rendering/mathml/RenderMathMLOperator.h18
-rw-r--r--Source/WebCore/rendering/mathml/RenderMathMLRoot.cpp233
-rw-r--r--Source/WebCore/rendering/mathml/RenderMathMLRoot.h13
-rw-r--r--Source/WebCore/rendering/mathml/RenderMathMLRow.cpp81
-rw-r--r--Source/WebCore/rendering/mathml/RenderMathMLRow.h11
-rw-r--r--Source/WebCore/rendering/mathml/RenderMathMLSquareRoot.cpp198
-rw-r--r--Source/WebCore/rendering/mathml/RenderMathMLSquareRoot.h16
-rw-r--r--Source/WebCore/rendering/mathml/RenderMathMLSubSup.cpp46
-rw-r--r--Source/WebCore/rendering/mathml/RenderMathMLSubSup.h4
-rw-r--r--Source/WebCore/rendering/mathml/RenderMathMLUnderOver.cpp22
-rw-r--r--Source/WebCore/rendering/mathml/RenderMathMLUnderOver.h1
-rw-r--r--Source/WebCore/rendering/style/BorderValue.h25
-rw-r--r--Source/WebCore/rendering/style/CollapsedBorderValue.h9
-rw-r--r--Source/WebCore/rendering/style/FillLayer.cpp21
-rw-r--r--Source/WebCore/rendering/style/FillLayer.h22
-rw-r--r--Source/WebCore/rendering/style/KeyframeList.cpp4
-rw-r--r--Source/WebCore/rendering/style/KeyframeList.h21
-rw-r--r--Source/WebCore/rendering/style/OutlineValue.h2
-rw-r--r--Source/WebCore/rendering/style/QuotesData.cpp4
-rw-r--r--Source/WebCore/rendering/style/RenderStyle.cpp154
-rw-r--r--Source/WebCore/rendering/style/RenderStyle.h151
-rw-r--r--Source/WebCore/rendering/style/RenderStyleConstants.h8
-rw-r--r--Source/WebCore/rendering/style/SVGRenderStyle.h1
-rw-r--r--Source/WebCore/rendering/style/ShadowData.cpp26
-rw-r--r--Source/WebCore/rendering/style/ShadowData.h19
-rw-r--r--Source/WebCore/rendering/style/StyleCachedImageSet.cpp121
-rw-r--r--Source/WebCore/rendering/style/StyleCachedImageSet.h86
-rw-r--r--Source/WebCore/rendering/style/StyleCustomFilterProgram.h10
-rw-r--r--Source/WebCore/rendering/style/StyleFlexibleBoxData.cpp22
-rw-r--r--Source/WebCore/rendering/style/StyleFlexibleBoxData.h10
-rw-r--r--Source/WebCore/rendering/style/StyleGeneratedImage.cpp4
-rw-r--r--Source/WebCore/rendering/style/StyleImage.h4
-rw-r--r--Source/WebCore/rendering/style/StylePendingImage.h6
-rw-r--r--Source/WebCore/rendering/style/StyleRareNonInheritedData.cpp2
-rw-r--r--Source/WebCore/rendering/style/StyleRareNonInheritedData.h2
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGAllInOne.cpp2
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGContainer.cpp4
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGContainer.h8
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGEllipse.cpp168
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGEllipse.h65
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGForeignObject.cpp12
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGForeignObject.h2
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGInline.cpp2
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGInline.h2
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGInlineText.cpp29
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGInlineText.h2
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGModelObject.cpp2
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGModelObject.h2
-rwxr-xr-xSource/WebCore/rendering/svg/RenderSVGRect.cpp12
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGRect.h1
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGResourceClipper.cpp13
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGResourceContainer.cpp3
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp6
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGResourceGradient.cpp12
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGResourceMarker.cpp3
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGResourceMasker.cpp14
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGResourcePattern.cpp14
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGRoot.cpp65
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGRoot.h12
-rwxr-xr-xSource/WebCore/rendering/svg/RenderSVGShape.cpp18
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGShape.h1
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGText.cpp13
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGText.h7
-rw-r--r--Source/WebCore/rendering/svg/SVGImageBufferTools.cpp165
-rw-r--r--Source/WebCore/rendering/svg/SVGImageBufferTools.h65
-rw-r--r--Source/WebCore/rendering/svg/SVGInlineTextBox.cpp30
-rw-r--r--Source/WebCore/rendering/svg/SVGInlineTextBox.h4
-rw-r--r--Source/WebCore/rendering/svg/SVGPathData.cpp10
-rw-r--r--Source/WebCore/rendering/svg/SVGRenderSupport.cpp45
-rw-r--r--Source/WebCore/rendering/svg/SVGRenderSupport.h2
-rwxr-xr-xSource/WebCore/rendering/svg/SVGRenderTreeAsText.cpp10
-rw-r--r--Source/WebCore/rendering/svg/SVGRenderingContext.cpp131
-rw-r--r--Source/WebCore/rendering/svg/SVGRenderingContext.h17
235 files changed, 8382 insertions, 5110 deletions
diff --git a/Source/WebCore/rendering/AutoTableLayout.cpp b/Source/WebCore/rendering/AutoTableLayout.cpp
index 2fa064f40..744a12b91 100644
--- a/Source/WebCore/rendering/AutoTableLayout.cpp
+++ b/Source/WebCore/rendering/AutoTableLayout.cpp
@@ -251,8 +251,8 @@ void AutoTableLayout::computePreferredLogicalWidths(LayoutUnit& minWidth, Layout
if (scaleColumns) {
maxNonPercent = maxNonPercent * 100 / max(remainingPercent, epsilon);
- maxWidth = max(maxWidth, static_cast<int>(min(maxNonPercent, numeric_limits<LayoutUnit>::max() / 2.0f)));
- maxWidth = max(maxWidth, static_cast<int>(min(maxPercent, numeric_limits<LayoutUnit>::max() / 2.0f)));
+ maxWidth = max<int>(maxWidth, static_cast<int>(min(maxNonPercent, MAX_LAYOUT_UNIT / 2.0f)));
+ maxWidth = max<int>(maxWidth, static_cast<int>(min(maxPercent, MAX_LAYOUT_UNIT / 2.0f)));
}
maxWidth = max<int>(maxWidth, spanMaxLogicalWidth);
@@ -266,8 +266,8 @@ void AutoTableLayout::computePreferredLogicalWidths(LayoutUnit& minWidth, Layout
minWidth = max<int>(minWidth, tableLogicalWidth.value());
maxWidth = minWidth;
} else if (!remainingPercent && maxNonPercent) {
- // if there was no remaining percent, maxWidth is invalid.
- maxWidth = intMaxForLength;
+ // if there was no remaining percent, maxWidth is invalid
+ maxWidth = MAX_LAYOUT_UNIT;
}
Length tableLogicalMinWidth = m_table->style()->logicalMinWidth();
@@ -402,13 +402,23 @@ int AutoTableLayout::calcEffectiveLogicalWidth()
}
} else if (allColsArePercent) {
// In this case, we just split the colspan's min amd max widths following the percentage.
+ int allocatedMinLogicalWidth = 0;
+ float allocatedMaxLogicalWidth = 0;
for (unsigned pos = effCol; pos < lastCol; ++pos) {
ASSERT(m_layoutStruct[pos].logicalWidth.isPercent() || m_layoutStruct[pos].effectiveLogicalWidth.isPercent());
// |allColsArePercent| means that either the logicalWidth *or* the effectiveLogicalWidth are percents, handle both of them here.
float percent = m_layoutStruct[pos].logicalWidth.isPercent() ? m_layoutStruct[pos].logicalWidth.percent() : m_layoutStruct[pos].effectiveLogicalWidth.percent();
- m_layoutStruct[pos].effectiveMinLogicalWidth = max(m_layoutStruct[pos].effectiveMinLogicalWidth, static_cast<int>(percent * cellMinLogicalWidth / totalPercent));
- m_layoutStruct[pos].effectiveMaxLogicalWidth = percent * cellMaxLogicalWidth / totalPercent;
+ int columnMinLogicalWidth = static_cast<int>(percent * cellMinLogicalWidth / totalPercent);
+ float columnMaxLogicalWidth = percent * cellMaxLogicalWidth / totalPercent;
+ m_layoutStruct[pos].effectiveMinLogicalWidth = max(m_layoutStruct[pos].effectiveMinLogicalWidth, columnMinLogicalWidth);
+ m_layoutStruct[pos].effectiveMaxLogicalWidth = columnMaxLogicalWidth;
+ allocatedMinLogicalWidth += columnMinLogicalWidth;
+ allocatedMaxLogicalWidth += columnMaxLogicalWidth;
}
+ ASSERT(allocatedMinLogicalWidth <= cellMinLogicalWidth);
+ ASSERT(allocatedMaxLogicalWidth <= cellMaxLogicalWidth);
+ cellMinLogicalWidth -= allocatedMinLogicalWidth;
+ cellMaxLogicalWidth -= allocatedMaxLogicalWidth;
} else {
float remainingMaxLogicalWidth = spanMaxLogicalWidth;
int remainingMinLogicalWidth = spanMinLogicalWidth;
@@ -551,7 +561,7 @@ void AutoTableLayout::layout()
for (size_t i = 0; i < nEffCols; ++i) {
Length& logicalWidth = m_layoutStruct[i].effectiveLogicalWidth;
if (logicalWidth.isPercent()) {
- int cellLogicalWidth = max<int>(m_layoutStruct[i].effectiveMinLogicalWidth, logicalWidth.calcMinValue(tableLogicalWidth));
+ int cellLogicalWidth = max<int>(m_layoutStruct[i].effectiveMinLogicalWidth, minimumValueForLength(logicalWidth, tableLogicalWidth));
available += m_layoutStruct[i].computedLogicalWidth - cellLogicalWidth;
m_layoutStruct[i].computedLogicalWidth = cellLogicalWidth;
}
diff --git a/Source/WebCore/rendering/ColumnInfo.h b/Source/WebCore/rendering/ColumnInfo.h
index c8191cf1d..e462a84a5 100644
--- a/Source/WebCore/rendering/ColumnInfo.h
+++ b/Source/WebCore/rendering/ColumnInfo.h
@@ -83,10 +83,10 @@ public:
m_maximumDistanceBetweenForcedBreaks = 0;
m_forcedBreakOffset = 0;
}
- void addForcedBreak(int offsetFromFirstPage)
+ void addForcedBreak(LayoutUnit offsetFromFirstPage)
{
ASSERT(!m_columnHeight);
- int distanceFromLastBreak = offsetFromFirstPage - m_forcedBreakOffset;
+ LayoutUnit distanceFromLastBreak = offsetFromFirstPage - m_forcedBreakOffset;
if (!distanceFromLastBreak)
return;
m_forcedBreaks++;
diff --git a/Source/WebCore/rendering/EllipsisBox.cpp b/Source/WebCore/rendering/EllipsisBox.cpp
index e403fe667..5969a3222 100644
--- a/Source/WebCore/rendering/EllipsisBox.cpp
+++ b/Source/WebCore/rendering/EllipsisBox.cpp
@@ -33,7 +33,7 @@ namespace WebCore {
void EllipsisBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutUnit lineTop, LayoutUnit lineBottom)
{
GraphicsContext* context = paintInfo.context;
- RenderStyle* style = m_renderer->style(m_firstLine);
+ RenderStyle* style = m_renderer->style(isFirstLineStyle());
Color textColor = style->visitedDependentColor(CSSPropertyColor);
if (textColor != context->fillColor())
context->setFillColor(textColor, style->colorSpace());
@@ -68,17 +68,17 @@ void EllipsisBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, La
// Paint the markup box
LayoutPoint adjustedPaintOffset = paintOffset;
adjustedPaintOffset.move(x() + m_logicalWidth - m_markupBox->x(),
- y() + style->fontMetrics().ascent() - (m_markupBox->y() + m_markupBox->renderer()->style(m_firstLine)->fontMetrics().ascent()));
+ y() + style->fontMetrics().ascent() - (m_markupBox->y() + m_markupBox->renderer()->style(isFirstLineStyle())->fontMetrics().ascent()));
m_markupBox->paint(paintInfo, adjustedPaintOffset, lineTop, lineBottom);
}
}
IntRect EllipsisBox::selectionRect()
{
- RenderStyle* style = m_renderer->style(m_firstLine);
+ RenderStyle* style = m_renderer->style(isFirstLineStyle());
const Font& font = style->font();
// FIXME: Why is this always LTR? Fix by passing correct text run flags below.
- return enclosingIntRect(font.selectionRectForText(RenderBlock::constructTextRun(renderer(), font, m_str, style, TextRun::AllowTrailingExpansion), IntPoint(x(), y() + root()->selectionTop()), root()->selectionHeight()));
+ return enclosingIntRect(font.selectionRectForText(RenderBlock::constructTextRun(renderer(), font, m_str, style, TextRun::AllowTrailingExpansion), IntPoint(x(), y() + root()->selectionTopAdjustedForPrecedingBlock()), root()->selectionHeightAdjustedForPrecedingBlock()));
}
void EllipsisBox::paintSelection(GraphicsContext* context, const LayoutPoint& paintOffset, RenderStyle* style, const Font& font)
@@ -108,9 +108,9 @@ bool EllipsisBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu
// Hit test the markup box.
if (m_markupBox) {
- RenderStyle* style = m_renderer->style(m_firstLine);
+ RenderStyle* style = m_renderer->style(isFirstLineStyle());
LayoutUnit mtx = adjustedLocation.x() + m_logicalWidth - m_markupBox->x();
- LayoutUnit mty = adjustedLocation.y() + style->fontMetrics().ascent() - (m_markupBox->y() + m_markupBox->renderer()->style(m_firstLine)->fontMetrics().ascent());
+ LayoutUnit mty = adjustedLocation.y() + style->fontMetrics().ascent() - (m_markupBox->y() + m_markupBox->renderer()->style(isFirstLineStyle())->fontMetrics().ascent());
if (m_markupBox->nodeAtPoint(request, result, pointInContainer, LayoutPoint(mtx, mty), lineTop, lineBottom)) {
renderer()->updateHitTestResult(result, pointInContainer - LayoutSize(mtx, mty));
return true;
diff --git a/Source/WebCore/rendering/FilterEffectObserver.h b/Source/WebCore/rendering/FilterEffectObserver.h
deleted file mode 100644
index 7573497ce..000000000
--- a/Source/WebCore/rendering/FilterEffectObserver.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2011 Adobe Systems Incorporated. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
- * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
- * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
- * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef FilterEffectObserver_h
-#define FilterEffectObserver_h
-
-#if ENABLE(CSS_FILTERS)
-
-namespace WebCore {
-
-class FilterEffectObserver {
-public:
- virtual ~FilterEffectObserver() { }
- virtual void filterNeedsRepaint() = 0;
-};
-
-} // namespace WebCore
-
-#endif // ENABLE(CSS_FILTERS)
-
-#endif // FilterEffectObserver_h
diff --git a/Source/WebCore/rendering/FilterEffectRenderer.cpp b/Source/WebCore/rendering/FilterEffectRenderer.cpp
index af5ecaf27..54e8c1cf5 100644
--- a/Source/WebCore/rendering/FilterEffectRenderer.cpp
+++ b/Source/WebCore/rendering/FilterEffectRenderer.cpp
@@ -35,7 +35,6 @@
#include "FEDropShadow.h"
#include "FEGaussianBlur.h"
#include "FEMerge.h"
-#include "FilterEffectObserver.h"
#include "FloatConversion.h"
#include "RenderLayer.h"
@@ -46,6 +45,7 @@
#include "CustomFilterProgram.h"
#include "CustomFilterOperation.h"
#include "FECustomFilter.h"
+#include "FrameView.h"
#include "Settings.h"
#endif
@@ -65,8 +65,15 @@ static inline void lastMatrixRow(Vector<float>& parameters)
parameters.append(1);
parameters.append(0);
}
-
-
+
+inline bool isFilterSizeValid(FloatRect rect)
+{
+ if (rect.width() < 0 || rect.width() > kMaxFilterSize
+ || rect.height() < 0 || rect.height() > kMaxFilterSize)
+ return false;
+ return true;
+}
+
#if ENABLE(CSS_SHADERS) && ENABLE(WEBGL)
static bool isCSSCustomFilterEnabled(Document* document)
{
@@ -76,9 +83,16 @@ static bool isCSSCustomFilterEnabled(Document* document)
}
#endif
-FilterEffectRenderer::FilterEffectRenderer(FilterEffectObserver* observer)
- : m_observer(observer)
+FilterEffectRenderer::FilterEffectRenderer()
+ : m_topOutset(0)
+ , m_rightOutset(0)
+ , m_bottomOutset(0)
+ , m_leftOutset(0)
, m_graphicsBufferAttached(false)
+ , m_hasFilterThatMovesPixels(false)
+#if ENABLE(CSS_SHADERS)
+ , m_hasCustomShaderFilter(false)
+#endif
{
setFilterResolution(FloatSize(1, 1));
m_sourceGraphic = SourceGraphic::create(this);
@@ -86,9 +100,6 @@ FilterEffectRenderer::FilterEffectRenderer(FilterEffectObserver* observer)
FilterEffectRenderer::~FilterEffectRenderer()
{
-#if ENABLE(CSS_SHADERS)
- removeCustomFilterClients();
-#endif
}
GraphicsContext* FilterEffectRenderer::inputContext()
@@ -96,14 +107,18 @@ GraphicsContext* FilterEffectRenderer::inputContext()
return sourceImage() ? sourceImage()->context() : 0;
}
-void FilterEffectRenderer::build(Document* document, const FilterOperations& operations)
+bool FilterEffectRenderer::build(Document* document, const FilterOperations& operations)
{
#if !ENABLE(CSS_SHADERS) || !ENABLE(WEBGL)
UNUSED_PARAM(document);
-#else
- CustomFilterProgramList cachedCustomFilterPrograms;
#endif
+#if ENABLE(CSS_SHADERS)
+ m_hasCustomShaderFilter = false;
+#endif
+ m_hasFilterThatMovesPixels = operations.hasFilterThatMovesPixels();
+ if (m_hasFilterThatMovesPixels)
+ operations.getOutsets(m_topOutset, m_rightOutset, m_bottomOutset, m_leftOutset);
m_effects.clear();
RefPtr<FilterEffect> previousEffect;
@@ -237,7 +252,7 @@ void FilterEffectRenderer::build(Document* document, const FilterOperations& ope
}
case FilterOperation::BLUR: {
BlurFilterOperation* blurOperation = static_cast<BlurFilterOperation*>(filterOperation);
- float stdDeviation = blurOperation->stdDeviation().calcFloatValue(0);
+ float stdDeviation = floatValueForLength(blurOperation->stdDeviation(), 0);
effect = FEGaussianBlur::create(this, stdDeviation, stdDeviation);
break;
}
@@ -255,12 +270,11 @@ void FilterEffectRenderer::build(Document* document, const FilterOperations& ope
CustomFilterOperation* customFilterOperation = static_cast<CustomFilterOperation*>(filterOperation);
RefPtr<CustomFilterProgram> program = customFilterOperation->program();
- cachedCustomFilterPrograms.append(program);
- program->addClient(this);
if (program->isLoaded()) {
- effect = FECustomFilter::create(this, document, program, customFilterOperation->parameters(),
+ effect = FECustomFilter::create(this, document->view()->root()->hostWindow(), program, customFilterOperation->parameters(),
customFilterOperation->meshRows(), customFilterOperation->meshColumns(),
customFilterOperation->meshBoxType(), customFilterOperation->meshType());
+ m_hasCustomShaderFilter = true;
}
#endif
break;
@@ -281,51 +295,43 @@ void FilterEffectRenderer::build(Document* document, const FilterOperations& ope
}
}
- // If we didn't make a real filter, create a null-op (FEMerge with one input).
+ // If we didn't make any effects, tell our caller we are not valid
if (!previousEffect)
- m_effects.append(FEMerge::create(this));
+ return false;
m_effects.first()->inputEffects().append(m_sourceGraphic);
setMaxEffectRects(m_sourceDrawingRegion);
-#if ENABLE(CSS_SHADERS) && ENABLE(WEBGL)
- removeCustomFilterClients();
- m_cachedCustomFilterPrograms.swap(cachedCustomFilterPrograms);
-#endif
+ return true;
}
-void FilterEffectRenderer::updateBackingStore(const FloatRect& filterRect)
+bool FilterEffectRenderer::updateBackingStoreRect(const FloatRect& filterRect)
{
- if (!filterRect.isZero()) {
+ if (!filterRect.isZero() && isFilterSizeValid(filterRect)) {
FloatRect currentSourceRect = sourceImageRect();
- if (filterRect != currentSourceRect)
+ if (filterRect != currentSourceRect) {
setSourceImageRect(filterRect);
+ return true;
+ }
}
+ return false;
}
-#if ENABLE(CSS_SHADERS)
-void FilterEffectRenderer::notifyCustomFilterProgramLoaded(CustomFilterProgram*)
-{
- m_observer->filterNeedsRepaint();
-}
-
-void FilterEffectRenderer::removeCustomFilterClients()
-{
- for (CustomFilterProgramList::iterator iter = m_cachedCustomFilterPrograms.begin(), end = m_cachedCustomFilterPrograms.end(); iter != end; ++iter)
- iter->get()->removeClient(this);
-}
-#endif
-
-void FilterEffectRenderer::prepare()
+void FilterEffectRenderer::allocateBackingStoreIfNeeded()
{
// At this point the effect chain has been built, and the
// source image sizes set. We just need to attach the graphic
// buffer if we have not yet done so.
if (!m_graphicsBufferAttached) {
IntSize logicalSize(m_sourceDrawingRegion.width(), m_sourceDrawingRegion.height());
- setSourceImage(ImageBuffer::create(logicalSize, 1, ColorSpaceDeviceRGB, renderingMode()));
+ if (!sourceImage() || sourceImage()->logicalSize() != logicalSize)
+ setSourceImage(ImageBuffer::create(logicalSize, 1, ColorSpaceDeviceRGB, renderingMode()));
m_graphicsBufferAttached = true;
}
+}
+
+void FilterEffectRenderer::clearIntermediateResults()
+{
m_sourceGraphic->clearResult();
for (size_t i = 0; i < m_effects.size(); ++i)
m_effects[i]->clearResult();
@@ -336,49 +342,95 @@ void FilterEffectRenderer::apply()
lastEffect()->apply();
}
+LayoutRect FilterEffectRenderer::computeSourceImageRectForDirtyRect(const LayoutRect& filterBoxRect, const LayoutRect& dirtyRect)
+{
+#if ENABLE(CSS_SHADERS)
+ if (hasCustomShaderFilter()) {
+ // When we have at least a custom shader in the chain, we need to compute the whole source image, because the shader can
+ // reference any pixel and we cannot control that.
+ return filterBoxRect;
+ }
+#endif
+ // The result of this function is the area in the "filterBoxRect" that needs to be repainted, so that we fully cover the "dirtyRect".
+ LayoutRect rectForRepaint = dirtyRect;
+ if (hasFilterThatMovesPixels()) {
+ // Note that the outsets are reversed here because we are going backwards -> we have the dirty rect and
+ // need to find out what is the rectangle that might influence the result inside that dirty rect.
+ rectForRepaint.move(-m_rightOutset, -m_bottomOutset);
+ rectForRepaint.expand(m_leftOutset + m_rightOutset, m_topOutset + m_bottomOutset);
+ }
+ rectForRepaint.intersect(filterBoxRect);
+ return rectForRepaint;
+}
-GraphicsContext* FilterEffectRendererHelper::beginFilterEffect(RenderLayer* renderLayer, GraphicsContext* oldContext, const LayoutRect& filterRect)
+bool FilterEffectRendererHelper::prepareFilterEffect(RenderLayer* renderLayer, const LayoutRect& filterBoxRect, const LayoutRect& dirtyRect, const LayoutRect& layerRepaintRect)
{
- ASSERT(m_haveFilterEffect && renderLayer->filter());
- m_savedGraphicsContext = oldContext;
+ ASSERT(m_haveFilterEffect && renderLayer->filterRenderer());
m_renderLayer = renderLayer;
- m_paintOffset = filterRect.location();
-
- FloatRect filterSourceRect = filterRect;
- filterSourceRect.setLocation(LayoutPoint());
+ m_repaintRect = dirtyRect;
+
+ FilterEffectRenderer* filter = renderLayer->filterRenderer();
+ LayoutRect filterSourceRect = filter->computeSourceImageRectForDirtyRect(filterBoxRect, dirtyRect);
+ m_paintOffset = filterSourceRect.location();
+
+ if (filterSourceRect.isEmpty()) {
+ // The dirty rect is not in view, just bail out.
+ m_haveFilterEffect = false;
+ return false;
+ }
- FilterEffectRenderer* filter = renderLayer->filter();
- filter->updateBackingStore(filterSourceRect);
- filter->prepare();
+ bool hasUpdatedBackingStore = filter->updateBackingStoreRect(filterSourceRect);
+ if (filter->hasFilterThatMovesPixels()) {
+ if (hasUpdatedBackingStore)
+ m_repaintRect = filterSourceRect;
+ else {
+ m_repaintRect.unite(layerRepaintRect);
+ m_repaintRect.intersect(filterSourceRect);
+ }
+ }
+ return true;
+}
+
+GraphicsContext* FilterEffectRendererHelper::beginFilterEffect(GraphicsContext* oldContext)
+{
+ ASSERT(m_renderLayer);
+ FilterEffectRenderer* filter = m_renderLayer->filterRenderer();
+ filter->allocateBackingStoreIfNeeded();
// Paint into the context that represents the SourceGraphic of the filter.
GraphicsContext* sourceGraphicsContext = filter->inputContext();
- if (!sourceGraphicsContext) {
- // Could not allocate a new graphics context. Disable the filters and continue.
+ if (!sourceGraphicsContext || !isFilterSizeValid(filter->filterRegion())) {
+ // Disable the filters and continue.
m_haveFilterEffect = false;
- return m_savedGraphicsContext;
+ return oldContext;
}
+ m_savedGraphicsContext = oldContext;
+
+ // Translate the context so that the contents of the layer is captuterd in the offscreen memory buffer.
sourceGraphicsContext->save();
- sourceGraphicsContext->translate(-filterRect.x(), -filterRect.y());
- sourceGraphicsContext->clearRect(filterRect);
+ sourceGraphicsContext->translate(-m_paintOffset.x(), -m_paintOffset.y());
+ sourceGraphicsContext->clearRect(m_repaintRect);
+ sourceGraphicsContext->clip(m_repaintRect);
return sourceGraphicsContext;
}
GraphicsContext* FilterEffectRendererHelper::applyFilterEffect()
{
- ASSERT(m_haveFilterEffect && m_renderLayer->filter());
- FilterEffectRenderer* filter = m_renderLayer->filter();
- filter->apply();
-
+ ASSERT(m_haveFilterEffect && m_renderLayer->filterRenderer());
+ FilterEffectRenderer* filter = m_renderLayer->filterRenderer();
filter->inputContext()->restore();
+
+ filter->apply();
// Get the filtered output and draw it in place.
- IntRect destRect = filter->outputRect();
+ LayoutRect destRect = filter->outputRect();
destRect.move(m_paintOffset.x(), m_paintOffset.y());
- m_savedGraphicsContext->drawImageBuffer(filter->output(), m_renderLayer->renderer()->style()->colorSpace(), destRect, CompositeSourceOver);
+ m_savedGraphicsContext->drawImageBuffer(filter->output(), m_renderLayer->renderer()->style()->colorSpace(), pixelSnappedIntRect(destRect), CompositeSourceOver);
+
+ filter->clearIntermediateResults();
return m_savedGraphicsContext;
}
diff --git a/Source/WebCore/rendering/FilterEffectRenderer.h b/Source/WebCore/rendering/FilterEffectRenderer.h
index b0105f248..c6266f628 100644
--- a/Source/WebCore/rendering/FilterEffectRenderer.h
+++ b/Source/WebCore/rendering/FilterEffectRenderer.h
@@ -41,17 +41,12 @@
#include <wtf/RefCounted.h>
#include <wtf/RefPtr.h>
-#if ENABLE(CSS_SHADERS)
-#include "CustomFilterProgramClient.h"
-#endif
-
namespace WebCore {
typedef Vector<RefPtr<FilterEffect> > FilterEffectList;
class CachedShader;
class CustomFilterProgram;
class Document;
-class FilterEffectObserver;
class GraphicsContext;
class RenderLayer;
@@ -67,26 +62,26 @@ public:
bool haveFilterEffect() const { return m_haveFilterEffect; }
bool hasStartedFilterEffect() const { return m_savedGraphicsContext; }
- GraphicsContext* beginFilterEffect(RenderLayer*, GraphicsContext* oldContext, const LayoutRect& filterRect);
+ bool prepareFilterEffect(RenderLayer*, const LayoutRect& filterBoxRect, const LayoutRect& dirtyRect, const LayoutRect& layerRepaintRect);
+ GraphicsContext* beginFilterEffect(GraphicsContext* oldContext);
GraphicsContext* applyFilterEffect();
+ const LayoutRect& repaintRect() const { return m_repaintRect; }
private:
GraphicsContext* m_savedGraphicsContext;
RenderLayer* m_renderLayer;
LayoutPoint m_paintOffset;
+ LayoutRect m_repaintRect;
bool m_haveFilterEffect;
};
class FilterEffectRenderer : public Filter
-#if ENABLE(CSS_SHADERS)
- , public CustomFilterProgramClient
-#endif
{
WTF_MAKE_FAST_ALLOCATED;
public:
- static PassRefPtr<FilterEffectRenderer> create(FilterEffectObserver* observer)
+ static PassRefPtr<FilterEffectRenderer> create()
{
- return adoptRef(new FilterEffectRenderer(observer));
+ return adoptRef(new FilterEffectRenderer());
}
virtual void setSourceImageRect(const FloatRect& sourceImageRect)
@@ -104,21 +99,21 @@ public:
GraphicsContext* inputContext();
ImageBuffer* output() const { return lastEffect()->asImageBuffer(); }
- void build(Document*, const FilterOperations&);
- void updateBackingStore(const FloatRect& filterRect);
- void prepare();
+ bool build(Document*, const FilterOperations&);
+ bool updateBackingStoreRect(const FloatRect& filterRect);
+ void allocateBackingStoreIfNeeded();
+ void clearIntermediateResults();
void apply();
IntRect outputRect() const { return lastEffect()->hasResult() ? lastEffect()->requestedRegionOfInputImageData(IntRect(m_filterRegion)) : IntRect(); }
-private:
+ bool hasFilterThatMovesPixels() const { return m_hasFilterThatMovesPixels; }
+ LayoutRect computeSourceImageRectForDirtyRect(const LayoutRect& filterBoxRect, const LayoutRect& dirtyRect);
+
#if ENABLE(CSS_SHADERS)
- // Implementation of the CustomFilterProgramClient interface.
- virtual void notifyCustomFilterProgramLoaded(CustomFilterProgram*);
-
- void removeCustomFilterClients();
+ bool hasCustomShaderFilter() const { return m_hasCustomShaderFilter; }
#endif
-
+private:
void setMaxEffectRects(const FloatRect& effectRect)
{
for (size_t i = 0; i < m_effects.size(); ++i) {
@@ -133,7 +128,7 @@ private:
return 0;
}
- FilterEffectRenderer(FilterEffectObserver*);
+ FilterEffectRenderer();
virtual ~FilterEffectRenderer();
FloatRect m_sourceDrawingRegion;
@@ -141,14 +136,17 @@ private:
FilterEffectList m_effects;
RefPtr<SourceGraphic> m_sourceGraphic;
- FilterEffectObserver* m_observer; // No need for a strong references here. It owns us.
-#if ENABLE(CSS_SHADERS) && ENABLE(WEBGL)
- typedef Vector<RefPtr<CustomFilterProgram> > CustomFilterProgramList;
- CustomFilterProgramList m_cachedCustomFilterPrograms;
-#endif
+ int m_topOutset;
+ int m_rightOutset;
+ int m_bottomOutset;
+ int m_leftOutset;
bool m_graphicsBufferAttached;
+ bool m_hasFilterThatMovesPixels;
+#if ENABLE(CSS_SHADERS)
+ bool m_hasCustomShaderFilter;
+#endif
};
} // namespace WebCore
diff --git a/Source/WebCore/rendering/FixedTableLayout.cpp b/Source/WebCore/rendering/FixedTableLayout.cpp
index fe97c636f..187557ed1 100644
--- a/Source/WebCore/rendering/FixedTableLayout.cpp
+++ b/Source/WebCore/rendering/FixedTableLayout.cpp
@@ -77,65 +77,68 @@ FixedTableLayout::FixedTableLayout(RenderTable* table)
{
}
+static RenderObject* nextCol(RenderObject* child)
+{
+ // If child is a colgroup, the next col is the colgroup's first child col.
+ if (RenderObject* next = child->firstChild())
+ return next;
+ // Otherwise it's the next col along.
+ if (RenderObject* next = child->nextSibling())
+ return next;
+ // Failing that, the child is the last col in a colgroup, so the next col is the next col/colgroup after its colgroup.
+ if (child->parent()->isTableCol())
+ return child->parent()->nextSibling();
+ return 0;
+}
+
int FixedTableLayout::calcWidthArray(int)
{
int usedWidth = 0;
// iterate over all <col> elements
- RenderObject* child = m_table->firstChild();
unsigned nEffCols = m_table->numEffCols();
m_width.resize(nEffCols);
m_width.fill(Length(Auto));
unsigned currentEffectiveColumn = 0;
- Length grpWidth;
- while (child && child->isTableCol()) {
+ for (RenderObject* child = m_table->firstChild();child && child->isTableCol(); child = nextCol(child)) {
+
+ // Width specified by column-groups does not affect column width in fixed layout tables
RenderTableCol* col = toRenderTableCol(child);
- if (col->firstChild())
- grpWidth = col->style()->logicalWidth();
- else {
- Length w = col->style()->logicalWidth();
- if (w.isAuto())
- w = grpWidth;
- int effWidth = 0;
- if (w.isFixed() && w.value() > 0)
- effWidth = w.value();
-
- unsigned span = col->span();
- while (span) {
- unsigned spanInCurrentEffectiveColumn;
- if (currentEffectiveColumn >= nEffCols) {
- m_table->appendColumn(span);
+ col->computePreferredLogicalWidths();
+
+ if (col->isTableColGroup())
+ continue;
+
+ Length colStyleLogicalWidth = col->style()->logicalWidth();
+ int effectiveColWidth = 0;
+ if (colStyleLogicalWidth.isFixed() && colStyleLogicalWidth.value() > 0)
+ effectiveColWidth = colStyleLogicalWidth.value();
+
+ unsigned span = col->span();
+ while (span) {
+ unsigned spanInCurrentEffectiveColumn;
+ if (currentEffectiveColumn >= nEffCols) {
+ m_table->appendColumn(span);
+ nEffCols++;
+ m_width.append(Length());
+ spanInCurrentEffectiveColumn = span;
+ } else {
+ if (span < m_table->spanOfEffCol(currentEffectiveColumn)) {
+ m_table->splitColumn(currentEffectiveColumn, span);
nEffCols++;
m_width.append(Length());
- spanInCurrentEffectiveColumn = span;
- } else {
- if (span < m_table->spanOfEffCol(currentEffectiveColumn)) {
- m_table->splitColumn(currentEffectiveColumn, span);
- nEffCols++;
- m_width.append(Length());
- }
- spanInCurrentEffectiveColumn = m_table->spanOfEffCol(currentEffectiveColumn);
}
- if ((w.isFixed() || w.isPercent()) && w.isPositive()) {
- m_width[currentEffectiveColumn] = w;
- m_width[currentEffectiveColumn] *= spanInCurrentEffectiveColumn;
- usedWidth += effWidth * spanInCurrentEffectiveColumn;
- }
- span -= spanInCurrentEffectiveColumn;
- currentEffectiveColumn++;
+ spanInCurrentEffectiveColumn = m_table->spanOfEffCol(currentEffectiveColumn);
}
+ if ((colStyleLogicalWidth.isFixed() || colStyleLogicalWidth.isPercent()) && colStyleLogicalWidth.isPositive()) {
+ m_width[currentEffectiveColumn] = colStyleLogicalWidth;
+ m_width[currentEffectiveColumn] *= spanInCurrentEffectiveColumn;
+ usedWidth += effectiveColWidth * spanInCurrentEffectiveColumn;
+ }
+ span -= spanInCurrentEffectiveColumn;
+ currentEffectiveColumn++;
}
- col->computePreferredLogicalWidths();
-
- RenderObject* next = child->firstChild();
- if (!next)
- next = child->nextSibling();
- if (!next && child->parent()->isTableCol()) {
- next = child->parent()->nextSibling();
- grpWidth = Length();
- }
- child = next;
}
// Iterate over the first row in case some are unspecified.
@@ -143,7 +146,7 @@ int FixedTableLayout::calcWidthArray(int)
if (section) {
unsigned cCol = 0;
RenderObject* firstRow = section->firstChild();
- child = firstRow->firstChild();
+ RenderObject* child = firstRow->firstChild();
while (child) {
if (child->isTableCell()) {
RenderTableCell* cell = toRenderTableCell(child);
@@ -152,9 +155,11 @@ int FixedTableLayout::calcWidthArray(int)
Length w = cell->styleOrColLogicalWidth();
unsigned span = cell->colSpan();
- int effWidth = 0;
- if (w.isFixed() && w.isPositive())
- effWidth = w.value();
+ int effectiveColWidth = 0;
+ if (w.isFixed() && w.isPositive()) {
+ w.setValue(w.value() + cell->borderAndPaddingLogicalWidth());
+ effectiveColWidth = w.value();
+ }
unsigned usedSpan = 0;
unsigned i = 0;
@@ -164,7 +169,7 @@ int FixedTableLayout::calcWidthArray(int)
if (m_width[cCol + i].isAuto() && w.type() != Auto) {
m_width[cCol + i] = w;
m_width[cCol + i] *= eSpan / span;
- usedWidth += effWidth * eSpan / span;
+ usedWidth += effectiveColWidth * eSpan / span;
}
usedSpan += eSpan;
i++;
@@ -241,7 +246,7 @@ void FixedTableLayout::layout()
calcWidth[i] = m_width[i].value();
totalFixedWidth += calcWidth[i];
} else if (m_width[i].isPercent()) {
- calcWidth[i] = m_width[i].calcValue(tableLogicalWidth);
+ calcWidth[i] = valueForLength(m_width[i], tableLogicalWidth);
totalPercentWidth += calcWidth[i];
totalPercent += m_width[i].percent();
} else if (m_width[i].isAuto()) {
diff --git a/Source/WebCore/rendering/FlowThreadController.cpp b/Source/WebCore/rendering/FlowThreadController.cpp
new file mode 100644
index 000000000..cf2207ffe
--- /dev/null
+++ b/Source/WebCore/rendering/FlowThreadController.cpp
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "FlowThreadController.h"
+
+#include "RenderFlowThread.h"
+#include "RenderNamedFlowThread.h"
+#include <wtf/text/AtomicString.h>
+
+namespace WebCore {
+
+PassOwnPtr<FlowThreadController> FlowThreadController::create(RenderView* view)
+{
+ return adoptPtr(new FlowThreadController(view));
+}
+
+FlowThreadController::FlowThreadController(RenderView* view)
+ : m_view(view)
+ , m_currentRenderFlowThread(0)
+ , m_isRenderNamedFlowThreadOrderDirty(false)
+{
+}
+
+FlowThreadController::~FlowThreadController()
+{
+}
+
+RenderNamedFlowThread* FlowThreadController::ensureRenderFlowThreadWithName(const AtomicString& name)
+{
+ if (!m_renderNamedFlowThreadList)
+ m_renderNamedFlowThreadList = adoptPtr(new RenderNamedFlowThreadList());
+ else {
+ for (RenderNamedFlowThreadList::iterator iter = m_renderNamedFlowThreadList->begin(); iter != m_renderNamedFlowThreadList->end(); ++iter) {
+ RenderNamedFlowThread* flowRenderer = *iter;
+ if (flowRenderer->flowThreadName() == name)
+ return flowRenderer;
+ }
+ }
+
+ RenderNamedFlowThread* flowRenderer = new (m_view->renderArena()) RenderNamedFlowThread(m_view->document(), name);
+ flowRenderer->setStyle(RenderFlowThread::createFlowThreadStyle(m_view->style()));
+ m_renderNamedFlowThreadList->add(flowRenderer);
+
+ // Keep the flow renderer as a child of RenderView.
+ m_view->addChild(flowRenderer);
+
+ setIsRenderNamedFlowThreadOrderDirty(true);
+
+ return flowRenderer;
+}
+
+void FlowThreadController::layoutRenderNamedFlowThreads()
+{
+ ASSERT(m_renderNamedFlowThreadList);
+
+ if (isRenderNamedFlowThreadOrderDirty()) {
+ // Arrange the thread list according to dependencies.
+ RenderNamedFlowThreadList sortedList;
+ for (RenderNamedFlowThreadList::iterator iter = m_renderNamedFlowThreadList->begin(); iter != m_renderNamedFlowThreadList->end(); ++iter) {
+ RenderNamedFlowThread* flowRenderer = *iter;
+ if (sortedList.contains(flowRenderer))
+ continue;
+ flowRenderer->pushDependencies(sortedList);
+ sortedList.add(flowRenderer);
+ }
+ m_renderNamedFlowThreadList->swap(sortedList);
+ setIsRenderNamedFlowThreadOrderDirty(false);
+ }
+
+ for (RenderNamedFlowThreadList::iterator iter = m_renderNamedFlowThreadList->begin(); iter != m_renderNamedFlowThreadList->end(); ++iter) {
+ RenderNamedFlowThread* flowRenderer = *iter;
+ flowRenderer->layoutIfNeeded();
+ }
+}
+
+void FlowThreadController::registerNamedFlowContentNode(Node* contentNode, RenderNamedFlowThread* namedFlow)
+{
+ ASSERT(contentNode && contentNode->isElementNode());
+ ASSERT(namedFlow);
+ ASSERT(!m_mapNamedFlowContentNodes.contains(contentNode));
+ ASSERT(!namedFlow->hasContentNode(contentNode));
+ m_mapNamedFlowContentNodes.add(contentNode, namedFlow);
+ namedFlow->registerNamedFlowContentNode(contentNode);
+}
+
+void FlowThreadController::unregisterNamedFlowContentNode(Node* contentNode)
+{
+ ASSERT(contentNode && contentNode->isElementNode());
+ HashMap<Node*, RenderNamedFlowThread*>::iterator it = m_mapNamedFlowContentNodes.find(contentNode);
+ ASSERT(it != m_mapNamedFlowContentNodes.end());
+ ASSERT(it->second);
+ ASSERT(it->second->hasContentNode(contentNode));
+ it->second->unregisterNamedFlowContentNode(contentNode);
+ m_mapNamedFlowContentNodes.remove(contentNode);
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/rendering/FlowThreadController.h b/Source/WebCore/rendering/FlowThreadController.h
new file mode 100644
index 000000000..0c317692f
--- /dev/null
+++ b/Source/WebCore/rendering/FlowThreadController.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef FlowThreadController_h
+#define FlowThreadController_h
+
+#include "RenderView.h"
+#include <wtf/ListHashSet.h>
+#include <wtf/OwnPtr.h>
+
+namespace WebCore {
+
+class RenderFlowThread;
+class RenderNamedFlowThread;
+
+typedef ListHashSet<RenderNamedFlowThread*> RenderNamedFlowThreadList;
+
+class FlowThreadController {
+public:
+ static PassOwnPtr<FlowThreadController> create(RenderView*);
+ ~FlowThreadController();
+
+ RenderFlowThread* currentRenderFlowThread() const { return m_currentRenderFlowThread; }
+ void setCurrentRenderFlowThread(RenderFlowThread* flowThread) { m_currentRenderFlowThread = flowThread; }
+
+ bool isRenderNamedFlowThreadOrderDirty() const { return m_isRenderNamedFlowThreadOrderDirty; }
+ void setIsRenderNamedFlowThreadOrderDirty(bool dirty)
+ {
+ m_isRenderNamedFlowThreadOrderDirty = dirty;
+ if (dirty)
+ m_view->setNeedsLayout(true);
+ }
+
+ RenderNamedFlowThread* ensureRenderFlowThreadWithName(const AtomicString&);
+ const RenderNamedFlowThreadList* renderNamedFlowThreadList() const { return m_renderNamedFlowThreadList.get(); }
+ bool hasRenderNamedFlowThreads() const { return m_renderNamedFlowThreadList && !m_renderNamedFlowThreadList->isEmpty(); }
+ void layoutRenderNamedFlowThreads();
+
+ void registerNamedFlowContentNode(Node*, RenderNamedFlowThread*);
+ void unregisterNamedFlowContentNode(Node*);
+
+protected:
+ FlowThreadController(RenderView*);
+
+private:
+ RenderView* m_view;
+ RenderFlowThread* m_currentRenderFlowThread;
+ bool m_isRenderNamedFlowThreadOrderDirty;
+ OwnPtr<RenderNamedFlowThreadList> m_renderNamedFlowThreadList;
+ // maps a content node to its render flow thread.
+ HashMap<Node*, RenderNamedFlowThread*> m_mapNamedFlowContentNodes;
+};
+
+}
+
+#endif
diff --git a/Source/WebCore/rendering/HitTestResult.cpp b/Source/WebCore/rendering/HitTestResult.cpp
index dc987c802..c19f1222f 100644
--- a/Source/WebCore/rendering/HitTestResult.cpp
+++ b/Source/WebCore/rendering/HitTestResult.cpp
@@ -54,6 +54,7 @@ HitTestResult::HitTestResult()
, m_rightPadding(0)
, m_bottomPadding(0)
, m_leftPadding(0)
+ , m_shadowContentFilterPolicy(DoNotAllowShadowContent)
, m_region(0)
{
}
@@ -66,17 +67,19 @@ HitTestResult::HitTestResult(const LayoutPoint& point)
, m_rightPadding(0)
, m_bottomPadding(0)
, m_leftPadding(0)
+ , m_shadowContentFilterPolicy(DoNotAllowShadowContent)
, m_region(0)
{
}
-HitTestResult::HitTestResult(const LayoutPoint& centerPoint, unsigned topPadding, unsigned rightPadding, unsigned bottomPadding, unsigned leftPadding)
+HitTestResult::HitTestResult(const LayoutPoint& centerPoint, unsigned topPadding, unsigned rightPadding, unsigned bottomPadding, unsigned leftPadding, ShadowContentFilterPolicy allowShadowContent)
: 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.
@@ -95,6 +98,7 @@ HitTestResult::HitTestResult(const HitTestResult& other)
, m_innerURLElement(other.URLElement())
, m_scrollbar(other.scrollbar())
, m_isOverWidget(other.isOverWidget())
+ , m_shadowContentFilterPolicy(other.shadowContentFilterPolicy())
, m_region(other.region())
{
// Only copy the padding and NodeSet in case of rect hit test.
@@ -134,7 +138,8 @@ HitTestResult& HitTestResult::operator=(const HitTestResult& other)
m_topPadding = m_rightPadding = m_bottomPadding = m_leftPadding = 0;
m_rectBasedTestResult = adoptPtr(other.m_rectBasedTestResult ? new NodeSet(*other.m_rectBasedTestResult) : 0);
-
+ m_shadowContentFilterPolicy = other.shadowContentFilterPolicy();
+
m_region = other.m_region;
return *this;
@@ -572,7 +577,9 @@ bool HitTestResult::addNodeToRectBasedTestResult(Node* node, const LayoutPoint&
if (!node)
return true;
- node = node->shadowAncestorNode();
+ if (m_shadowContentFilterPolicy == DoNotAllowShadowContent)
+ node = node->shadowAncestorNode();
+
mutableRectBasedTestResult().add(node);
if (node->renderer()->isInline()) {
@@ -603,7 +610,9 @@ bool HitTestResult::addNodeToRectBasedTestResult(Node* node, const LayoutPoint&
if (!node)
return true;
- node = node->shadowAncestorNode();
+ if (m_shadowContentFilterPolicy == DoNotAllowShadowContent)
+ node = node->shadowAncestorNode();
+
mutableRectBasedTestResult().add(node);
if (node->renderer()->isInline()) {
@@ -643,16 +652,16 @@ void HitTestResult::append(const HitTestResult& other)
}
}
-LayoutRect HitTestResult::rectForPoint(const LayoutPoint& point, unsigned topPadding, unsigned rightPadding, unsigned bottomPadding, unsigned leftPadding)
+IntRect HitTestResult::rectForPoint(const LayoutPoint& point, unsigned topPadding, unsigned rightPadding, unsigned bottomPadding, unsigned leftPadding)
{
- LayoutPoint actualPoint(point);
- actualPoint -= LayoutSize(leftPadding, topPadding);
+ 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 LayoutRect(actualPoint, actualPadding);
+ return IntRect(actualPoint, actualPadding);
}
const HitTestResult::NodeSet& HitTestResult::rectBasedTestResult() const
diff --git a/Source/WebCore/rendering/HitTestResult.h b/Source/WebCore/rendering/HitTestResult.h
index 152278c4d..e919472b2 100644
--- a/Source/WebCore/rendering/HitTestResult.h
+++ b/Source/WebCore/rendering/HitTestResult.h
@@ -42,6 +42,8 @@ class Node;
class RenderRegion;
class Scrollbar;
+enum ShadowContentFilterPolicy { DoNotAllowShadowContent, AllowShadowContent };
+
class HitTestResult {
public:
typedef ListHashSet<RefPtr<Node> > NodeSet;
@@ -49,7 +51,7 @@ public:
HitTestResult();
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);
+ HitTestResult(const LayoutPoint& centerPoint, unsigned topPadding, unsigned rightPadding, unsigned bottomPadding, unsigned leftPadding, ShadowContentFilterPolicy);
HitTestResult(const HitTestResult&);
~HitTestResult();
HitTestResult& operator=(const HitTestResult&);
@@ -68,6 +70,8 @@ public:
void setToNonShadowAncestor();
+ ShadowContentFilterPolicy shadowContentFilterPolicy() const { return m_shadowContentFilterPolicy; }
+
void setInnerNode(Node*);
void setInnerNonSharedNode(Node*);
void setPoint(const LayoutPoint& p) { m_point = p; }
@@ -108,8 +112,8 @@ public:
// Rect-based hit test related methods.
bool isRectBasedTest() const { return m_isRectBased; }
- LayoutRect rectForPoint(const LayoutPoint&) const;
- static LayoutRect rectForPoint(const LayoutPoint&, unsigned topPadding, unsigned rightPadding, unsigned bottomPadding, unsigned leftPadding);
+ 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; }
@@ -146,6 +150,7 @@ private:
int m_rightPadding;
int m_bottomPadding;
int m_leftPadding;
+ ShadowContentFilterPolicy m_shadowContentFilterPolicy;
RenderRegion* m_region; // The region we're inside.
@@ -157,7 +162,7 @@ private:
// y = p.y() - topPadding
// width = leftPadding + rightPadding + 1
// height = topPadding + bottomPadding + 1
-inline LayoutRect HitTestResult::rectForPoint(const LayoutPoint& point) const
+inline IntRect HitTestResult::rectForPoint(const LayoutPoint& point) const
{
return rectForPoint(point, m_topPadding, m_rightPadding, m_bottomPadding, m_leftPadding);
}
diff --git a/Source/WebCore/rendering/HitTestingTransformState.cpp b/Source/WebCore/rendering/HitTestingTransformState.cpp
index cb1e1d6cb..4934a7b4f 100644
--- a/Source/WebCore/rendering/HitTestingTransformState.cpp
+++ b/Source/WebCore/rendering/HitTestingTransformState.cpp
@@ -73,7 +73,7 @@ FloatQuad HitTestingTransformState::mappedQuad() const
return m_accumulatedTransform.inverse().projectQuad(m_lastPlanarQuad);
}
-IntRect HitTestingTransformState::boundsOfMappedQuad() const
+LayoutRect HitTestingTransformState::boundsOfMappedQuad() const
{
return m_accumulatedTransform.inverse().clampedBoundsOfProjectedQuad(m_lastPlanarQuad);
}
diff --git a/Source/WebCore/rendering/HitTestingTransformState.h b/Source/WebCore/rendering/HitTestingTransformState.h
index 6aea66c63..2439dff78 100644
--- a/Source/WebCore/rendering/HitTestingTransformState.h
+++ b/Source/WebCore/rendering/HitTestingTransformState.h
@@ -58,7 +58,7 @@ public:
FloatPoint mappedPoint() const;
FloatQuad mappedQuad() const;
- IntRect boundsOfMappedQuad() const;
+ LayoutRect boundsOfMappedQuad() const;
void flatten();
FloatPoint m_lastPlanarPoint;
diff --git a/Source/WebCore/rendering/InlineBox.cpp b/Source/WebCore/rendering/InlineBox.cpp
index 7eceba404..957e0f0cb 100644
--- a/Source/WebCore/rendering/InlineBox.cpp
+++ b/Source/WebCore/rendering/InlineBox.cpp
@@ -37,22 +37,18 @@ using namespace std;
namespace WebCore {
-#if !COMPILER(MSVC)
-// FIXME: Figure out why this doesn't work on MSVC.
class SameSizeAsInlineBox {
virtual ~SameSizeAsInlineBox() { }
void* a[4];
FloatPoint b;
float c;
- uint32_t d : 31;
- bool e : 1;
+ uint32_t d : 32;
#ifndef NDEBUG
bool f;
#endif
};
COMPILE_ASSERT(sizeof(InlineBox) == sizeof(SameSizeAsInlineBox), InlineBox_size_guard);
-#endif
#ifndef NDEBUG
static bool inInlineBoxDetach;
@@ -149,19 +145,29 @@ float InlineBox::logicalHeight() const
return virtualLogicalHeight();
if (renderer()->isText())
- return m_isText ? renderer()->style(m_firstLine)->fontMetrics().height() : 0;
+ return m_bitfields.isText() ? renderer()->style(isFirstLineStyle())->fontMetrics().height() : 0;
if (renderer()->isBox() && parent())
return isHorizontal() ? toRenderBox(m_renderer)->height() : toRenderBox(m_renderer)->width();
ASSERT(isInlineFlowBox());
RenderBoxModelObject* flowObject = boxModelObject();
- const FontMetrics& fontMetrics = renderer()->style(m_firstLine)->fontMetrics();
+ const FontMetrics& fontMetrics = renderer()->style(isFirstLineStyle())->fontMetrics();
float result = fontMetrics.height();
if (parent())
result += flowObject->borderAndPaddingLogicalHeight();
return result;
}
+LayoutUnit InlineBox::baselinePosition(FontBaseline baselineType) const
+{
+ return boxModelObject()->baselinePosition(baselineType, m_bitfields.firstLine(), isHorizontal() ? HorizontalLine : VerticalLine, PositionOnContainingLine);
+}
+
+LayoutUnit InlineBox::lineHeight() const
+{
+ return boxModelObject()->lineHeight(m_bitfields.firstLine(), isHorizontal() ? HorizontalLine : VerticalLine, PositionOnContainingLine);
+}
+
int InlineBox::caretMinOffset() const
{
return m_renderer->caretMinOffset();
@@ -181,21 +187,21 @@ void InlineBox::dirtyLineBoxes()
void InlineBox::deleteLine(RenderArena* arena)
{
- if (!m_extracted && m_renderer->isBox())
+ if (!m_bitfields.extracted() && m_renderer->isBox())
toRenderBox(m_renderer)->setInlineBoxWrapper(0);
destroy(arena);
}
void InlineBox::extractLine()
{
- m_extracted = true;
+ m_bitfields.setExtracted(true);
if (m_renderer->isBox())
toRenderBox(m_renderer)->setInlineBoxWrapper(0);
}
void InlineBox::attachLine()
{
- m_extracted = false;
+ m_bitfields.setExtracted(false);
if (m_renderer->isBox())
toRenderBox(m_renderer)->setInlineBoxWrapper(this);
}
@@ -262,17 +268,17 @@ RootInlineBox* InlineBox::root()
bool InlineBox::nextOnLineExists() const
{
- if (!m_determinedIfNextOnLineExists) {
- m_determinedIfNextOnLineExists = true;
+ if (!m_bitfields.determinedIfNextOnLineExists()) {
+ m_bitfields.setDeterminedIfNextOnLineExists(true);
if (!parent())
- m_nextOnLineExists = false;
+ m_bitfields.setNextOnLineExists(false);
else if (nextOnLine())
- m_nextOnLineExists = true;
+ m_bitfields.setNextOnLineExists(true);
else
- m_nextOnLineExists = parent()->nextOnLineExists();
+ m_bitfields.setNextOnLineExists(parent()->nextOnLineExists());
}
- return m_nextOnLineExists;
+ return m_bitfields.nextOnLineExists();
}
InlineBox* InlineBox::nextLeafChild() const
@@ -335,7 +341,7 @@ float InlineBox::placeEllipsisBox(bool, float, float, float, bool&)
void InlineBox::clearKnownToHaveNoOverflow()
{
- m_knownToHaveNoOverflow = false;
+ m_bitfields.setKnownToHaveNoOverflow(false);
if (parent() && parent()->knownToHaveNoOverflow())
parent()->clearKnownToHaveNoOverflow();
}
diff --git a/Source/WebCore/rendering/InlineBox.h b/Source/WebCore/rendering/InlineBox.h
index 196c230fd..2ed9cd40b 100644
--- a/Source/WebCore/rendering/InlineBox.h
+++ b/Source/WebCore/rendering/InlineBox.h
@@ -40,22 +40,6 @@ public:
, m_parent(0)
, m_renderer(obj)
, m_logicalWidth(0)
- , m_firstLine(false)
- , m_constructed(false)
- , m_bidiEmbeddingLevel(0)
- , m_dirty(false)
- , m_extracted(false)
- , m_hasVirtualLogicalHeight(false)
- , m_isHorizontal(true)
- , m_endsWithBreak(false)
- , m_hasSelectedChildrenOrCanHaveLeadingExpansion(false)
- , m_knownToHaveNoOverflow(true)
- , m_hasEllipsisBoxOrHyphen(false)
- , m_dirOverride(false)
- , m_isText(false)
- , m_determinedIfNextOnLineExists(false)
- , m_nextOnLineExists(false)
- , m_expansion(0)
#ifndef NDEBUG
, m_hasBadParent(false)
#endif
@@ -70,22 +54,7 @@ public:
, m_renderer(obj)
, m_topLeft(topLeft)
, m_logicalWidth(logicalWidth)
- , m_firstLine(firstLine)
- , m_constructed(constructed)
- , m_bidiEmbeddingLevel(0)
- , m_dirty(dirty)
- , m_extracted(extracted)
- , m_hasVirtualLogicalHeight(false)
- , m_isHorizontal(isHorizontal)
- , m_endsWithBreak(false)
- , m_hasSelectedChildrenOrCanHaveLeadingExpansion(false)
- , m_knownToHaveNoOverflow(true)
- , m_hasEllipsisBoxOrHyphen(false)
- , m_dirOverride(false)
- , m_isText(false)
- , m_determinedIfNextOnLineExists(false)
- , m_nextOnLineExists(false)
- , m_expansion(0)
+ , m_bitfields(firstLine, constructed, dirty, extracted, isHorizontal)
#ifndef NDEBUG
, m_hasBadParent(false)
#endif
@@ -121,8 +90,6 @@ public:
virtual void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom);
virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const LayoutPoint& pointInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom);
- InlineBox* next() const { return m_next; }
-
// Overloaded new operator.
void* operator new(size_t, RenderArena*);
@@ -143,8 +110,8 @@ public:
virtual const char* boxName() const;
#endif
- bool isText() const { return m_isText; }
- void setIsText(bool b) { m_isText = b; }
+ bool isText() const { return m_bitfields.isText(); }
+ void setIsText(bool isText) { m_bitfields.setIsText(isText); }
virtual bool isInlineFlowBox() const { return false; }
virtual bool isInlineTextBox() const { return false; }
@@ -155,16 +122,16 @@ public:
virtual bool isSVGRootInlineBox() const { return false; }
#endif
- bool hasVirtualLogicalHeight() const { return m_hasVirtualLogicalHeight; }
- void setHasVirtualLogicalHeight() { m_hasVirtualLogicalHeight = true; }
+ bool hasVirtualLogicalHeight() const { return m_bitfields.hasVirtualLogicalHeight(); }
+ void setHasVirtualLogicalHeight() { m_bitfields.setHasVirtualLogicalHeight(true); }
virtual float virtualLogicalHeight() const
{
ASSERT_NOT_REACHED();
return 0;
}
- bool isHorizontal() const { return m_isHorizontal; }
- void setIsHorizontal(bool horizontal) { m_isHorizontal = horizontal; }
+ bool isHorizontal() const { return m_bitfields.isHorizontal(); }
+ void setIsHorizontal(bool isHorizontal) { m_bitfields.setIsHorizontal(isHorizontal); }
virtual FloatRect calculateBoundaries() const
{
@@ -172,13 +139,13 @@ public:
return FloatRect();
}
- bool isConstructed() { return m_constructed; }
- virtual void setConstructed() { m_constructed = true; }
+ bool isConstructed() { return m_bitfields.constructed(); }
+ virtual void setConstructed() { m_bitfields.setConstructed(true); }
- void setExtracted(bool b = true) { m_extracted = b; }
+ void setExtracted(bool extracted = true) { m_bitfields.setExtracted(extracted); }
- void setFirstLineStyleBit(bool f) { m_firstLine = f; }
- bool isFirstLineStyle() const { return m_firstLine; }
+ void setFirstLineStyleBit(bool firstLine) { m_bitfields.setFirstLine(firstLine); }
+ bool isFirstLineStyle() const { return m_bitfields.firstLine(); }
void remove();
@@ -272,25 +239,25 @@ public:
FloatRect logicalFrameRect() const { return isHorizontal() ? FloatRect(m_topLeft.x(), m_topLeft.y(), m_logicalWidth, logicalHeight()) : FloatRect(m_topLeft.y(), m_topLeft.x(), m_logicalWidth, logicalHeight()); }
- virtual LayoutUnit baselinePosition(FontBaseline baselineType) const { return boxModelObject()->baselinePosition(baselineType, m_firstLine, isHorizontal() ? HorizontalLine : VerticalLine, PositionOnContainingLine); }
- virtual LayoutUnit lineHeight() const { return boxModelObject()->lineHeight(m_firstLine, isHorizontal() ? HorizontalLine : VerticalLine, PositionOnContainingLine); }
-
+ virtual LayoutUnit baselinePosition(FontBaseline baselineType) const;
+ virtual LayoutUnit lineHeight() const;
+
virtual int caretMinOffset() const;
virtual int caretMaxOffset() const;
- unsigned char bidiLevel() const { return m_bidiEmbeddingLevel; }
- void setBidiLevel(unsigned char level) { m_bidiEmbeddingLevel = level; }
- TextDirection direction() const { return m_bidiEmbeddingLevel % 2 ? RTL : LTR; }
+ unsigned char bidiLevel() const { return m_bitfields.bidiEmbeddingLevel(); }
+ void setBidiLevel(unsigned char level) { m_bitfields.setBidiEmbeddingLevel(level); }
+ TextDirection direction() const { return bidiLevel() % 2 ? RTL : LTR; }
bool isLeftToRightDirection() const { return direction() == LTR; }
int caretLeftmostOffset() const { return isLeftToRightDirection() ? caretMinOffset() : caretMaxOffset(); }
int caretRightmostOffset() const { return isLeftToRightDirection() ? caretMaxOffset() : caretMinOffset(); }
virtual void clearTruncation() { }
- bool isDirty() const { return m_dirty; }
- void markDirty(bool dirty = true) { m_dirty = dirty; }
+ bool isDirty() const { return m_bitfields.dirty(); }
+ void markDirty(bool dirty = true) { m_bitfields.setDirty(dirty); }
- void dirtyLineBoxes();
+ virtual void dirtyLineBoxes();
virtual RenderObject::SelectionState selectionState();
@@ -298,13 +265,15 @@ public:
// visibleLeftEdge, visibleRightEdge are in the parent's coordinate system.
virtual float placeEllipsisBox(bool ltr, float visibleLeftEdge, float visibleRightEdge, float ellipsisWidth, bool&);
+#ifndef NDEBUG
void setHasBadParent();
+#endif
+
+ int expansion() const { return m_bitfields.expansion(); }
- int expansion() const { return m_expansion; }
-
bool visibleToHitTesting() const { return renderer()->style()->visibility() == VISIBLE && renderer()->style()->pointerEvents() != PE_NONE; }
- EVerticalAlign verticalAlign() const { return renderer()->style(m_firstLine)->verticalAlign(); }
+ EVerticalAlign verticalAlign() const { return renderer()->style(m_bitfields.firstLine())->verticalAlign(); }
// Use with caution! The type is not checked!
RenderBoxModelObject* boxModelObject() const
@@ -320,9 +289,12 @@ public:
void flipForWritingMode(LayoutRect&);
LayoutPoint flipForWritingMode(const LayoutPoint&);
- bool knownToHaveNoOverflow() const { return m_knownToHaveNoOverflow; }
+ bool knownToHaveNoOverflow() const { return m_bitfields.knownToHaveNoOverflow(); }
void clearKnownToHaveNoOverflow();
+ bool dirOverride() const { return m_bitfields.dirOverride(); }
+ void setDirOverride(bool dirOverride) { m_bitfields.setDirOverride(dirOverride); }
+
private:
InlineBox* m_next; // The next element on the same line as us.
InlineBox* m_prev; // The previous element on the same line as us.
@@ -334,37 +306,107 @@ public:
FloatPoint m_topLeft;
float m_logicalWidth;
-
- // Some of these bits are actually for subclasses and moved here to compact the structures.
-
- // for this class
-protected:
- bool m_firstLine : 1;
-private:
- bool m_constructed : 1;
- unsigned char m_bidiEmbeddingLevel : 6;
-protected:
- bool m_dirty : 1;
- bool m_extracted : 1;
- bool m_hasVirtualLogicalHeight : 1;
- bool m_isHorizontal : 1;
+#define ADD_BOOLEAN_BITFIELD(name, Name) \
+ private:\
+ unsigned m_##name : 1;\
+ public:\
+ bool name() const { return m_##name; }\
+ void set##Name(bool name) { m_##name = name; }\
+
+ class InlineBoxBitfields {
+ public:
+ InlineBoxBitfields(bool firstLine = false, bool constructed = false, bool dirty = false, bool extracted = false, bool isHorizontal = true)
+ : m_firstLine(firstLine)
+ , m_constructed(constructed)
+ , m_bidiEmbeddingLevel(0)
+ , m_dirty(dirty)
+ , m_extracted(extracted)
+ , m_hasVirtualLogicalHeight(false)
+ , m_isHorizontal(isHorizontal)
+ , m_endsWithBreak(false)
+ , m_hasSelectedChildrenOrCanHaveLeadingExpansion(false)
+ , m_knownToHaveNoOverflow(true)
+ , m_hasEllipsisBoxOrHyphen(false)
+ , m_dirOverride(false)
+ , m_isText(false)
+ , m_determinedIfNextOnLineExists(false)
+ , m_nextOnLineExists(false)
+ , m_expansion(0)
+ {
+ }
+
+ // Some of these bits are actually for subclasses and moved here to compact the structures.
+ // for this class
+ ADD_BOOLEAN_BITFIELD(firstLine, FirstLine);
+ ADD_BOOLEAN_BITFIELD(constructed, Constructed);
+
+ private:
+ unsigned m_bidiEmbeddingLevel : 6; // The maximium bidi level is 62: http://unicode.org/reports/tr9/#Explicit_Levels_and_Directions
+
+ public:
+ unsigned char bidiEmbeddingLevel() const { return m_bidiEmbeddingLevel; }
+ void setBidiEmbeddingLevel(unsigned char bidiEmbeddingLevel) { m_bidiEmbeddingLevel = bidiEmbeddingLevel; }
+
+ ADD_BOOLEAN_BITFIELD(dirty, Dirty);
+ ADD_BOOLEAN_BITFIELD(extracted, Extracted);
+ ADD_BOOLEAN_BITFIELD(hasVirtualLogicalHeight, HasVirtualLogicalHeight);
+ ADD_BOOLEAN_BITFIELD(isHorizontal, IsHorizontal);
+ // for RootInlineBox
+ ADD_BOOLEAN_BITFIELD(endsWithBreak, EndsWithBreak); // Whether the line ends with a <br>.
+ // shared between RootInlineBox and InlineTextBox
+ ADD_BOOLEAN_BITFIELD(hasSelectedChildrenOrCanHaveLeadingExpansion, HasSelectedChildrenOrCanHaveLeadingExpansion);
+ ADD_BOOLEAN_BITFIELD(knownToHaveNoOverflow, KnownToHaveNoOverflow);
+ ADD_BOOLEAN_BITFIELD(hasEllipsisBoxOrHyphen, HasEllipsisBoxOrHyphen);
+ // for InlineTextBox
+ ADD_BOOLEAN_BITFIELD(dirOverride, DirOverride);
+ ADD_BOOLEAN_BITFIELD(isText, IsText); // Whether or not this object represents text with a non-zero height. Includes non-image list markers, text boxes.
+
+ private:
+ mutable unsigned m_determinedIfNextOnLineExists : 1;
+
+ public:
+ bool determinedIfNextOnLineExists() const { return m_determinedIfNextOnLineExists; }
+ void setDeterminedIfNextOnLineExists(bool determinedIfNextOnLineExists) const { m_determinedIfNextOnLineExists = determinedIfNextOnLineExists; }
+
+ private:
+ mutable unsigned m_nextOnLineExists : 1;
+
+ public:
+ bool nextOnLineExists() const { return m_nextOnLineExists; }
+ void setNextOnLineExists(bool nextOnLineExists) const { m_nextOnLineExists = nextOnLineExists; }
+
+ private:
+ signed m_expansion : 12; // for justified text
+
+ public:
+ signed expansion() const { return m_expansion; }
+ void setExpansion(signed expansion) { m_expansion = expansion; }
+ };
+#undef ADD_BOOLEAN_BITFIELD
- // for RootInlineBox
- bool m_endsWithBreak : 1; // Whether the line ends with a <br>.
- // shared between RootInlineBox and InlineTextBox
- bool m_hasSelectedChildrenOrCanHaveLeadingExpansion : 1; // Whether we have any children selected (this bit will also be set if the <br> that terminates our line is selected).
- bool m_knownToHaveNoOverflow : 1;
- bool m_hasEllipsisBoxOrHyphen : 1;
+private:
+ InlineBoxBitfields m_bitfields;
- // for InlineTextBox
-public:
- bool m_dirOverride : 1;
- bool m_isText : 1; // Whether or not this object represents text with a non-zero height. Includes non-image list markers, text boxes.
protected:
- mutable bool m_determinedIfNextOnLineExists : 1;
- mutable bool m_nextOnLineExists : 1;
- signed m_expansion : 12; // for justified text
+ // For RootInlineBox
+ bool endsWithBreak() const { return m_bitfields.endsWithBreak(); }
+ void setEndsWithBreak(bool endsWithBreak) { m_bitfields.setEndsWithBreak(endsWithBreak); }
+ bool hasEllipsisBox() const { return m_bitfields.hasEllipsisBoxOrHyphen(); }
+ bool hasSelectedChildren() const { return m_bitfields.hasSelectedChildrenOrCanHaveLeadingExpansion(); }
+ void setHasSelectedChildren(bool hasSelectedChildren) { m_bitfields.setHasSelectedChildrenOrCanHaveLeadingExpansion(hasSelectedChildren); }
+ void setHasEllipsisBox(bool hasEllipsisBox) { m_bitfields.setHasEllipsisBoxOrHyphen(hasEllipsisBox); }
+
+ // For InlineTextBox
+ bool hasHyphen() const { return m_bitfields.hasEllipsisBoxOrHyphen(); }
+ void setHasHyphen(bool hasHyphen) { m_bitfields.setHasEllipsisBoxOrHyphen(hasHyphen); }
+ bool canHaveLeadingExpansion() const { return m_bitfields.hasSelectedChildrenOrCanHaveLeadingExpansion(); }
+ void setCanHaveLeadingExpansion(bool canHaveLeadingExpansion) { m_bitfields.setHasSelectedChildrenOrCanHaveLeadingExpansion(canHaveLeadingExpansion); }
+ signed expansion() { return m_bitfields.expansion(); }
+ void setExpansion(signed expansion) { m_bitfields.setExpansion(expansion); }
+
+ // For InlineFlowBox and InlineTextBox
+ bool extracted() const { return m_bitfields.extracted(); }
#ifndef NDEBUG
private:
@@ -378,12 +420,12 @@ inline InlineBox::~InlineBox()
}
#endif
+#ifndef NDEBUG
inline void InlineBox::setHasBadParent()
{
-#ifndef NDEBUG
m_hasBadParent = true;
-#endif
}
+#endif
} // namespace WebCore
diff --git a/Source/WebCore/rendering/InlineFlowBox.cpp b/Source/WebCore/rendering/InlineFlowBox.cpp
index bf84a0a03..cbd685d69 100644
--- a/Source/WebCore/rendering/InlineFlowBox.cpp
+++ b/Source/WebCore/rendering/InlineFlowBox.cpp
@@ -45,6 +45,13 @@ using namespace std;
namespace WebCore {
+class SameSizeAsInlineFlowBox : public InlineBox {
+ void* pointers[5];
+ uint32_t bitfields : 24;
+};
+
+COMPILE_ASSERT(sizeof(InlineFlowBox) == sizeof(SameSizeAsInlineFlowBox), InlineFlowBox_should_stay_small);
+
#ifndef NDEBUG
InlineFlowBox::~InlineFlowBox()
@@ -102,7 +109,7 @@ void InlineFlowBox::addToLine(InlineBox* child)
child->setPrevOnLine(m_lastChild);
m_lastChild = child;
}
- child->setFirstLineStyleBit(m_firstLine);
+ child->setFirstLineStyleBit(isFirstLineStyle());
child->setIsHorizontal(isHorizontal());
if (child->isText()) {
if (child->renderer()->parent() == renderer())
@@ -114,8 +121,8 @@ void InlineFlowBox::addToLine(InlineBox* child)
}
if (descendantsHaveSameLineHeightAndBaseline() && !child->renderer()->isPositioned()) {
- RenderStyle* parentStyle = renderer()->style(m_firstLine);
- RenderStyle* childStyle = child->renderer()->style(m_firstLine);
+ RenderStyle* parentStyle = renderer()->style(isFirstLineStyle());
+ RenderStyle* childStyle = child->renderer()->style(isFirstLineStyle());
bool shouldClearDescendantsHaveSameLineHeightAndBaseline = false;
if (child->renderer()->isReplaced())
shouldClearDescendantsHaveSameLineHeightAndBaseline = true;
@@ -152,16 +159,16 @@ void InlineFlowBox::addToLine(InlineBox* child)
if (!child->renderer()->isPositioned()) {
if (child->isText()) {
- RenderStyle* childStyle = child->renderer()->style(m_firstLine);
+ RenderStyle* childStyle = child->renderer()->style(isFirstLineStyle());
if (childStyle->letterSpacing() < 0 || childStyle->textShadow() || childStyle->textEmphasisMark() != TextEmphasisMarkNone || childStyle->textStrokeWidth())
child->clearKnownToHaveNoOverflow();
} else if (child->renderer()->isReplaced()) {
RenderBox* box = toRenderBox(child->renderer());
if (box->hasRenderOverflow() || box->hasSelfPaintingLayer())
child->clearKnownToHaveNoOverflow();
- } else if (!child->renderer()->isBR() && (child->renderer()->style(m_firstLine)->boxShadow() || child->boxModelObject()->hasSelfPaintingLayer()
+ } else if (!child->renderer()->isBR() && (child->renderer()->style(isFirstLineStyle())->boxShadow() || child->boxModelObject()->hasSelfPaintingLayer()
|| (child->renderer()->isListMarker() && !toRenderListMarker(child->renderer())->isInside())
- || child->renderer()->style(m_firstLine)->hasBorderImageOutsets()))
+ || child->renderer()->style(isFirstLineStyle())->hasBorderImageOutsets()))
child->clearKnownToHaveNoOverflow();
if (knownToHaveNoOverflow() && child->isInlineFlowBox() && !toInlineFlowBox(child)->knownToHaveNoOverflow())
@@ -175,7 +182,7 @@ void InlineFlowBox::removeChild(InlineBox* child)
{
checkConsistency();
- if (!m_dirty)
+ if (!isDirty())
dirtyLineBoxes();
root()->childRemoved(child);
@@ -223,7 +230,7 @@ void InlineFlowBox::removeLineBoxFromRenderObject()
void InlineFlowBox::extractLine()
{
- if (!m_extracted)
+ if (!extracted())
extractLineBoxFromRenderObject();
for (InlineBox* child = firstChild(); child; child = child->nextOnLine())
child->extractLine();
@@ -236,7 +243,7 @@ void InlineFlowBox::extractLineBoxFromRenderObject()
void InlineFlowBox::attachLine()
{
- if (m_extracted)
+ if (extracted())
attachLineBoxToRenderObject();
for (InlineBox* child = firstChild(); child; child = child->nextOnLine())
child->attachLine();
@@ -365,7 +372,7 @@ float InlineFlowBox::placeBoxesInInlineDirection(float logicalLeft, bool& needsW
RenderText* rt = toRenderText(text->renderer());
if (rt->textLength()) {
if (needsWordSpacing && isSpaceOrNewline(rt->characters()[text->start()]))
- logicalLeft += rt->style(m_firstLine)->font().wordSpacing();
+ logicalLeft += rt->style(isFirstLineStyle())->font().wordSpacing();
needsWordSpacing = !isSpaceOrNewline(rt->characters()[text->end()]);
}
text->setLogicalLeft(logicalLeft);
@@ -424,8 +431,8 @@ bool InlineFlowBox::requiresIdeographicBaseline(const GlyphOverflowAndFallbackFo
if (isHorizontal())
return false;
- if (renderer()->style(m_firstLine)->fontDescription().textOrientation() == TextOrientationUpright
- || renderer()->style(m_firstLine)->font().primaryFont()->hasVerticalGlyphs())
+ if (renderer()->style(isFirstLineStyle())->fontDescription().textOrientation() == TextOrientationUpright
+ || renderer()->style(isFirstLineStyle())->font().primaryFont()->hasVerticalGlyphs())
return true;
for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
@@ -436,7 +443,7 @@ bool InlineFlowBox::requiresIdeographicBaseline(const GlyphOverflowAndFallbackFo
if (toInlineFlowBox(curr)->requiresIdeographicBaseline(textBoxDataMap))
return true;
} else {
- if (curr->renderer()->style(m_firstLine)->font().primaryFont()->hasVerticalGlyphs())
+ if (curr->renderer()->style(isFirstLineStyle())->font().primaryFont()->hasVerticalGlyphs())
return true;
const Vector<const SimpleFontData*>* usedFonts = 0;
@@ -586,8 +593,10 @@ void InlineFlowBox::placeBoxesInBlockDirection(LayoutUnit top, LayoutUnit maxHei
{
bool isRootBox = isRootInlineBox();
if (isRootBox) {
- const FontMetrics& fontMetrics = renderer()->style(m_firstLine)->fontMetrics();
- setLogicalTop(top + maxAscent - fontMetrics.ascent(baselineType));
+ const FontMetrics& fontMetrics = renderer()->style(isFirstLineStyle())->fontMetrics();
+ // RootInlineBoxes are always placed on at pixel boundaries in their logical y direction. Not doing
+ // so results in incorrect rendering of text decorations, most notably underlines.
+ setLogicalTop(roundToInt(top + maxAscent - fontMetrics.ascent(baselineType)));
}
LayoutUnit adjustmentForChildrenWithSameLineHeightAndBaseline = 0;
@@ -626,11 +635,11 @@ void InlineFlowBox::placeBoxesInBlockDirection(LayoutUnit top, LayoutUnit maxHei
LayoutUnit boxHeightIncludingMargins = boxHeight;
if (curr->isText() || curr->isInlineFlowBox()) {
- const FontMetrics& fontMetrics = curr->renderer()->style(m_firstLine)->fontMetrics();
+ const FontMetrics& fontMetrics = curr->renderer()->style(isFirstLineStyle())->fontMetrics();
newLogicalTop += curr->baselinePosition(baselineType) - fontMetrics.ascent(baselineType);
if (curr->isInlineFlowBox()) {
RenderBoxModelObject* boxObject = toRenderBoxModelObject(curr->renderer());
- newLogicalTop -= boxObject->style(m_firstLine)->isHorizontalWritingMode() ? boxObject->borderTop() + boxObject->paddingTop() :
+ newLogicalTop -= boxObject->style(isFirstLineStyle())->isHorizontalWritingMode() ? boxObject->borderTop() + boxObject->paddingTop() :
boxObject->borderRight() + boxObject->paddingRight();
}
newLogicalTopIncludingMargins = newLogicalTop;
@@ -657,17 +666,17 @@ void InlineFlowBox::placeBoxesInBlockDirection(LayoutUnit top, LayoutUnit maxHei
RenderRubyRun* rubyRun = toRenderRubyRun(curr->renderer());
if (RenderRubyBase* rubyBase = rubyRun->rubyBase()) {
- LayoutUnit bottomRubyBaseLeading = (curr->logicalHeight() - rubyBase->logicalBottom()) + rubyBase->logicalHeight() - (rubyBase->lastRootBox() ? rubyBase->lastRootBox()->lineBottom() : zeroLayoutUnit);
- LayoutUnit topRubyBaseLeading = rubyBase->logicalTop() + (rubyBase->firstRootBox() ? rubyBase->firstRootBox()->lineTop() : zeroLayoutUnit);
+ LayoutUnit bottomRubyBaseLeading = (curr->logicalHeight() - rubyBase->logicalBottom()) + rubyBase->logicalHeight() - (rubyBase->lastRootBox() ? rubyBase->lastRootBox()->lineBottom() : ZERO_LAYOUT_UNIT);
+ LayoutUnit topRubyBaseLeading = rubyBase->logicalTop() + (rubyBase->firstRootBox() ? rubyBase->firstRootBox()->lineTop() : ZERO_LAYOUT_UNIT);
newLogicalTop += !renderer()->style()->isFlippedLinesWritingMode() ? topRubyBaseLeading : bottomRubyBaseLeading;
boxHeight -= (topRubyBaseLeading + bottomRubyBaseLeading);
}
}
if (curr->isInlineTextBox()) {
TextEmphasisPosition emphasisMarkPosition;
- if (toInlineTextBox(curr)->getEmphasisMarkPosition(curr->renderer()->style(m_firstLine), emphasisMarkPosition)) {
+ if (toInlineTextBox(curr)->getEmphasisMarkPosition(curr->renderer()->style(isFirstLineStyle()), emphasisMarkPosition)) {
bool emphasisMarkIsOver = emphasisMarkPosition == TextEmphasisPositionOver;
- if (emphasisMarkIsOver != curr->renderer()->style(m_firstLine)->isFlippedLinesWritingMode())
+ if (emphasisMarkIsOver != curr->renderer()->style(isFirstLineStyle())->isFlippedLinesWritingMode())
hasAnnotationsBefore = true;
else
hasAnnotationsAfter = true;
@@ -734,7 +743,7 @@ inline void InlineFlowBox::addBoxShadowVisualOverflow(LayoutRect& logicalVisualO
if (!parent())
return;
- RenderStyle* style = renderer()->style(m_firstLine);
+ RenderStyle* style = renderer()->style(isFirstLineStyle());
if (!style->boxShadow())
return;
@@ -767,7 +776,7 @@ inline void InlineFlowBox::addBorderOutsetVisualOverflow(LayoutRect& logicalVisu
if (!parent())
return;
- RenderStyle* style = renderer()->style(m_firstLine);
+ RenderStyle* style = renderer()->style(isFirstLineStyle());
if (!style->hasBorderImageOutsets())
return;
@@ -787,8 +796,8 @@ inline void InlineFlowBox::addBorderOutsetVisualOverflow(LayoutRect& logicalVisu
LayoutUnit borderOutsetLogicalRight;
style->getBorderImageInlineDirectionOutsets(borderOutsetLogicalLeft, borderOutsetLogicalRight);
- LayoutUnit outsetLogicalLeft = includeLogicalLeftEdge() ? borderOutsetLogicalLeft : zeroLayoutUnit;
- LayoutUnit outsetLogicalRight = includeLogicalRightEdge() ? borderOutsetLogicalRight : zeroLayoutUnit;
+ LayoutUnit outsetLogicalLeft = includeLogicalLeftEdge() ? borderOutsetLogicalLeft : ZERO_LAYOUT_UNIT;
+ LayoutUnit outsetLogicalRight = includeLogicalRightEdge() ? borderOutsetLogicalRight : ZERO_LAYOUT_UNIT;
LayoutUnit logicalLeftVisualOverflow = min(pixelSnappedLogicalLeft() - outsetLogicalLeft, logicalVisualOverflow.x());
LayoutUnit logicalRightVisualOverflow = max(pixelSnappedLogicalRight() + outsetLogicalRight, logicalVisualOverflow.maxX());
@@ -802,7 +811,7 @@ inline void InlineFlowBox::addTextBoxVisualOverflow(InlineTextBox* textBox, Glyp
if (textBox->knownToHaveNoOverflow())
return;
- RenderStyle* style = textBox->renderer()->style(m_firstLine);
+ RenderStyle* style = textBox->renderer()->style(isFirstLineStyle());
GlyphOverflowAndFallbackFontsMap::iterator it = textBoxDataMap.find(textBox);
GlyphOverflow* glyphOverflow = it == textBoxDataMap.end() ? 0 : &it->second.second;
@@ -1116,8 +1125,8 @@ void InlineFlowBox::paintFillLayer(const PaintInfo& paintInfo, const Color& c, c
for (InlineFlowBox* curr = this; curr; curr = curr->prevLineBox())
totalLogicalWidth += curr->logicalWidth();
}
- LayoutUnit stripX = rect.x() - (isHorizontal() ? logicalOffsetOnLine : zeroLayoutUnit);
- LayoutUnit stripY = rect.y() - (isHorizontal() ? zeroLayoutUnit : logicalOffsetOnLine);
+ LayoutUnit stripX = rect.x() - (isHorizontal() ? logicalOffsetOnLine : ZERO_LAYOUT_UNIT);
+ LayoutUnit stripY = rect.y() - (isHorizontal() ? ZERO_LAYOUT_UNIT : logicalOffsetOnLine);
LayoutUnit stripWidth = isHorizontal() ? totalLogicalWidth : static_cast<LayoutUnit>(width());
LayoutUnit stripHeight = isHorizontal() ? static_cast<LayoutUnit>(height()) : totalLogicalWidth;
@@ -1208,8 +1217,8 @@ void InlineFlowBox::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint&
// You can use p::first-line to specify a background. If so, the root line boxes for
// a line may actually have to paint a background.
- RenderStyle* styleToUse = renderer()->style(m_firstLine);
- if ((!parent() && m_firstLine && styleToUse != renderer()->style()) || (parent() && renderer()->hasBoxDecorations())) {
+ RenderStyle* styleToUse = renderer()->style(isFirstLineStyle());
+ if ((!parent() && isFirstLineStyle() && styleToUse != renderer()->style()) || (parent() && renderer()->hasBoxDecorations())) {
LayoutRect paintRect = LayoutRect(adjustedPaintoffset, frameRect.size());
// Shadow comes first and is behind the background and border.
if (!boxModelObject()->boxShadowShouldBeAppliedToBackground(BackgroundBleedNone, this))
@@ -1231,7 +1240,7 @@ void InlineFlowBox::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint&
// The simple case is where we either have no border image or we are the only box for this object. In those
// cases only a single call to draw is required.
if (!hasBorderImage || (!prevLineBox() && !nextLineBox()))
- boxModelObject()->paintBorder(paintInfo, paintRect, renderer()->style(), BackgroundBleedNone, includeLogicalLeftEdge(), includeLogicalRightEdge());
+ boxModelObject()->paintBorder(paintInfo, paintRect, renderer()->style(isFirstLineStyle()), BackgroundBleedNone, includeLogicalLeftEdge(), includeLogicalRightEdge());
else {
// We have a border image that spans multiple lines.
// We need to adjust tx and ty by the width of all previous lines.
@@ -1247,15 +1256,15 @@ void InlineFlowBox::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint&
LayoutUnit totalLogicalWidth = logicalOffsetOnLine;
for (InlineFlowBox* curr = this; curr; curr = curr->nextLineBox())
totalLogicalWidth += curr->logicalWidth();
- LayoutUnit stripX = adjustedPaintoffset.x() - (isHorizontal() ? logicalOffsetOnLine : zeroLayoutUnit);
- LayoutUnit stripY = adjustedPaintoffset.y() - (isHorizontal() ? zeroLayoutUnit : logicalOffsetOnLine);
+ LayoutUnit stripX = adjustedPaintoffset.x() - (isHorizontal() ? logicalOffsetOnLine : ZERO_LAYOUT_UNIT);
+ LayoutUnit stripY = adjustedPaintoffset.y() - (isHorizontal() ? ZERO_LAYOUT_UNIT : logicalOffsetOnLine);
LayoutUnit stripWidth = isHorizontal() ? totalLogicalWidth : frameRect.width();
LayoutUnit stripHeight = isHorizontal() ? frameRect.height() : totalLogicalWidth;
LayoutRect clipRect = clipRectForNinePieceImageStrip(this, borderImage, paintRect);
GraphicsContextStateSaver stateSaver(*context);
context->clip(clipRect);
- boxModelObject()->paintBorder(paintInfo, LayoutRect(stripX, stripY, stripWidth, stripHeight), renderer()->style());
+ boxModelObject()->paintBorder(paintInfo, LayoutRect(stripX, stripY, stripWidth, stripHeight), renderer()->style(isFirstLineStyle()));
}
}
}
@@ -1282,8 +1291,9 @@ void InlineFlowBox::paintMask(PaintInfo& paintInfo, const LayoutPoint& paintOffs
// Figure out if we need to push a transparency layer to render our mask.
bool pushTransparencyLayer = false;
bool compositedMask = renderer()->hasLayer() && boxModelObject()->layer()->hasCompositedMask();
+ bool flattenCompositingLayers = renderer()->view()->frameView() && renderer()->view()->frameView()->paintBehavior() & PaintBehaviorFlattenCompositingLayers;
CompositeOperator compositeOp = CompositeSourceOver;
- if (!compositedMask) {
+ if (!compositedMask || flattenCompositingLayers) {
if ((maskBoxImage && renderer()->style()->maskLayers()->hasImage()) || renderer()->style()->maskLayers()->next())
pushTransparencyLayer = true;
@@ -1318,8 +1328,8 @@ void InlineFlowBox::paintMask(PaintInfo& paintInfo, const LayoutPoint& paintOffs
LayoutUnit totalLogicalWidth = logicalOffsetOnLine;
for (InlineFlowBox* curr = this; curr; curr = curr->nextLineBox())
totalLogicalWidth += curr->logicalWidth();
- LayoutUnit stripX = adjustedPaintOffset.x() - (isHorizontal() ? logicalOffsetOnLine : zeroLayoutUnit);
- LayoutUnit stripY = adjustedPaintOffset.y() - (isHorizontal() ? zeroLayoutUnit : logicalOffsetOnLine);
+ LayoutUnit stripX = adjustedPaintOffset.x() - (isHorizontal() ? logicalOffsetOnLine : ZERO_LAYOUT_UNIT);
+ LayoutUnit stripY = adjustedPaintOffset.y() - (isHorizontal() ? ZERO_LAYOUT_UNIT : logicalOffsetOnLine);
LayoutUnit stripWidth = isHorizontal() ? totalLogicalWidth : frameRect.width();
LayoutUnit stripHeight = isHorizontal() ? frameRect.height() : totalLogicalWidth;
@@ -1416,7 +1426,7 @@ LayoutUnit InlineFlowBox::computeOverAnnotationAdjustment(LayoutUnit allowedPosi
continue;
if (!rubyRun->style()->isFlippedLinesWritingMode()) {
- LayoutUnit topOfFirstRubyTextLine = rubyText->logicalTop() + (rubyText->firstRootBox() ? rubyText->firstRootBox()->lineTop() : zeroLayoutUnit);
+ LayoutUnit topOfFirstRubyTextLine = rubyText->logicalTop() + (rubyText->firstRootBox() ? rubyText->firstRootBox()->lineTop() : ZERO_LAYOUT_UNIT);
if (topOfFirstRubyTextLine >= 0)
continue;
topOfFirstRubyTextLine += curr->logicalTop();
@@ -1431,7 +1441,7 @@ LayoutUnit InlineFlowBox::computeOverAnnotationAdjustment(LayoutUnit allowedPosi
}
if (curr->isInlineTextBox()) {
- RenderStyle* style = curr->renderer()->style(m_firstLine);
+ RenderStyle* style = curr->renderer()->style(isFirstLineStyle());
TextEmphasisPosition emphasisMarkPosition;
if (style->textEmphasisMark() != TextEmphasisMarkNone && toInlineTextBox(curr)->getEmphasisMarkPosition(style, emphasisMarkPosition) && emphasisMarkPosition == TextEmphasisPositionOver) {
if (!style->isFlippedLinesWritingMode()) {
@@ -1458,7 +1468,7 @@ LayoutUnit InlineFlowBox::computeUnderAnnotationAdjustment(LayoutUnit allowedPos
result = max(result, toInlineFlowBox(curr)->computeUnderAnnotationAdjustment(allowedPosition));
if (curr->isInlineTextBox()) {
- RenderStyle* style = curr->renderer()->style(m_firstLine);
+ RenderStyle* style = curr->renderer()->style(isFirstLineStyle());
if (style->textEmphasisMark() != TextEmphasisMarkNone && style->textEmphasisPosition() == TextEmphasisPositionUnder) {
if (!style->isFlippedLinesWritingMode()) {
LayoutUnit bottomOfEmphasisMark = curr->logicalBottom() + style->font().emphasisMarkHeight(style->textEmphasisMarkString());
diff --git a/Source/WebCore/rendering/InlineFlowBox.h b/Source/WebCore/rendering/InlineFlowBox.h
index a81af717b..bfdf87efd 100644
--- a/Source/WebCore/rendering/InlineFlowBox.h
+++ b/Source/WebCore/rendering/InlineFlowBox.h
@@ -88,7 +88,7 @@ public:
virtual void setConstructed()
{
InlineBox::setConstructed();
- for (InlineBox* child = firstChild(); child; child = child->next())
+ for (InlineBox* child = firstChild(); child; child = child->nextOnLine())
child->setConstructed();
}
@@ -137,13 +137,13 @@ public:
{
if (!includeLogicalLeftEdge())
return 0;
- return isHorizontal() ? renderer()->style()->borderLeftWidth() : renderer()->style()->borderTopWidth();
+ return isHorizontal() ? renderer()->style(isFirstLineStyle())->borderLeftWidth() : renderer()->style(isFirstLineStyle())->borderTopWidth();
}
int borderLogicalRight() const
{
if (!includeLogicalRightEdge())
return 0;
- return isHorizontal() ? renderer()->style()->borderRightWidth() : renderer()->style()->borderBottomWidth();
+ return isHorizontal() ? renderer()->style(isFirstLineStyle())->borderRightWidth() : renderer()->style(isFirstLineStyle())->borderBottomWidth();
}
int paddingLogicalLeft() const
{
@@ -297,20 +297,22 @@ protected:
InlineFlowBox* m_prevLineBox; // The previous box that also uses our RenderObject
InlineFlowBox* m_nextLineBox; // The next box that also uses our RenderObject
- bool m_includeLogicalLeftEdge : 1;
- bool m_includeLogicalRightEdge : 1;
- bool m_hasTextChildren : 1;
- bool m_hasTextDescendants : 1;
- bool m_descendantsHaveSameLineHeightAndBaseline : 1;
+private:
+ unsigned m_includeLogicalLeftEdge : 1;
+ unsigned m_includeLogicalRightEdge : 1;
+ unsigned m_hasTextChildren : 1;
+ unsigned m_hasTextDescendants : 1;
+ unsigned m_descendantsHaveSameLineHeightAndBaseline : 1;
+protected:
// The following members are only used by RootInlineBox but moved here to keep the bits packed.
// Whether or not this line uses alphabetic or ideographic baselines by default.
unsigned m_baselineType : 1; // FontBaseline
// If the line contains any ruby runs, then this will be true.
- bool m_hasAnnotationsBefore : 1;
- bool m_hasAnnotationsAfter : 1;
+ unsigned m_hasAnnotationsBefore : 1;
+ unsigned m_hasAnnotationsAfter : 1;
unsigned m_lineBreakBidiStatusEor : 5; // WTF::Unicode::Direction
unsigned m_lineBreakBidiStatusLastStrong : 5; // WTF::Unicode::Direction
@@ -320,7 +322,7 @@ protected:
#ifndef NDEBUG
private:
- bool m_hasBadChildList;
+ unsigned m_hasBadChildList : 1;
#endif
};
diff --git a/Source/WebCore/rendering/InlineTextBox.cpp b/Source/WebCore/rendering/InlineTextBox.cpp
index 639d6bad6..d6ed33287 100644
--- a/Source/WebCore/rendering/InlineTextBox.cpp
+++ b/Source/WebCore/rendering/InlineTextBox.cpp
@@ -59,21 +59,21 @@ static InlineTextBoxOverflowMap* gTextBoxesWithOverflow;
void InlineTextBox::destroy(RenderArena* arena)
{
- if (!m_knownToHaveNoOverflow && gTextBoxesWithOverflow)
+ if (!knownToHaveNoOverflow() && gTextBoxesWithOverflow)
gTextBoxesWithOverflow->remove(this);
InlineBox::destroy(arena);
}
LayoutRect InlineTextBox::logicalOverflowRect() const
{
- if (m_knownToHaveNoOverflow || !gTextBoxesWithOverflow)
+ if (knownToHaveNoOverflow() || !gTextBoxesWithOverflow)
return enclosingIntRect(logicalFrameRect());
return gTextBoxesWithOverflow->get(this);
}
void InlineTextBox::setLogicalOverflowRect(const LayoutRect& rect)
{
- ASSERT(!m_knownToHaveNoOverflow);
+ ASSERT(!knownToHaveNoOverflow());
if (!gTextBoxesWithOverflow)
gTextBoxesWithOverflow = new InlineTextBoxOverflowMap;
gTextBoxesWithOverflow->add(this, rect);
@@ -85,7 +85,7 @@ LayoutUnit InlineTextBox::baselinePosition(FontBaseline baselineType) const
return 0;
if (parent()->renderer() == renderer()->parent())
return parent()->baselinePosition(baselineType);
- return toRenderBoxModelObject(renderer()->parent())->baselinePosition(baselineType, m_firstLine, isHorizontal() ? HorizontalLine : VerticalLine, PositionOnContainingLine);
+ return toRenderBoxModelObject(renderer()->parent())->baselinePosition(baselineType, isFirstLineStyle(), isHorizontal() ? HorizontalLine : VerticalLine, PositionOnContainingLine);
}
LayoutUnit InlineTextBox::lineHeight() const
@@ -93,10 +93,10 @@ LayoutUnit InlineTextBox::lineHeight() const
if (!isText() || !renderer()->parent())
return 0;
if (m_renderer->isBR())
- return toRenderBR(m_renderer)->lineHeight(m_firstLine);
+ return toRenderBR(m_renderer)->lineHeight(isFirstLineStyle());
if (parent()->renderer() == renderer()->parent())
return parent()->lineHeight();
- return toRenderBoxModelObject(renderer()->parent())->lineHeight(m_firstLine, isHorizontal() ? HorizontalLine : VerticalLine, PositionOnContainingLine);
+ return toRenderBoxModelObject(renderer()->parent())->lineHeight(isFirstLineStyle(), isHorizontal() ? HorizontalLine : VerticalLine, PositionOnContainingLine);
}
LayoutUnit InlineTextBox::selectionTop()
@@ -174,20 +174,20 @@ static void adjustCharactersAndLengthForHyphen(BufferForAppendingHyphen& charact
length += hyphenString.length();
}
-IntRect InlineTextBox::localSelectionRect(int startPos, int endPos)
+LayoutRect InlineTextBox::localSelectionRect(int startPos, int endPos)
{
int sPos = max(startPos - m_start, 0);
int ePos = min(endPos - m_start, (int)m_len);
if (sPos > ePos)
- return IntRect();
+ return LayoutRect();
FontCachePurgePreventer fontCachePurgePreventer;
RenderText* textObj = textRenderer();
- int selTop = selectionTop();
- int selHeight = selectionHeight();
- RenderStyle* styleToUse = textObj->style(m_firstLine);
+ LayoutUnit selTop = selectionTop();
+ LayoutUnit selHeight = selectionHeight();
+ RenderStyle* styleToUse = textObj->style(isFirstLineStyle());
const Font& font = styleToUse->font();
BufferForAppendingHyphen charactersWithHyphen;
@@ -196,19 +196,19 @@ IntRect InlineTextBox::localSelectionRect(int startPos, int endPos)
if (respectHyphen)
endPos = textRun.length();
- IntRect r = enclosingIntRect(font.selectionRectForText(textRun, FloatPoint(logicalLeft(), selTop), selHeight, sPos, ePos));
+ LayoutRect r = enclosingIntRect(font.selectionRectForText(textRun, FloatPoint(logicalLeft(), selTop), selHeight, sPos, ePos));
- int logicalWidth = r.width();
+ LayoutUnit logicalWidth = r.width();
if (r.x() > logicalRight())
logicalWidth = 0;
else if (r.maxX() > logicalRight())
logicalWidth = logicalRight() - r.x();
- IntPoint topPoint = isHorizontal() ? IntPoint(r.x(), selTop) : IntPoint(selTop, r.x());
- int width = isHorizontal() ? logicalWidth : selHeight;
- int height = isHorizontal() ? selHeight : logicalWidth;
+ LayoutPoint topPoint = isHorizontal() ? LayoutPoint(r.x(), selTop) : LayoutPoint(selTop, r.x());
+ LayoutUnit width = isHorizontal() ? logicalWidth : selHeight;
+ LayoutUnit height = isHorizontal() ? selHeight : logicalWidth;
- return IntRect(topPoint, IntSize(width, height));
+ return LayoutRect(topPoint, LayoutSize(width, height));
}
void InlineTextBox::deleteLine(RenderArena* arena)
@@ -219,7 +219,7 @@ void InlineTextBox::deleteLine(RenderArena* arena)
void InlineTextBox::extractLine()
{
- if (m_extracted)
+ if (extracted())
return;
toRenderText(renderer())->extractTextBox(this);
@@ -227,7 +227,7 @@ void InlineTextBox::extractLine()
void InlineTextBox::attachLine()
{
- if (!m_extracted)
+ if (!extracted())
return;
toRenderText(renderer())->attachTextBox(this);
@@ -283,7 +283,7 @@ float InlineTextBox::placeEllipsisBox(bool flowIsLTR, float visibleLeftEdge, flo
// If we got here that means that we were only partially truncated and we need to return the pixel offset at which
// to place the ellipsis.
- float widthOfVisibleText = toRenderText(renderer())->width(m_start, offset, textPos(), m_firstLine);
+ float widthOfVisibleText = toRenderText(renderer())->width(m_start, offset, textPos(), isFirstLineStyle());
// The ellipsis needs to be placed just after the last visible character.
// Where "after" is defined by the flow directionality, not the inline
@@ -483,7 +483,7 @@ void InlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset,
LayoutUnit paintEnd = isHorizontal() ? paintInfo.rect.maxX() : paintInfo.rect.maxY();
LayoutUnit paintStart = isHorizontal() ? paintInfo.rect.x() : paintInfo.rect.y();
- LayoutPoint adjustedPaintOffset = paintOffset;
+ LayoutPoint adjustedPaintOffset = roundedIntPoint(paintOffset);
if (logicalStart >= paintEnd || logicalStart + logicalExtent <= paintStart)
return;
@@ -506,7 +506,7 @@ void InlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset,
// farther to the right.
// NOTE: WebKit's behavior differs from that of IE which appears to just overlay the ellipsis on top of the
// truncated string i.e. |Hello|CBA| -> |...lo|CBA|
- LayoutUnit widthOfVisibleText = toRenderText(renderer())->width(m_start, m_truncation, textPos(), m_firstLine);
+ LayoutUnit widthOfVisibleText = toRenderText(renderer())->width(m_start, m_truncation, textPos(), isFirstLineStyle());
LayoutUnit widthOfHiddenText = m_logicalWidth - widthOfVisibleText;
// FIXME: The hit testing logic also needs to take this translation into account.
LayoutSize truncationOffset(isLeftToRightDirection() ? widthOfHiddenText : -widthOfHiddenText, 0);
@@ -516,7 +516,7 @@ void InlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset,
GraphicsContext* context = paintInfo.context;
- RenderStyle* styleToUse = renderer()->style(m_firstLine);
+ RenderStyle* styleToUse = renderer()->style(isFirstLineStyle());
adjustedPaintOffset.move(0, styleToUse->isHorizontalWritingMode() ? 0 : -logicalHeight());
@@ -841,8 +841,12 @@ void InlineTextBox::paintSelection(GraphicsContext* context, const FloatPoint& b
if (respectHyphen)
ePos = textRun.length();
- int deltaY = renderer()->style()->isFlippedLinesWritingMode() ? selectionBottom() - logicalBottom() : logicalTop() - selectionTop();
- int selHeight = selectionHeight();
+ LayoutUnit selectionBottom = root()->selectionBottom();
+ LayoutUnit selectionTop = root()->selectionTopAdjustedForPrecedingBlock();
+
+ int deltaY = renderer()->style()->isFlippedLinesWritingMode() ? selectionBottom - logicalBottom() : logicalTop() - selectionTop;
+ int selHeight = max<LayoutUnit>(0, selectionBottom - selectionTop);
+
FloatPoint localOrigin(boxOrigin.x(), boxOrigin.y() - deltaY);
FloatRect clipRect(localOrigin, FloatSize(m_logicalWidth, selHeight));
@@ -904,7 +908,7 @@ void InlineTextBox::paintDecoration(GraphicsContext* context, const FloatPoint&
float width = m_logicalWidth;
if (m_truncation != cNoTruncation) {
- width = toRenderText(renderer())->width(m_start, m_truncation, textPos(), m_firstLine);
+ width = toRenderText(renderer())->width(m_start, m_truncation, textPos(), isFirstLineStyle());
if (!isLeftToRightDirection())
localOrigin.move(m_logicalWidth - width, 0);
}
@@ -919,7 +923,7 @@ void InlineTextBox::paintDecoration(GraphicsContext* context, const FloatPoint&
bool linesAreOpaque = !isPrinting && (!(deco & UNDERLINE) || underline.alpha() == 255) && (!(deco & OVERLINE) || overline.alpha() == 255) && (!(deco & LINE_THROUGH) || linethrough.alpha() == 255);
- RenderStyle* styleToUse = renderer()->style(m_firstLine);
+ RenderStyle* styleToUse = renderer()->style(isFirstLineStyle());
int baseline = styleToUse->fontMetrics().ascent();
bool setClip = false;
@@ -983,22 +987,24 @@ void InlineTextBox::paintDecoration(GraphicsContext* context, const FloatPoint&
context->clearShadow();
}
-static GraphicsContext::TextCheckingLineStyle textCheckingLineStyleForMarkerType(DocumentMarker::MarkerType markerType)
+static GraphicsContext::DocumentMarkerLineStyle lineStyleForMarkerType(DocumentMarker::MarkerType markerType)
{
switch (markerType) {
case DocumentMarker::Spelling:
- return GraphicsContext::TextCheckingSpellingLineStyle;
+ return GraphicsContext::DocumentMarkerSpellingLineStyle;
case DocumentMarker::Grammar:
- return GraphicsContext::TextCheckingGrammarLineStyle;
+ return GraphicsContext::DocumentMarkerGrammarLineStyle;
case DocumentMarker::CorrectionIndicator:
- return GraphicsContext::TextCheckingReplacementLineStyle;
+ return GraphicsContext::DocumentMarkerAutocorrectionReplacementLineStyle;
+ case DocumentMarker::DictationAlternatives:
+ return GraphicsContext::DocumentMarkerDictationAlternativesLineStyle;
default:
ASSERT_NOT_REACHED();
- return GraphicsContext::TextCheckingSpellingLineStyle;
+ return GraphicsContext::DocumentMarkerSpellingLineStyle;
}
}
-void InlineTextBox::paintSpellingOrGrammarMarker(GraphicsContext* pt, const FloatPoint& boxOrigin, DocumentMarker* marker, RenderStyle* style, const Font& font, bool grammar)
+void InlineTextBox::paintDocumentMarker(GraphicsContext* pt, const FloatPoint& boxOrigin, DocumentMarker* marker, RenderStyle* style, const Font& font, bool grammar)
{
// Never print spelling/grammar markers (5327887)
if (textRenderer()->document()->printing())
@@ -1053,7 +1059,7 @@ void InlineTextBox::paintSpellingOrGrammarMarker(GraphicsContext* pt, const Floa
// So, we generally place the underline at the bottom of the text, but in larger fonts that's not so good so
// we pin to two pixels under the baseline.
int lineThickness = cMisspellingLineThickness;
- int baseline = renderer()->style(m_firstLine)->fontMetrics().ascent();
+ int baseline = renderer()->style(isFirstLineStyle())->fontMetrics().ascent();
int descent = logicalHeight() - baseline;
int underlineOffset;
if (descent <= (2 + lineThickness)) {
@@ -1063,7 +1069,7 @@ void InlineTextBox::paintSpellingOrGrammarMarker(GraphicsContext* pt, const Floa
// In larger fonts, though, place the underline up near the baseline to prevent a big gap.
underlineOffset = baseline + 2;
}
- pt->drawLineForTextChecking(FloatPoint(boxOrigin.x() + start, boxOrigin.y() + underlineOffset), width, textCheckingLineStyleForMarkerType(marker->type()));
+ pt->drawLineForDocumentMarker(FloatPoint(boxOrigin.x() + start, boxOrigin.y() + underlineOffset), width, lineStyleForMarkerType(marker->type()));
}
void InlineTextBox::paintTextMatchMarker(GraphicsContext* pt, const FloatPoint& boxOrigin, DocumentMarker* marker, RenderStyle* style, const Font& font)
@@ -1130,6 +1136,7 @@ void InlineTextBox::paintDocumentMarkers(GraphicsContext* pt, const FloatPoint&
case DocumentMarker::Spelling:
case DocumentMarker::CorrectionIndicator:
case DocumentMarker::Replacement:
+ case DocumentMarker::DictationAlternatives:
if (background)
continue;
break;
@@ -1153,17 +1160,16 @@ void InlineTextBox::paintDocumentMarkers(GraphicsContext* pt, const FloatPoint&
// marker intersects this run. Paint it.
switch (marker->type()) {
case DocumentMarker::Spelling:
- paintSpellingOrGrammarMarker(pt, boxOrigin, marker, style, font, false);
+ case DocumentMarker::CorrectionIndicator:
+ case DocumentMarker::DictationAlternatives:
+ paintDocumentMarker(pt, boxOrigin, marker, style, font, false);
break;
case DocumentMarker::Grammar:
- paintSpellingOrGrammarMarker(pt, boxOrigin, marker, style, font, true);
+ paintDocumentMarker(pt, boxOrigin, marker, style, font, true);
break;
case DocumentMarker::TextMatch:
paintTextMatchMarker(pt, boxOrigin, marker, style, font);
break;
- case DocumentMarker::CorrectionIndicator:
- paintSpellingOrGrammarMarker(pt, boxOrigin, marker, style, font, false);
- break;
case DocumentMarker::Replacement:
computeRectForReplacementMarker(marker, style, font);
break;
@@ -1187,7 +1193,7 @@ void InlineTextBox::paintCompositionUnderline(GraphicsContext* ctx, const FloatP
if (paintStart <= underline.startOffset) {
paintStart = underline.startOffset;
useWholeWidth = false;
- start = toRenderText(renderer())->width(m_start, paintStart - m_start, textPos(), m_firstLine);
+ start = toRenderText(renderer())->width(m_start, paintStart - m_start, textPos(), isFirstLineStyle());
}
if (paintEnd != underline.endOffset) { // end points at the last char, not past it
paintEnd = min(paintEnd, (unsigned)underline.endOffset);
@@ -1198,14 +1204,14 @@ void InlineTextBox::paintCompositionUnderline(GraphicsContext* ctx, const FloatP
useWholeWidth = false;
}
if (!useWholeWidth) {
- width = toRenderText(renderer())->width(paintStart, paintEnd - paintStart, textPos() + start, m_firstLine);
+ width = toRenderText(renderer())->width(paintStart, paintEnd - paintStart, textPos() + start, isFirstLineStyle());
}
// Thick marked text underlines are 2px thick as long as there is room for the 2px line under the baseline.
// All other marked text underlines are 1px thick.
// If there's not enough space the underline will touch or overlap characters.
int lineThickness = 1;
- int baseline = renderer()->style(m_firstLine)->fontMetrics().ascent();
+ int baseline = renderer()->style(isFirstLineStyle())->fontMetrics().ascent();
if (underline.thick && logicalHeight() - baseline >= 2)
lineThickness = 2;
@@ -1251,7 +1257,7 @@ int InlineTextBox::offsetForPosition(float lineOffset, bool includePartialGlyphs
FontCachePurgePreventer fontCachePurgePreventer;
RenderText* text = toRenderText(renderer());
- RenderStyle* style = text->style(m_firstLine);
+ RenderStyle* style = text->style(isFirstLineStyle());
const Font& font = style->font();
return font.offsetForPosition(constructTextRun(style, font), lineOffset - logicalLeft(), includePartialGlyphs);
}
@@ -1267,7 +1273,7 @@ float InlineTextBox::positionForOffset(int offset) const
FontCachePurgePreventer fontCachePurgePreventer;
RenderText* text = toRenderText(renderer());
- RenderStyle* styleToUse = text->style(m_firstLine);
+ RenderStyle* styleToUse = text->style(isFirstLineStyle());
ASSERT(styleToUse);
const Font& font = styleToUse->font();
int from = !isLeftToRightDirection() ? offset - m_start : 0;
@@ -1325,7 +1331,7 @@ TextRun InlineTextBox::constructTextRun(RenderStyle* style, const Font& font, co
ASSERT(maximumLength >= length);
- TextRun run(characters, length, textRenderer->allowTabs(), textPos(), expansion(), expansionBehavior(), direction(), m_dirOverride || style->rtlOrdering() == VisualOrder);
+ TextRun run(characters, length, textRenderer->allowTabs(), textPos(), expansion(), expansionBehavior(), direction(), dirOverride() || style->rtlOrdering() == VisualOrder, !textRenderer->canUseSimpleFontCodePath());
if (textRunNeedsRenderingContext(font))
run.setRenderingContext(SVGTextRunRenderingContext::create(textRenderer));
diff --git a/Source/WebCore/rendering/InlineTextBox.h b/Source/WebCore/rendering/InlineTextBox.h
index e59660e3f..a9bde74f0 100644
--- a/Source/WebCore/rendering/InlineTextBox.h
+++ b/Source/WebCore/rendering/InlineTextBox.h
@@ -75,11 +75,10 @@ public:
unsigned short truncation() { return m_truncation; }
- bool hasHyphen() const { return m_hasEllipsisBoxOrHyphen; }
- void setHasHyphen(bool hasHyphen) { m_hasEllipsisBoxOrHyphen = hasHyphen; }
-
- bool canHaveLeadingExpansion() const { return m_hasSelectedChildrenOrCanHaveLeadingExpansion; }
- void setCanHaveLeadingExpansion(bool canHaveLeadingExpansion) { m_hasSelectedChildrenOrCanHaveLeadingExpansion = canHaveLeadingExpansion; }
+ using InlineBox::hasHyphen;
+ using InlineBox::setHasHyphen;
+ using InlineBox::canHaveLeadingExpansion;
+ using InlineBox::setCanHaveLeadingExpansion;
static inline bool compareByStart(const InlineTextBox* first, const InlineTextBox* second) { return first->start() < second->start(); }
@@ -110,7 +109,7 @@ private:
public:
virtual FloatRect calculateBoundaries() const { return FloatRect(x(), y(), width(), height()); }
- virtual IntRect localSelectionRect(int startPos, int endPos);
+ virtual LayoutRect localSelectionRect(int startPos, int endPos);
bool isSelected(int startPos, int endPos) const;
void selectionStartEnd(int& sPos, int& ePos);
@@ -136,7 +135,12 @@ private:
public:
virtual bool isLineBreak() const;
- void setExpansion(int expansion) { m_logicalWidth -= m_expansion; m_expansion = expansion; m_logicalWidth += m_expansion; }
+ void setExpansion(int newExpansion)
+ {
+ m_logicalWidth -= expansion();
+ InlineBox::setExpansion(newExpansion);
+ m_logicalWidth += newExpansion;
+ }
private:
virtual bool isInlineTextBox() const { return true; }
@@ -178,14 +182,14 @@ protected:
private:
void paintDecoration(GraphicsContext*, const FloatPoint& boxOrigin, int decoration, const ShadowData*);
void paintSelection(GraphicsContext*, const FloatPoint& boxOrigin, RenderStyle*, const Font&);
- void paintSpellingOrGrammarMarker(GraphicsContext*, const FloatPoint& boxOrigin, DocumentMarker*, RenderStyle*, const Font&, bool grammar);
+ void paintDocumentMarker(GraphicsContext*, const FloatPoint& boxOrigin, DocumentMarker*, RenderStyle*, const Font&, bool grammar);
void paintTextMatchMarker(GraphicsContext*, const FloatPoint& boxOrigin, DocumentMarker*, RenderStyle*, const Font&);
void computeRectForReplacementMarker(DocumentMarker*, RenderStyle*, const Font&);
TextRun::ExpansionBehavior expansionBehavior() const
{
return (canHaveLeadingExpansion() ? TextRun::AllowLeadingExpansion : TextRun::ForbidLeadingExpansion)
- | (m_expansion && nextLeafChild() ? TextRun::AllowTrailingExpansion : TextRun::ForbidTrailingExpansion);
+ | (expansion() && nextLeafChild() ? TextRun::AllowTrailingExpansion : TextRun::ForbidTrailingExpansion);
}
};
diff --git a/Source/WebCore/rendering/LayoutRepainter.cpp b/Source/WebCore/rendering/LayoutRepainter.cpp
index 80b659df6..205ad4ab8 100644
--- a/Source/WebCore/rendering/LayoutRepainter.cpp
+++ b/Source/WebCore/rendering/LayoutRepainter.cpp
@@ -30,14 +30,14 @@
namespace WebCore {
-LayoutRepainter::LayoutRepainter(RenderObject& object, bool checkForRepaint, const IntRect* oldBounds)
+LayoutRepainter::LayoutRepainter(RenderObject& object, bool checkForRepaint)
: m_object(object)
, m_repaintContainer(0)
, m_checkForRepaint(checkForRepaint)
{
if (m_checkForRepaint) {
m_repaintContainer = m_object.containerForRepaint();
- m_oldBounds = oldBounds ? *oldBounds : m_object.clippedOverflowRectForRepaint(m_repaintContainer);
+ m_oldBounds = m_object.clippedOverflowRectForRepaint(m_repaintContainer);
m_oldOutlineBox = m_object.outlineBoundsForRepaint(m_repaintContainer);
}
}
diff --git a/Source/WebCore/rendering/LayoutRepainter.h b/Source/WebCore/rendering/LayoutRepainter.h
index 60aabc736..57400faeb 100644
--- a/Source/WebCore/rendering/LayoutRepainter.h
+++ b/Source/WebCore/rendering/LayoutRepainter.h
@@ -35,7 +35,7 @@ class RenderBoxModelObject;
class LayoutRepainter {
public:
- LayoutRepainter(RenderObject&, bool checkForRepaint, const IntRect* oldBounds = 0);
+ LayoutRepainter(RenderObject&, bool checkForRepaint);
bool checkForRepaint() const { return m_checkForRepaint; }
@@ -45,8 +45,9 @@ public:
private:
RenderObject& m_object;
RenderBoxModelObject* m_repaintContainer;
- IntRect m_oldBounds;
- IntRect m_oldOutlineBox;
+ // We store these values as LayoutRects, but the final invalidations will be pixel snapped
+ LayoutRect m_oldBounds;
+ LayoutRect m_oldOutlineBox;
bool m_checkForRepaint;
};
diff --git a/Source/WebCore/rendering/LayoutTypes.h b/Source/WebCore/rendering/LayoutTypes.h
index 2041ee597..dd56ad710 100644
--- a/Source/WebCore/rendering/LayoutTypes.h
+++ b/Source/WebCore/rendering/LayoutTypes.h
@@ -37,97 +37,102 @@
#define LayoutTypes_h
#include "FloatRect.h"
+#include "FractionalLayoutRect.h"
+#include "FractionalLayoutUnit.h"
#include "IntRect.h"
-#include <wtf/UnusedParam.h>
+
+#include <wtf/MathExtras.h>
namespace WebCore {
-typedef int LayoutUnit;
-typedef IntPoint LayoutPoint;
-typedef IntSize LayoutSize;
-typedef IntRect LayoutRect;
+typedef FractionalLayoutUnit LayoutUnit;
+typedef FractionalLayoutPoint LayoutPoint;
+typedef FractionalLayoutSize LayoutSize;
+typedef FractionalLayoutRect LayoutRect;
-const LayoutUnit zeroLayoutUnit = 0;
+#define MAX_LAYOUT_UNIT LayoutUnit::max()
+#define MIN_LAYOUT_UNIT LayoutUnit::min()
+#define ZERO_LAYOUT_UNIT LayoutUnit(0)
-inline LayoutRect enclosingLayoutRect(const FloatRect& rect)
+inline FractionalLayoutRect enclosingLayoutRect(const FloatRect& rect)
{
return enclosingIntRect(rect);
}
-inline IntRect pixelSnappedIntRect(const LayoutRect& rect)
+inline LayoutSize roundedLayoutSize(const FloatSize& s)
{
- return rect;
+#if ENABLE(SUBPIXEL_LAYOUT)
+ return FractionalLayoutSize(s);
+#else
+ return roundedIntSize(s);
+#endif
}
inline IntRect pixelSnappedIntRect(LayoutUnit left, LayoutUnit top, LayoutUnit width, LayoutUnit height)
{
- return IntRect(left, top, width, height);
-}
-
-inline IntRect pixelSnappedIntRect(const LayoutPoint& location, const LayoutSize& size)
-{
- return IntRect(location, size);
+ return IntRect(left.round(), top.round(), snapSizeToPixel(width, left), snapSizeToPixel(height, top));
}
inline IntRect pixelSnappedIntRectFromEdges(LayoutUnit left, LayoutUnit top, LayoutUnit right, LayoutUnit bottom)
{
- return IntRect(left, top, right - left, bottom - top);
-}
-
-inline int snapSizeToPixel(LayoutUnit size, LayoutUnit location)
-{
- UNUSED_PARAM(location);
- return size;
-}
-
-inline IntSize roundedIntSize(const LayoutSize& s)
-{
- return s;
-}
-
-inline LayoutSize roundedLayoutSize(const FloatSize& s)
-{
- return roundedIntSize(s);
-}
-
-inline IntPoint roundedIntPoint(const LayoutPoint& p)
-{
- return p;
+ return IntRect(left.round(), top.round(), snapSizeToPixel(right - left, left), snapSizeToPixel(bottom - top, top));
}
inline LayoutPoint roundedLayoutPoint(const FloatPoint& p)
{
+#if ENABLE(SUBPIXEL_LAYOUT)
+ return FractionalLayoutPoint(p);
+#else
return roundedIntPoint(p);
+#endif
}
inline LayoutPoint flooredLayoutPoint(const FloatPoint& p)
{
- return flooredIntPoint(p);
+ return LayoutPoint(p.x(), p.y());
}
inline LayoutPoint flooredLayoutPoint(const FloatSize& s)
{
- return flooredIntPoint(s);
+ return LayoutPoint(s.width(), s.height());
}
inline LayoutSize flooredLayoutSize(const FloatPoint& p)
{
- return LayoutSize(static_cast<int>(p.x()), static_cast<int>(p.y()));
+ return LayoutSize(p.x(), p.y());
}
inline int roundToInt(LayoutUnit value)
{
- return value;
+ return value.round();
+}
+
+inline int floorToInt(LayoutUnit value)
+{
+ return value.toInt();
}
inline LayoutUnit roundedLayoutUnit(float value)
{
- return lroundf(value);
+#if ENABLE(SUBPIXEL_LAYOUT)
+ return FractionalLayoutUnit(value);
+#else
+ return static_cast<int>(lroundf(value));
+#endif
}
inline LayoutUnit ceiledLayoutUnit(float value)
{
+#if ENABLE(SUBPIXEL_LAYOUT)
+ return FractionalLayoutUnit(value);
+#else
return ceilf(value);
+#endif
+}
+
+inline LayoutUnit absoluteValue(const LayoutUnit& value)
+{
+ return value.abs();
}
inline LayoutSize toLayoutSize(const LayoutPoint& p)
@@ -142,12 +147,22 @@ inline LayoutPoint toLayoutPoint(const LayoutSize& p)
inline LayoutUnit layoutMod(const LayoutUnit& numerator, const LayoutUnit& denominator)
{
- return numerator % denominator;
+ return numerator.toInt() % denominator.toInt();
}
inline LayoutUnit clampToLayoutUnit(double value)
{
- return clampToInteger(value);
+ return clampTo<FractionalLayoutUnit>(value, FractionalLayoutUnit::min(), FractionalLayoutUnit::max());
+}
+
+inline IntRect pixelSnappedIntRect(LayoutPoint location, LayoutSize size)
+{
+ return IntRect(roundedIntPoint(location), pixelSnappedIntSize(size, location));
+}
+
+inline bool isIntegerValue(const LayoutUnit value)
+{
+ return value.floor() == value;
}
} // namespace WebCore
diff --git a/Source/WebCore/rendering/PaintInfo.h b/Source/WebCore/rendering/PaintInfo.h
index e28ba0dab..7ed743272 100644
--- a/Source/WebCore/rendering/PaintInfo.h
+++ b/Source/WebCore/rendering/PaintInfo.h
@@ -32,7 +32,9 @@
#include "GraphicsContext.h"
#include "IntRect.h"
+#include "LayoutTypes.h"
#include "PaintPhase.h"
+#include <limits>
#include <wtf/HashMap.h>
#include <wtf/ListHashSet.h>
@@ -96,7 +98,7 @@ struct PaintInfo {
}
#endif
- static IntRect infiniteRect() { return IntRect(INT_MIN / 2, INT_MIN / 2, INT_MAX, INT_MAX); }
+ static IntRect infiniteRect() { return IntRect(LayoutRect::infiniteRect()); }
// FIXME: Introduce setters/getters at some point. Requires a lot of changes throughout rendering/.
GraphicsContext* context;
diff --git a/Source/WebCore/rendering/RenderApplet.cpp b/Source/WebCore/rendering/RenderApplet.cpp
index 090ba1678..1b8b75e17 100644
--- a/Source/WebCore/rendering/RenderApplet.cpp
+++ b/Source/WebCore/rendering/RenderApplet.cpp
@@ -44,13 +44,13 @@ RenderApplet::~RenderApplet()
{
}
-LayoutSize RenderApplet::intrinsicSize() const
+IntSize RenderApplet::intrinsicSize() const
{
// FIXME: This doesn't make sense. We can't just start returning
// a different size once we've created the widget and expect
// layout and sizing to be correct. We should remove this and
// pass the appropriate intrinsic size in the constructor.
- return widget() ? LayoutSize(50, 50) : LayoutSize(150, 150);
+ return widget() ? IntSize(50, 50) : IntSize(150, 150);
}
void RenderApplet::createWidgetIfNecessary()
diff --git a/Source/WebCore/rendering/RenderApplet.h b/Source/WebCore/rendering/RenderApplet.h
index 9478c5b79..007902d1f 100644
--- a/Source/WebCore/rendering/RenderApplet.h
+++ b/Source/WebCore/rendering/RenderApplet.h
@@ -46,7 +46,7 @@ private:
virtual bool isApplet() const { return true; }
virtual void layout();
- virtual LayoutSize intrinsicSize() const;
+ virtual IntSize intrinsicSize() const;
#if USE(ACCELERATED_COMPOSITING)
virtual bool requiresLayer() const;
diff --git a/Source/WebCore/rendering/RenderArena.cpp b/Source/WebCore/rendering/RenderArena.cpp
index 6c4c5dc15..b01f65ddd 100644
--- a/Source/WebCore/rendering/RenderArena.cpp
+++ b/Source/WebCore/rendering/RenderArena.cpp
@@ -110,7 +110,9 @@ void* RenderArena::allocate(size_t size)
if (!result) {
// Allocate a new chunk from the arena
- ARENA_ALLOCATE(result, &m_pool, size);
+ unsigned bytesAllocated = 0;
+ ARENA_ALLOCATE(result, &m_pool, size, &bytesAllocated);
+ m_totalAllocated += bytesAllocated;
}
return result;
diff --git a/Source/WebCore/rendering/RenderArena.h b/Source/WebCore/rendering/RenderArena.h
index 9150e7135..0b64e1877 100644
--- a/Source/WebCore/rendering/RenderArena.h
+++ b/Source/WebCore/rendering/RenderArena.h
@@ -54,6 +54,7 @@ public:
void free(size_t, void*);
size_t totalRenderArenaSize() const { return m_totalSize; }
+ size_t totalRenderArenaAllocatedBytes() const { return m_totalAllocated; }
private:
// Underlying arena pool
@@ -64,6 +65,7 @@ private:
void* m_recyclers[gMaxRecycledSize >> 2];
size_t m_totalSize;
+ size_t m_totalAllocated;
};
} // namespace WebCore
diff --git a/Source/WebCore/rendering/RenderBR.cpp b/Source/WebCore/rendering/RenderBR.cpp
index ca14e45be..d80393614 100644
--- a/Source/WebCore/rendering/RenderBR.cpp
+++ b/Source/WebCore/rendering/RenderBR.cpp
@@ -43,11 +43,11 @@ int RenderBR::lineHeight(bool firstLine) const
if (firstLine && document()->usesFirstLineRules()) {
RenderStyle* s = style(firstLine);
if (s != style())
- return s->computedLineHeight();
+ return s->computedLineHeight(view());
}
if (m_lineHeight == -1)
- m_lineHeight = style()->computedLineHeight();
+ m_lineHeight = style()->computedLineHeight(view());
return m_lineHeight;
}
diff --git a/Source/WebCore/rendering/RenderBlock.cpp b/Source/WebCore/rendering/RenderBlock.cpp
index d87d77226..d03463b51 100755
--- a/Source/WebCore/rendering/RenderBlock.cpp
+++ b/Source/WebCore/rendering/RenderBlock.cpp
@@ -45,11 +45,11 @@
#include "RenderBoxRegionInfo.h"
#include "RenderCombineText.h"
#include "RenderDeprecatedFlexibleBox.h"
-#include "RenderFlowThread.h"
#include "RenderImage.h"
#include "RenderInline.h"
#include "RenderLayer.h"
#include "RenderMarquee.h"
+#include "RenderNamedFlowThread.h"
#include "RenderRegion.h"
#include "RenderReplica.h"
#include "RenderTableCell.h"
@@ -69,6 +69,29 @@ namespace WebCore {
using namespace HTMLNames;
+struct SameSizeAsRenderBlock : public RenderBox {
+ void* pointers[3];
+ RenderObjectChildList children;
+ RenderLineBoxList lineBoxes;
+ uint32_t bitfields;
+};
+
+COMPILE_ASSERT(sizeof(RenderBlock) == sizeof(SameSizeAsRenderBlock), RenderBlock_should_stay_small);
+
+struct SameSizeAsFloatingObject {
+ void* pointers[2];
+ LayoutRect rect;
+ int paginationStrut;
+ uint32_t bitfields : 8;
+};
+
+COMPILE_ASSERT(sizeof(RenderBlock::MarginValues) == sizeof(LayoutUnit[4]), MarginValues_should_stay_small);
+
+struct SameSizeAsMarginInfo {
+ uint32_t bitfields : 16;
+ LayoutUnit margins[2];
+};
+
typedef WTF::HashMap<const RenderBox*, ColumnInfo*> ColumnInfoMap;
static ColumnInfoMap* gColumnInfoMap = 0;
@@ -167,8 +190,8 @@ RenderBlock::MarginInfo::MarginInfo(RenderBlock* block, LayoutUnit beforeBorderP
m_quirkContainer = block->isTableCell() || block->isBody() || blockStyle->marginBeforeCollapse() == MDISCARD
|| blockStyle->marginAfterCollapse() == MDISCARD;
- m_positiveMargin = m_canCollapseMarginBeforeWithChildren ? block->maxPositiveMarginBefore() : zeroLayoutUnit;
- m_negativeMargin = m_canCollapseMarginBeforeWithChildren ? block->maxNegativeMarginBefore() : zeroLayoutUnit;
+ m_positiveMargin = m_canCollapseMarginBeforeWithChildren ? block->maxPositiveMarginBefore() : ZERO_LAYOUT_UNIT;
+ m_negativeMargin = m_canCollapseMarginBeforeWithChildren ? block->maxNegativeMarginBefore() : ZERO_LAYOUT_UNIT;
}
// -------------------------------------------------------------------------------------------------------
@@ -177,10 +200,11 @@ RenderBlock::RenderBlock(Node* node)
: RenderBox(node)
, m_lineHeight(-1)
, m_beingDestroyed(false)
- , m_hasPositionedFloats(false)
, m_hasMarkupTruncation(false)
{
setChildrenInline(true);
+ COMPILE_ASSERT(sizeof(RenderBlock::FloatingObject) == sizeof(SameSizeAsFloatingObject), FloatingObject_should_stay_small);
+ COMPILE_ASSERT(sizeof(RenderBlock::MarginInfo) == sizeof(SameSizeAsMarginInfo), MarginInfo_should_stay_small);
}
RenderBlock::~RenderBlock()
@@ -481,7 +505,8 @@ void RenderBlock::addChildToAnonymousColumnBlocks(RenderObject* newChild, Render
}
// Split our anonymous blocks.
- RenderObject* newBeforeChild = splitAnonymousBlocksAroundChild(beforeChild);
+ RenderObject* newBeforeChild = splitAnonymousBoxesAroundChild(beforeChild);
+
// Create a new anonymous box of the appropriate type.
RenderBlock* newBox = newChildHasColumnSpan ? createAnonymousColumnSpanBlock() : createAnonymousColumnsBlock();
@@ -681,94 +706,6 @@ void RenderBlock::splitFlow(RenderObject* beforeChild, RenderBlock* newBlockBox,
post->setNeedsLayoutAndPrefWidthsRecalc();
}
-RenderObject* RenderBlock::splitAnonymousBlocksAroundChild(RenderObject* beforeChild)
-{
- if (beforeChild->isTablePart())
- beforeChild = splitTablePartsAroundChild(beforeChild);
-
- while (beforeChild->parent() != this) {
- RenderBlock* blockToSplit = toRenderBlock(beforeChild->parent());
- if (blockToSplit->firstChild() != beforeChild) {
- // We have to split the parentBlock into two blocks.
- RenderBlock* post = createAnonymousBlockWithSameTypeAs(blockToSplit);
- post->setChildrenInline(blockToSplit->childrenInline());
- RenderBlock* parentBlock = toRenderBlock(blockToSplit->parent());
- parentBlock->children()->insertChildNode(parentBlock, post, blockToSplit->nextSibling());
- blockToSplit->moveChildrenTo(post, beforeChild, 0, blockToSplit->hasLayer());
- post->setNeedsLayoutAndPrefWidthsRecalc();
- blockToSplit->setNeedsLayoutAndPrefWidthsRecalc();
- beforeChild = post;
- } else
- beforeChild = blockToSplit;
- }
- return beforeChild;
-}
-
-static void markTableForSectionAndCellRecalculation(RenderObject* child)
-{
- RenderObject* curr = child;
- while (!curr->isTable()) {
- if (curr->isTableSection())
- toRenderTableSection(curr)->setNeedsCellRecalc();
- curr = curr->parent();
- }
-
- RenderTable* table = toRenderTable(curr);
- table->setNeedsSectionRecalc();
- table->setNeedsLayoutAndPrefWidthsRecalc();
-}
-
-static void moveAllTableChildrenTo(RenderObject* fromTablePart, RenderTable* toTable, RenderObject* startChild)
-{
- for (RenderObject* curr = startChild; curr;) {
- // Need to store next sibling as we won't have access to it
- // after we are removed from table.
- RenderObject* next = curr->nextSibling();
- fromTablePart->removeChild(curr);
- toTable->addChild(curr);
- if (curr->isTableSection())
- toRenderTableSection(curr)->setNeedsCellRecalc();
- curr->setNeedsLayoutAndPrefWidthsRecalc();
- curr = next;
- }
-
- // This marks fromTable for section and cell recalculation.
- markTableForSectionAndCellRecalculation(fromTablePart);
-
- // startChild is now part of toTable. This marks toTable for section and cell recalculation.
- markTableForSectionAndCellRecalculation(startChild);
-}
-
-RenderObject* RenderBlock::splitTablePartsAroundChild(RenderObject* beforeChild)
-{
- ASSERT(beforeChild->isTablePart());
-
- while (beforeChild->parent() != this) {
- RenderObject* tablePartToSplit = beforeChild->parent();
- if (!tablePartToSplit->isTablePart() && !tablePartToSplit->isTable())
- break;
- if (tablePartToSplit->firstChild() != beforeChild) {
- // Get our table container.
- RenderObject* curr = tablePartToSplit;
- while (!curr->isTable())
- curr = curr->parent();
- RenderTable* table = toRenderTable(curr);
-
- // Create an anonymous table container next to our table container.
- RenderBlock* parentBlock = toRenderBlock(table->parent());
- RenderTable* postTable = parentBlock->createAnonymousTable();
- parentBlock->children()->insertChildNode(parentBlock, postTable, table->nextSibling());
-
- // Move all the children from beforeChild to the newly created anonymous table container.
- moveAllTableChildrenTo(tablePartToSplit, postTable, beforeChild);
-
- beforeChild = postTable;
- } else
- beforeChild = tablePartToSplit;
- }
- return beforeChild;
-}
-
void RenderBlock::makeChildrenAnonymousColumnBlocks(RenderObject* beforeChild, RenderBlock* newBlockBox, RenderObject* newChild)
{
RenderBlock* pre = 0;
@@ -780,7 +717,7 @@ void RenderBlock::makeChildrenAnonymousColumnBlocks(RenderObject* beforeChild, R
block->deleteLineBoxTree();
if (beforeChild && beforeChild->parent() != this)
- beforeChild = splitAnonymousBlocksAroundChild(beforeChild);
+ beforeChild = splitAnonymousBoxesAroundChild(beforeChild);
if (beforeChild != firstChild()) {
pre = block->createAnonymousColumnsBlock();
@@ -868,7 +805,13 @@ void RenderBlock::addChildIgnoringAnonymousColumnBlocks(RenderObject* newChild,
// If the requested beforeChild is not one of our children, then this is because
// there is an anonymous container within this object that contains the beforeChild.
RenderObject* beforeChildAnonymousContainer = beforeChildContainer;
- if (beforeChildAnonymousContainer->isAnonymousBlock()) {
+ if (beforeChildAnonymousContainer->isAnonymousBlock()
+#if ENABLE(FULLSCREEN_API)
+ // Full screen renderers and full screen placeholders act as anonymous blocks, not tables:
+ || beforeChildAnonymousContainer->isRenderFullScreen()
+ || beforeChildAnonymousContainer->isRenderFullScreenPlaceholder()
+#endif
+ ) {
// Insert the child into the anonymous block box instead of here.
if (newChild->isInline() || beforeChild->parent()->firstChild() != beforeChild)
beforeChild->parent()->addChild(newChild, beforeChild);
@@ -884,7 +827,7 @@ void RenderBlock::addChildIgnoringAnonymousColumnBlocks(RenderObject* newChild,
return;
}
- beforeChild = splitTablePartsAroundChild(beforeChild);
+ beforeChild = splitAnonymousBoxesAroundChild(beforeChild);
ASSERT(beforeChild->parent() == this);
if (beforeChild->parent() != this) {
@@ -921,12 +864,19 @@ void RenderBlock::addChildIgnoringAnonymousColumnBlocks(RenderObject* newChild,
// Someone may have put a <p> inside a <q>, causing a split. When this happens, the :after content
// has to move into the inline continuation. Call updateBeforeAfterContent to ensure that our :after
// content gets properly destroyed.
+ bool isFirstChild = (beforeChild == firstChild());
bool isLastChild = (beforeChild == lastChild());
if (document()->usesBeforeAfterRules())
children()->updateBeforeAfterContent(this, AFTER);
- if (isLastChild && beforeChild != lastChild())
- beforeChild = 0; // We destroyed the last child, so now we need to update our insertion
- // point to be 0. It's just a straight append now.
+ if (isLastChild && beforeChild != lastChild()) {
+ // We destroyed the last child, so now we need to update our insertion
+ // point to be 0. It's just a straight append now.
+ beforeChild = 0;
+ } else if (isFirstChild && beforeChild != firstChild()) {
+ // If beforeChild was the last anonymous block that collapsed,
+ // then we need to update its value.
+ beforeChild = firstChild();
+ }
splitFlow(beforeChild, newBox, newChild, oldContinuation);
return;
@@ -1063,30 +1013,6 @@ RootInlineBox* RenderBlock::createAndAppendRootInlineBox()
return rootBox;
}
-void RenderBlock::moveChildTo(RenderBlock* toBlock, RenderObject* child, RenderObject* beforeChild, bool fullRemoveInsert)
-{
- ASSERT(this == child->parent());
- ASSERT(!beforeChild || toBlock == beforeChild->parent());
- if (fullRemoveInsert) {
- // Takes care of adding the new child correctly if toBlock and fromBlock
- // have different kind of children (block vs inline).
- toBlock->addChildIgnoringContinuation(children()->removeChildNode(this, child), beforeChild);
- } else
- toBlock->children()->insertChildNode(toBlock, children()->removeChildNode(this, child, false), beforeChild, false);
-}
-
-void RenderBlock::moveChildrenTo(RenderBlock* toBlock, RenderObject* startChild, RenderObject* endChild, RenderObject* beforeChild, bool fullRemoveInsert)
-{
- ASSERT(!beforeChild || toBlock == beforeChild->parent());
-
- for (RenderObject* child = startChild; child && child != endChild; ) {
- // Save our next sibling as moveChildTo will clear it.
- RenderObject* nextSibling = child->nextSibling();
- moveChildTo(toBlock, child, beforeChild, fullRemoveInsert);
- child = nextSibling;
- }
-}
-
void RenderBlock::makeChildrenNonInline(RenderObject *insertionPoint)
{
// makeChildrenNonInline takes a block whose children are *all* inline and it
@@ -1214,8 +1140,8 @@ void RenderBlock::collapseAnonymousBoxChild(RenderBlock* parent, RenderObject* c
// Delete the now-empty block's lines and nuke it.
if (!parent->documentBeingDestroyed())
anonBlock->deleteLineBoxTree();
- if (childFlowThread && !parent->documentBeingDestroyed())
- childFlowThread->removeFlowChildInfo(anonBlock);
+ if (!parent->documentBeingDestroyed() && childFlowThread && childFlowThread->isRenderNamedFlowThread())
+ toRenderNamedFlowThread(childFlowThread)->removeFlowChildInfo(anonBlock);
anonBlock->destroy();
}
@@ -1241,7 +1167,7 @@ void RenderBlock::removeChild(RenderObject* oldChild)
// to clear out inherited column properties by just making a new style, and to also clear the
// column span flag if it is set.
ASSERT(!inlineChildrenBlock->continuation());
- RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyle(style());
+ RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(style(), BLOCK);
children()->removeChildNode(this, inlineChildrenBlock, inlineChildrenBlock->hasLayer());
inlineChildrenBlock->setStyle(newStyle);
@@ -1371,18 +1297,12 @@ void RenderBlock::finishDelayUpdateScrollInfo()
void RenderBlock::updateScrollInfoAfterLayout()
{
- if (!hasOverflowClip())
- return;
-
- if (!hasLayer()) {
- updateCachedSizeForOverflowClip();
- return;
+ if (hasOverflowClip()) {
+ if (gDelayUpdateScrollInfo)
+ gDelayedUpdateScrollInfoSet->add(this);
+ else
+ layer()->updateScrollInfoAfterLayout();
}
-
- if (gDelayUpdateScrollInfo)
- gDelayedUpdateScrollInfoSet->add(this);
- else
- layer()->updateScrollInfoAfterLayout();
}
void RenderBlock::layout()
@@ -1409,7 +1329,7 @@ void RenderBlock::computeInitialRegionRangeForBlock()
// effectively clamped to our region range.
LayoutUnit oldHeight = logicalHeight();
LayoutUnit oldLogicalTop = logicalTop();
- setLogicalHeight(numeric_limits<LayoutUnit>::max() / 2);
+ setLogicalHeight(MAX_LAYOUT_UNIT / 2);
computeLogicalHeight();
enclosingRenderFlowThread()->setRegionRangeForBox(this, offsetFromLogicalTopOfFirstPage());
setLogicalHeight(oldHeight);
@@ -1423,7 +1343,18 @@ void RenderBlock::computeRegionRangeForBlock()
enclosingRenderFlowThread()->setRegionRangeForBox(this, offsetFromLogicalTopOfFirstPage());
}
-void RenderBlock::layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeight, BlockLayoutPass layoutPass)
+bool RenderBlock::recomputeLogicalWidth()
+{
+ LayoutUnit oldWidth = logicalWidth();
+ LayoutUnit oldColumnWidth = desiredColumnWidth();
+
+ computeLogicalWidth();
+ calcColumnWidth();
+
+ return oldWidth != logicalWidth() || oldColumnWidth != desiredColumnWidth();
+}
+
+void RenderBlock::layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeight)
{
ASSERT(needsLayout());
@@ -1435,23 +1366,12 @@ void RenderBlock::layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeigh
LayoutRepainter repainter(*this, everHadLayout() && checkForRepaintDuringLayout());
- LayoutUnit oldWidth = logicalWidth();
- LayoutUnit oldColumnWidth = desiredColumnWidth();
-
- computeLogicalWidth();
- calcColumnWidth();
+ if (recomputeLogicalWidth())
+ relayoutChildren = true;
m_overflow.clear();
- if (oldWidth != logicalWidth() || oldColumnWidth != desiredColumnWidth())
- relayoutChildren = true;
-
- // If nothing changed about our floating positioned objects, let's go ahead and try to place them as
- // floats to avoid doing two passes.
- BlockLayoutPass floatsLayoutPass = layoutPass;
- if (floatsLayoutPass == NormalLayoutPass && !relayoutChildren && !positionedFloatsNeedRelayout())
- floatsLayoutPass = PositionedFloatLayoutPass;
- clearFloats(floatsLayoutPass);
+ clearFloats();
LayoutUnit previousHeight = logicalHeight();
setLogicalHeight(0);
@@ -1556,7 +1476,7 @@ void RenderBlock::layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeigh
for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
if (child->isBlockFlow() && !child->isFloatingOrPositioned()) {
RenderBlock* block = toRenderBlock(child);
- if (block->lowestFloatLogicalBottomIncludingPositionedFloats() + block->logicalTop() > newHeight)
+ if (block->lowestFloatLogicalBottom() + block->logicalTop() > newHeight)
addOverhangingFloats(block, false);
}
}
@@ -1566,7 +1486,7 @@ void RenderBlock::layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeigh
if (previousHeight != newHeight)
relayoutChildren = true;
- bool needAnotherLayoutPass = layoutPositionedObjects(relayoutChildren || isRoot());
+ layoutPositionedObjects(relayoutChildren || isRoot());
computeRegionRangeForBlock();
@@ -1611,7 +1531,7 @@ void RenderBlock::layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeigh
repaintRect.inflate(maximalOutlineSize(PaintPhaseOutline));
- if (hasOverflowClipWithLayer()) {
+ if (hasOverflowClip()) {
// Adjust repaint rect for scroll offset
repaintRect.move(-scrolledContentOffset());
@@ -1627,11 +1547,7 @@ void RenderBlock::layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeigh
}
}
- if (needAnotherLayoutPass && layoutPass == NormalLayoutPass) {
- setChildNeedsLayout(true, false);
- layoutBlock(false, pageLogicalHeight, PositionedFloatLayoutPass);
- } else
- setNeedsLayout(false);
+ setNeedsLayout(false);
}
void RenderBlock::addOverflowFromChildren()
@@ -1703,7 +1619,7 @@ void RenderBlock::addOverflowFromFloats()
FloatingObjectSetIterator end = floatingObjectSet.end();
for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
FloatingObject* r = *it;
- if (r->m_isDescendant && !r->m_renderer->isPositioned())
+ if (r->isDescendant())
addOverflowFromChild(r->m_renderer, IntSize(xPositionForFloatIncludingMargin(r), yPositionForFloatIncludingMargin(r)));
}
return;
@@ -1734,7 +1650,7 @@ void RenderBlock::addVisualOverflowFromTheme()
if (!style()->hasAppearance())
return;
- IntRect inflatedRect = borderBoxRect();
+ IntRect inflatedRect = pixelSnappedBorderBoxRect();
theme()->adjustRepaintRect(this, inflatedRect);
addVisualOverflow(inflatedRect);
}
@@ -1772,7 +1688,7 @@ void RenderBlock::adjustPositionedBlock(RenderBox* child, const MarginInfo& marg
if (childLayer->staticBlockPosition() != logicalTop) {
childLayer->setStaticBlockPosition(logicalTop);
if (hasStaticBlockPosition)
- child->setChildNeedsLayout(true, false);
+ child->setChildNeedsLayout(true, MarkOnlyThis);
}
}
@@ -1791,7 +1707,7 @@ void RenderBlock::adjustFloatingBlock(const MarginInfo& marginInfo)
// for by simply calling canCollapseWithMarginBefore. See
// http://www.hixie.ch/tests/adhoc/css/box/block/margin-collapse/046.html for
// an example of this scenario.
- LayoutUnit marginOffset = marginInfo.canCollapseWithMarginBefore() ? zeroLayoutUnit : marginInfo.margin();
+ LayoutUnit marginOffset = marginInfo.canCollapseWithMarginBefore() ? ZERO_LAYOUT_UNIT : marginInfo.margin();
setLogicalHeight(logicalHeight() + marginOffset);
positionNewFloats();
setLogicalHeight(logicalHeight() - marginOffset);
@@ -1833,14 +1749,22 @@ bool RenderBlock::handleRunInChild(RenderBox* child)
// block.
if (!child->isRunIn() || !child->childrenInline())
return false;
+
// FIXME: We don't handle non-block elements with run-in for now.
if (!child->isRenderBlock())
- return false;
+ return false;
+
// Run-in child shouldn't intrude into the sibling block if it is part of a
// continuation chain. In that case, treat it as a normal block.
if (child->isElementContinuation() || child->virtualContinuation())
return false;
+ // 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();
+ if (runInNode && runInNode->hasTagName(selectTag))
+ return false;
+
RenderBlock* blockRunIn = toRenderBlock(child);
RenderObject* curr = blockRunIn->nextSibling();
if (!curr || !curr->isRenderBlock() || !curr->childrenInline() || curr->isRunIn() || curr->isAnonymous() || curr->isFloatingOrPositioned())
@@ -1862,14 +1786,13 @@ bool RenderBlock::handleRunInChild(RenderBox* child)
children()->removeChildNode(this, blockRunIn);
// Create an inline.
- Node* runInNode = blockRunIn->node();
RenderInline* inlineRunIn = new (renderArena()) RenderInline(runInNode ? runInNode : document());
inlineRunIn->setStyle(blockRunIn->style());
// 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, false);
+ 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;
}
@@ -2080,7 +2003,7 @@ LayoutUnit RenderBlock::estimateLogicalTopPosition(RenderBox* child, const Margi
}
LayoutUnit RenderBlock::computeStartPositionDeltaForChildAvoidingFloats(const RenderBox* child, LayoutUnit childMarginStart,
- LayoutUnit childLogicalWidth, RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage)
+ RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage)
{
LayoutUnit startPosition = startOffsetForContent(region, offsetFromLogicalTopOfFirstPage);
@@ -2097,24 +2020,9 @@ LayoutUnit RenderBlock::computeStartPositionDeltaForChildAvoidingFloats(const Re
if (childMarginStart < 0)
startOff += childMarginStart;
newPosition = max(newPosition, startOff); // Let the float sit in the child's margin if it can fit.
- } else if (startOff != startPosition) {
- // The object is shifting to the "end" side of the block. The object might be centered, so we need to
- // recalculate our inline direction margins. Note that the containing block content
- // width computation will take into account the delta between |startOff| and |startPosition|
- // so that we can just pass the content width in directly to the |computeMarginsInContainingBlockInlineDirection|
- // function.
- LayoutUnit oldMarginStart = marginStartForChild(child);
- LayoutUnit oldMarginEnd = marginEndForChild(child);
- RenderBox* mutableChild = const_cast<RenderBox*>(child);
- mutableChild->computeInlineDirectionMargins(this,
- availableLogicalWidthForLine(blockOffset, false, region, offsetFromLogicalTopOfFirstPage), childLogicalWidth);
- newPosition = startOff + marginStartForChild(child);
- if (inRenderFlowThread()) {
- setMarginStartForChild(mutableChild, oldMarginStart);
- setMarginEndForChild(mutableChild, oldMarginEnd);
- }
- }
-
+ } else if (startOff != startPosition)
+ newPosition = startOff + childMarginStart;
+
return newPosition - oldPosition;
}
@@ -2132,7 +2040,7 @@ void RenderBlock::determineLogicalLeftPositionForChild(RenderBox* child)
// Some objects (e.g., tables, horizontal rules, overflow:auto blocks) avoid floats. They need
// to shift over as necessary to dodge any floats that might get in the way.
if (child->avoidsFloats() && containsFloats() && !inRenderFlowThread())
- newPosition += computeStartPositionDeltaForChildAvoidingFloats(child, marginStartForChild(child), logicalWidthForChild(child));
+ newPosition += computeStartPositionDeltaForChildAvoidingFloats(child, marginStartForChild(child));
setLogicalLeftForChild(child, style()->isLeftToRightDirection() ? newPosition : totalAvailableLogicalWidth - newPosition - logicalWidthForChild(child), ApplyLayoutDelta);
}
@@ -2211,7 +2119,7 @@ void RenderBlock::layoutBlockChildren(bool relayoutChildren, LayoutUnit& maxFloa
while (box != this) {
if (box->normalChildNeedsLayout())
break;
- box->setChildNeedsLayout(true, false);
+ box->setChildNeedsLayout(true, MarkOnlyThis);
box = box->containingBlock();
ASSERT(box);
if (!box)
@@ -2253,13 +2161,12 @@ void RenderBlock::layoutBlockChildren(bool relayoutChildren, LayoutUnit& maxFloa
// Make sure we layout children if they need it.
// FIXME: Technically percentage height objects only need a relayout if their percentage isn't going to be turned into
// an auto value. Add a method to determine this, so that we can avoid the relayout.
- RenderStyle* childStyle = child->style();
- if (relayoutChildren || ((childStyle->logicalHeight().isPercent() || childStyle->logicalMinHeight().isPercent() || childStyle->logicalMaxHeight().isPercent()) && !isRenderView()))
- child->setChildNeedsLayout(true, false);
+ if (relayoutChildren || (child->hasRelativeLogicalHeight() && !isRenderView()))
+ child->setChildNeedsLayout(true, MarkOnlyThis);
// If relayoutChildren is set and the child has percentage padding or an embedded content box, we also need to invalidate the childs pref widths.
if (relayoutChildren && child->needsPreferredWidthsRecalculation())
- child->setPreferredLogicalWidthsDirty(true, false);
+ child->setPreferredLogicalWidthsDirty(true, MarkOnlyThis);
// Handle the four types of special elements first. These include positioned content, floating content, compacts and
// run-ins. When we encounter these four types of objects, we don't actually lay them out as normal flow blocks.
@@ -2313,7 +2220,7 @@ void RenderBlock::layoutBlockChild(RenderBox* child, MarginInfo& marginInfo, Lay
else if (!child->avoidsFloats() || child->shrinkToAvoidFloats()) {
// If an element might be affected by the presence of floats, then always mark it for
// layout.
- LayoutUnit fb = max(previousFloatLogicalBottom, lowestFloatLogicalBottomIncludingPositionedFloats());
+ LayoutUnit fb = max(previousFloatLogicalBottom, lowestFloatLogicalBottom());
if (fb > logicalTopEstimate)
markDescendantsWithFloats = true;
}
@@ -2322,7 +2229,7 @@ void RenderBlock::layoutBlockChild(RenderBox* child, MarginInfo& marginInfo, Lay
if (markDescendantsWithFloats)
childRenderBlock->markAllDescendantsWithFloatsForLayout();
if (!child->isWritingModeRoot())
- previousFloatLogicalBottom = max(previousFloatLogicalBottom, oldLogicalTop + childRenderBlock->lowestFloatLogicalBottomIncludingPositionedFloats());
+ previousFloatLogicalBottom = max(previousFloatLogicalBottom, oldLogicalTop + childRenderBlock->lowestFloatLogicalBottom());
}
if (!child->needsLayout())
@@ -2357,7 +2264,7 @@ void RenderBlock::layoutBlockChild(RenderBox* child, MarginInfo& marginInfo, Lay
// When the child shifts to clear an item, its width can
// change (because it has more available line width).
// So go ahead and mark the item as dirty.
- child->setChildNeedsLayout(true, false);
+ child->setChildNeedsLayout(true, MarkOnlyThis);
}
if (childRenderBlock) {
@@ -2461,8 +2368,8 @@ bool RenderBlock::simplifiedLayout()
simplifiedNormalFlowLayout();
// Lay out our positioned objects if our positioned child bit is set.
- if (posChildNeedsLayout() && layoutPositionedObjects(false))
- return false; // If a positioned float is causing our normal flow to change, then we have to bail and do a full layout.
+ if (posChildNeedsLayout())
+ layoutPositionedObjects(false);
// Recompute our overflow information.
// FIXME: We could do better here by computing a temporary overflow object from layoutPositionedObjects and only
@@ -2482,41 +2389,14 @@ bool RenderBlock::simplifiedLayout()
return true;
}
-bool RenderBlock::positionedFloatsNeedRelayout()
-{
- if (!hasPositionedFloats())
- return false;
-
- RenderBox* positionedObject;
- Iterator end = m_positionedObjects->end();
- for (Iterator it = m_positionedObjects->begin(); it != end; ++it) {
- positionedObject = *it;
- if (!positionedObject->isFloating())
- continue;
-
- if (positionedObject->needsLayout())
- return true;
-
- if (positionedObject->style()->hasStaticBlockPosition(isHorizontalWritingMode()) && positionedObject->parent() != this && positionedObject->parent()->isBlockFlow())
- return true;
-
- if (view()->layoutState()->pageLogicalHeightChanged() || (view()->layoutState()->pageLogicalHeight() && view()->layoutState()->pageLogicalOffset(logicalTop()) != pageLogicalOffset()))
- return true;
- }
-
- return false;
-}
-
-bool RenderBlock::layoutPositionedObjects(bool relayoutChildren)
+void RenderBlock::layoutPositionedObjects(bool relayoutChildren)
{
if (!m_positionedObjects)
- return false;
+ return;
if (hasColumns())
view()->layoutState()->clearPaginationInformation(); // Positioned objects are not part of the column flow, so they don't paginate with the columns.
- bool didFloatingBoxRelayout = false;
-
RenderBox* r;
Iterator end = m_positionedObjects->end();
for (Iterator it = m_positionedObjects->begin(); it != end; ++it) {
@@ -2526,20 +2406,15 @@ bool RenderBlock::layoutPositionedObjects(bool relayoutChildren)
// objects that are positioned implicitly like this. Such objects are rare, and so in typical DHTML menu usage (where everything is
// positioned explicitly) this should not incur a performance penalty.
if (relayoutChildren || (r->style()->hasStaticBlockPosition(isHorizontalWritingMode()) && r->parent() != this))
- r->setChildNeedsLayout(true, false);
+ r->setChildNeedsLayout(true, MarkOnlyThis);
// If relayoutChildren is set and the child has percentage padding or an embedded content box, we also need to invalidate the childs pref widths.
if (relayoutChildren && r->needsPreferredWidthsRecalculation())
- r->setPreferredLogicalWidthsDirty(true, false);
+ r->setPreferredLogicalWidthsDirty(true, MarkOnlyThis);
if (!r->needsLayout())
r->markForPaginationRelayoutIfNeeded();
- // FIXME: Technically we could check the old placement and the new placement of the box and only invalidate if
- // the margin box of the object actually changed.
- if (r->needsLayout() && r->isFloating())
- didFloatingBoxRelayout = true;
-
// We don't have to do a full layout. We just have to update our position. Try that first. If we have shrink-to-fit width
// and we hit the available width constraint, the layoutIfNeeded() will catch it and do a full layout.
if (r->needsPositionedMovementLayoutOnly() && r->tryLayoutDoingPositionedMovementOnly())
@@ -2556,20 +2431,26 @@ bool RenderBlock::layoutPositionedObjects(bool relayoutChildren)
r->computeLogicalWidth();
oldLogicalTop = logicalTopForChild(r);
}
-
- r->layoutIfNeeded();
+ r->layoutIfNeeded();
+
+ // Adjust the static position of a center-aligned inline positioned object with a block child now that the child's width has been computed.
+ if (!r->parent()->isRenderView() && r->parent()->isRenderBlock() && r->firstChild() && r->style()->position() == AbsolutePosition
+ && r->style()->isOriginalDisplayInlineType() && (r->style()->textAlign() == CENTER || r->style()->textAlign() == WEBKIT_CENTER)) {
+ RenderBlock* block = toRenderBlock(r->parent());
+ LayoutUnit blockHeight = block->logicalHeight();
+ block->setStaticInlinePositionForChild(r, blockHeight, block->startAlignedOffsetForLine(r, blockHeight, false));
+ }
+
// Lay out again if our estimate was wrong.
if (needsBlockDirectionLocationSetBeforeLayout && logicalTopForChild(r) != oldLogicalTop) {
- r->setChildNeedsLayout(true, false);
+ r->setChildNeedsLayout(true, MarkOnlyThis);
r->layoutIfNeeded();
}
}
if (hasColumns())
view()->layoutState()->m_columnInfo = columnInfo(); // FIXME: Kind of gross. We just put this back into the layout state so that pop() will work.
-
- return didFloatingBoxRelayout;
}
void RenderBlock::markPositionedObjectsForLayout()
@@ -2591,7 +2472,7 @@ void RenderBlock::markForPaginationRelayoutIfNeeded()
return;
if (view()->layoutState()->pageLogicalHeightChanged() || (view()->layoutState()->pageLogicalHeight() && view()->layoutState()->pageLogicalOffset(logicalTop()) != pageLogicalOffset()))
- setChildNeedsLayout(true, false);
+ setChildNeedsLayout(true, MarkOnlyThis);
}
void RenderBlock::repaintOverhangingFloats(bool paintAllDescendants)
@@ -2611,7 +2492,7 @@ void RenderBlock::repaintOverhangingFloats(bool paintAllDescendants)
// Only repaint the object if it is overhanging, is not in its own layer, and
// is our responsibility to paint (m_shouldPaint is set). When paintAllDescendants is true, the latter
// condition is replaced with being a descendant of us.
- if (logicalBottomForFloat(r) > logicalHeight() && ((paintAllDescendants && r->m_renderer->isDescendantOf(this)) || r->m_shouldPaint) && !r->m_renderer->hasSelfPaintingLayer()) {
+ if (logicalBottomForFloat(r) > logicalHeight() && ((paintAllDescendants && r->m_renderer->isDescendantOf(this)) || r->shouldPaint()) && !r->m_renderer->hasSelfPaintingLayer()) {
r->m_renderer->repaint();
r->m_renderer->repaintOverhangingFloats();
}
@@ -2644,7 +2525,7 @@ void RenderBlock::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
// Our scrollbar widgets paint exactly when we tell them to, so that they work properly with
// z-index. We paint after we painted the background/border, so that the scrollbars will
// sit above the background/border.
- if (hasOverflowClipWithLayer() && style()->visibility() == VISIBLE && (phase == PaintPhaseBlockBackground || phase == PaintPhaseChildBlockBackground) && paintInfo.shouldPaintWithinRoot(this))
+ if (hasOverflowClip() && style()->visibility() == VISIBLE && (phase == PaintPhaseBlockBackground || phase == PaintPhaseChildBlockBackground) && paintInfo.shouldPaintWithinRoot(this))
layer()->paintOverflowControls(paintInfo.context, roundedIntPoint(adjustedPaintOffset), paintInfo.rect);
}
@@ -2668,9 +2549,9 @@ void RenderBlock::paintColumnRules(PaintInfo& paintInfo, const LayoutPoint& pain
bool antialias = shouldAntialiasLines(paintInfo.context);
if (colInfo->progressionAxis() == ColumnInfo::InlineAxis) {
- LayoutUnit currLogicalLeftOffset = style()->isLeftToRightDirection() ? zeroLayoutUnit : contentLogicalWidth();
+ LayoutUnit currLogicalLeftOffset = style()->isLeftToRightDirection() ? ZERO_LAYOUT_UNIT : contentLogicalWidth();
LayoutUnit ruleAdd = logicalLeftOffsetForContent();
- LayoutUnit ruleLogicalLeft = style()->isLeftToRightDirection() ? zeroLayoutUnit : contentLogicalWidth();
+ LayoutUnit ruleLogicalLeft = style()->isLeftToRightDirection() ? ZERO_LAYOUT_UNIT : contentLogicalWidth();
LayoutUnit inlineDirectionSize = colInfo->desiredColumnWidth();
BoxSide boxSide = isHorizontalWritingMode()
? style()->isLeftToRightDirection() ? BSLeft : BSRight
@@ -2780,13 +2661,10 @@ void RenderBlock::paintContents(PaintInfo& paintInfo, const LayoutPoint& paintOf
if (document()->didLayoutWithPendingStylesheets() && !isRenderView())
return;
- // We don't want to hand off painting in the line box tree with the accumulated error of the render tree, as this will cause
- // us to mess up painting aligned things (such as underlines in text) with both the render tree and line box tree's error.
- LayoutPoint roundedPaintOffset = roundedIntPoint(paintOffset);
if (childrenInline())
- m_lineBoxes.paint(this, paintInfo, roundedPaintOffset);
+ m_lineBoxes.paint(this, paintInfo, paintOffset);
else
- paintChildren(paintInfo, roundedPaintOffset);
+ paintChildren(paintInfo, paintOffset);
}
void RenderBlock::paintChildren(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
@@ -2918,7 +2796,10 @@ void RenderBlock::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffs
// 6. paint continuation outlines.
if ((paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseChildOutlines)) {
RenderInline* inlineCont = inlineElementContinuation();
- if (inlineCont && inlineCont->hasOutline() && inlineCont->style()->visibility() == VISIBLE) {
+ // FIXME: For now, do not add continuations for outline painting by our containing block if we are a relative positioned
+ // anonymous block (i.e. have our own layer). This is because a block depends on renderers in its continuation table being
+ // in the same layer.
+ if (inlineCont && inlineCont->hasOutline() && inlineCont->style()->visibility() == VISIBLE && !hasLayer()) {
RenderInline* inlineRenderer = toRenderInline(inlineCont->node()->renderer());
RenderBlock* cb = containingBlock();
@@ -2970,7 +2851,7 @@ void RenderBlock::paintFloats(PaintInfo& paintInfo, const LayoutPoint& paintOffs
for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
FloatingObject* r = *it;
// Only paint the object if our m_shouldPaint flag is set.
- if (r->m_shouldPaint && !r->m_renderer->hasSelfPaintingLayer()) {
+ if (r->shouldPaint() && !r->m_renderer->hasSelfPaintingLayer()) {
PaintInfo currentPaintInfo(paintInfo);
currentPaintInfo.phase = preservePhase ? paintInfo.phase : PaintPhaseBlockBackground;
LayoutPoint childPoint = flipFloatForWritingModeForChild(r, LayoutPoint(paintOffset.x() + xPositionForFloatIncludingMargin(r) - r->m_renderer->x(), paintOffset.y() + yPositionForFloatIncludingMargin(r) - r->m_renderer->y()));
@@ -3282,8 +3163,8 @@ GapRects RenderBlock::inlineSelectionGaps(RenderBlock* rootBlock, const LayoutPo
// Now paint the gaps for the lines.
for (; curr && curr->hasSelectedChildren(); curr = curr->nextRootBox()) {
- LayoutUnit selTop = curr->selectionTop();
- LayoutUnit selHeight = curr->selectionHeight();
+ LayoutUnit selTop = curr->selectionTopAdjustedForPrecedingBlock();
+ LayoutUnit selHeight = curr->selectionHeightAdjustedForPrecedingBlock();
if (!containsStart && !lastSelectedLine &&
selectionState() != SelectionStart && selectionState() != SelectionBoth)
@@ -3475,6 +3356,38 @@ LayoutUnit RenderBlock::logicalRightSelectionOffset(RenderBlock* rootBlock, Layo
return logicalRight;
}
+RenderBlock* RenderBlock::blockBeforeWithinSelectionRoot(LayoutSize& offset) const
+{
+ if (isSelectionRoot())
+ return 0;
+
+ const RenderBox* object = this;
+ RenderObject* sibling;
+ do {
+ sibling = object->previousSibling();
+ while (sibling && (!sibling->isRenderBlock() || toRenderBlock(sibling)->isSelectionRoot()))
+ sibling = sibling->previousSibling();
+
+ offset -= LayoutSize(object->logicalLeft(), object->logicalTop());
+ object = object->parentBox();
+ } while (!sibling && object && object->isRenderBlock() && !toRenderBlock(object)->isSelectionRoot());
+
+ if (!sibling)
+ return 0;
+
+ RenderBlock* beforeBlock = toRenderBlock(sibling);
+
+ offset += LayoutSize(beforeBlock->logicalLeft(), beforeBlock->logicalTop());
+
+ RenderObject* child = beforeBlock->lastChild();
+ while (child && child->isRenderBlock()) {
+ beforeBlock = toRenderBlock(child);
+ offset += LayoutSize(beforeBlock->logicalLeft(), beforeBlock->logicalTop());
+ child = beforeBlock->lastChild();
+ }
+ return beforeBlock;
+}
+
void RenderBlock::insertPositionedObject(RenderBox* o)
{
ASSERT(!isAnonymousBlock());
@@ -3487,12 +3400,18 @@ void RenderBlock::insertPositionedObject(RenderBox* o)
m_positionedObjects = adoptPtr(new PositionedObjectsListHashSet);
m_positionedObjects->add(o);
+
+ if (o->style()->position() == FixedPosition && view())
+ view()->insertFixedPositionedObject(o);
}
void RenderBlock::removePositionedObject(RenderBox* o)
{
if (m_positionedObjects)
m_positionedObjects->remove(o);
+
+ if (view())
+ view()->removeFixedPositionedObject(o);
}
void RenderBlock::removePositionedObjects(RenderBlock* o)
@@ -3510,7 +3429,7 @@ void RenderBlock::removePositionedObjects(RenderBlock* o)
r = *it;
if (!o || r->isDescendantOf(o)) {
if (o)
- r->setChildNeedsLayout(true, false);
+ r->setChildNeedsLayout(true, MarkOnlyThis);
// It is parent blocks job to add positioned child to positioned objects list of its containing block
// Parent layout needs to be invalidated to ensure this happens.
@@ -3549,23 +3468,21 @@ RenderBlock::FloatingObject* RenderBlock::insertFloatingObject(RenderBox* o)
// Our location is irrelevant if we're unsplittable or no pagination is in effect.
// Just go ahead and lay out the float.
- if (!o->isPositioned()) {
- bool isChildRenderBlock = o->isRenderBlock();
- if (isChildRenderBlock && !o->needsLayout() && view()->layoutState()->pageLogicalHeightChanged())
- o->setChildNeedsLayout(true, false);
+ bool isChildRenderBlock = o->isRenderBlock();
+ if (isChildRenderBlock && !o->needsLayout() && view()->layoutState()->pageLogicalHeightChanged())
+ o->setChildNeedsLayout(true, MarkOnlyThis);
- bool needsBlockDirectionLocationSetBeforeLayout = isChildRenderBlock && view()->layoutState()->needsBlockDirectionLocationSetBeforeLayout();
- if (!needsBlockDirectionLocationSetBeforeLayout || isWritingModeRoot()) // We are unsplittable if we're a block flow root.
- o->layoutIfNeeded();
- else {
- o->computeLogicalWidth();
- o->computeBlockDirectionMargins(this);
- }
+ bool needsBlockDirectionLocationSetBeforeLayout = isChildRenderBlock && view()->layoutState()->needsBlockDirectionLocationSetBeforeLayout();
+ if (!needsBlockDirectionLocationSetBeforeLayout || isWritingModeRoot()) // We are unsplittable if we're a block flow root.
+ o->layoutIfNeeded();
+ else {
+ o->computeLogicalWidth();
+ o->computeBlockDirectionMargins(this);
}
setLogicalWidthForFloat(newObj, logicalWidthForChild(o) + marginStartForChild(o) + marginEndForChild(o));
- newObj->m_shouldPaint = !o->hasSelfPaintingLayer(); // If a layer exists, the float will paint itself. Otherwise someone else will.
- newObj->m_isDescendant = true;
+ newObj->setShouldPaint(!o->hasSelfPaintingLayer()); // If a layer exists, the float will paint itself. Otherwise someone else will.
+ newObj->setIsDescendant(true);
newObj->m_renderer = o;
m_floatingObjects->add(newObj);
@@ -3585,8 +3502,8 @@ void RenderBlock::removeFloatingObject(RenderBox* o)
LayoutUnit logicalBottom = logicalBottomForFloat(r);
// Fix for https://bugs.webkit.org/show_bug.cgi?id=54995.
- if (logicalBottom < 0 || logicalBottom < logicalTop || logicalTop == numeric_limits<LayoutUnit>::max())
- logicalBottom = numeric_limits<LayoutUnit>::max();
+ if (logicalBottom < 0 || logicalBottom < logicalTop || logicalTop == MAX_LAYOUT_UNIT)
+ logicalBottom = MAX_LAYOUT_UNIT;
else {
// Special-case zero- and less-than-zero-height floats: those don't touch
// the line that they're on, but it still needs to be dirtied. This is
@@ -3714,9 +3631,8 @@ bool RenderBlock::positionNewFloats()
for (; it != end; ++it) {
FloatingObject* floatingObject = *it;
// The containing block is responsible for positioning floats, so if we have floats in our
- // list that come from somewhere else, do not attempt to position them. Also don't attempt to handle
- // positioned floats, since the positioning layout code handles those.
- if (floatingObject->renderer()->containingBlock() != this || floatingObject->renderer()->isPositioned())
+ // list that come from somewhere else, do not attempt to position them.
+ if (floatingObject->renderer()->containingBlock() != this)
continue;
RenderBox* childBox = floatingObject->renderer();
@@ -3765,7 +3681,7 @@ bool RenderBlock::positionNewFloats()
setLogicalTopForChild(childBox, floatLogicalLocation.y() + marginBeforeForChild(childBox));
if (childBlock)
- childBlock->setChildNeedsLayout(true, false);
+ childBlock->setChildNeedsLayout(true, MarkOnlyThis);
childBox->layoutIfNeeded();
}
}
@@ -3786,7 +3702,7 @@ void RenderBlock::newLine(EClear clear)
{
positionNewFloats();
// set y position
- int newY = 0;
+ LayoutUnit newY = 0;
switch (clear)
{
case CLEFT:
@@ -3816,7 +3732,7 @@ void RenderBlock::addPercentHeightDescendant(RenderBox* descendant)
descendantSet = new HashSet<RenderBox*>;
gPercentHeightDescendantsMap->set(this, descendantSet);
}
- bool added = descendantSet->add(descendant).second;
+ bool added = descendantSet->add(descendant).isNewEntry;
if (!added) {
ASSERT(gPercentHeightContainerMap->get(descendant));
ASSERT(gPercentHeightContainerMap->get(descendant)->contains(this));
@@ -3902,9 +3818,12 @@ inline void RenderBlock::FloatIntervalSearchAdapter<FloatTypeValue>::collectIfNe
LayoutUnit RenderBlock::textIndentOffset() const
{
LayoutUnit cw = 0;
+ RenderView* renderView = 0;
if (style()->textIndent().isPercent())
cw = containingBlock()->availableLogicalWidth();
- return style()->textIndent().calcMinValue(cw);
+ else if (style()->textIndent().isViewportPercentage())
+ renderView = view();
+ return minimumValueForLength(style()->textIndent(), cw, renderView);
}
LayoutUnit RenderBlock::logicalLeftOffsetForContent(RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage) const
@@ -4027,7 +3946,7 @@ LayoutUnit RenderBlock::nextFloatLogicalBottomBelow(LayoutUnit logicalHeight) co
if (!m_floatingObjects)
return logicalHeight;
- LayoutUnit bottom = numeric_limits<LayoutUnit>::max();
+ LayoutUnit bottom = MAX_LAYOUT_UNIT;
const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
FloatingObjectSetIterator end = floatingObjectSet.end();
for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
@@ -4037,7 +3956,7 @@ LayoutUnit RenderBlock::nextFloatLogicalBottomBelow(LayoutUnit logicalHeight) co
bottom = min(floatBottom, bottom);
}
- return bottom == numeric_limits<LayoutUnit>::max() ? zeroLayoutUnit : bottom;
+ return bottom == MAX_LAYOUT_UNIT ? ZERO_LAYOUT_UNIT : bottom;
}
LayoutUnit RenderBlock::lowestFloatLogicalBottom(FloatingObject::Type floatType) const
@@ -4062,7 +3981,7 @@ void RenderBlock::markLinesDirtyInBlockRange(LayoutUnit logicalTop, LayoutUnit l
RootInlineBox* lowestDirtyLine = lastRootBox();
RootInlineBox* afterLowest = lowestDirtyLine;
- while (lowestDirtyLine && lowestDirtyLine->lineBottomWithLeading() >= logicalBottom && logicalBottom < numeric_limits<LayoutUnit>::max()) {
+ while (lowestDirtyLine && lowestDirtyLine->lineBottomWithLeading() >= logicalBottom && logicalBottom < MAX_LAYOUT_UNIT) {
afterLowest = lowestDirtyLine;
lowestDirtyLine = lowestDirtyLine->prevRootBox();
}
@@ -4073,40 +3992,21 @@ void RenderBlock::markLinesDirtyInBlockRange(LayoutUnit logicalTop, LayoutUnit l
}
}
-void RenderBlock::addPositionedFloats()
-{
- if (!m_positionedObjects)
- return;
-
- Iterator end = m_positionedObjects->end();
- for (Iterator it = m_positionedObjects->begin(); it != end; ++it) {
- RenderBox* positionedObject = *it;
- if (!positionedObject->isFloating())
- continue;
-
- ASSERT(!positionedObject->needsLayout());
-
- // If we're a positioned float, then we need to insert ourselves as a floating object also. We only do
- // this after the positioned object has received a layout, since otherwise the dimensions and placement
- // won't be correct.
- FloatingObject* floatingObject = insertFloatingObject(positionedObject);
- setLogicalLeftForFloat(floatingObject, logicalLeftForChild(positionedObject) - marginLogicalLeftForChild(positionedObject));
- setLogicalTopForFloat(floatingObject, logicalTopForChild(positionedObject) - marginBeforeForChild(positionedObject));
- setLogicalHeightForFloat(floatingObject, logicalHeightForChild(positionedObject) + marginBeforeForChild(positionedObject) + marginAfterForChild(positionedObject));
-
- m_floatingObjects->addPlacedObject(floatingObject);
-
- m_hasPositionedFloats = true;
- }
-}
-
-void RenderBlock::clearFloats(BlockLayoutPass layoutPass)
+void RenderBlock::clearFloats()
{
if (m_floatingObjects)
m_floatingObjects->setHorizontalWritingMode(isHorizontalWritingMode());
- // Clear our positioned floats boolean.
- m_hasPositionedFloats = false;
+ HashSet<RenderBox*> oldIntrudingFloatSet;
+ if (!childrenInline() && m_floatingObjects) {
+ const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
+ FloatingObjectSetIterator end = floatingObjectSet.end();
+ for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
+ FloatingObject* floatingObject = *it;
+ if (!floatingObject->isDescendant())
+ oldIntrudingFloatSet.add(floatingObject->m_renderer);
+ }
+ }
// Inline blocks are covered by the isReplaced() check in the avoidFloats method.
if (avoidsFloats() || isRoot() || isRenderView() || isFloatingOrPositioned() || isTableCell()) {
@@ -4114,8 +4014,8 @@ void RenderBlock::clearFloats(BlockLayoutPass layoutPass)
deleteAllValues(m_floatingObjects->set());
m_floatingObjects->clear();
}
- if (layoutPass == PositionedFloatLayoutPass)
- addPositionedFloats();
+ if (!oldIntrudingFloatSet.isEmpty())
+ markAllDescendantsWithFloatsForLayout();
return;
}
@@ -4135,9 +4035,6 @@ void RenderBlock::clearFloats(BlockLayoutPass layoutPass)
m_floatingObjects->clear();
}
- if (layoutPass == PositionedFloatLayoutPass)
- addPositionedFloats();
-
// We should not process floats if the parent node is not a RenderBlock. Otherwise, we will add
// floats in an invalid context. This will cause a crash arising from a bad cast on the parent.
// See <rdar://problem/8049753>, where float property is applied on a text node in a SVG.
@@ -4148,7 +4045,7 @@ void RenderBlock::clearFloats(BlockLayoutPass layoutPass)
// out of flow (like floating/positioned elements), and we also skip over any objects that may have shifted
// to avoid floats.
RenderBlock* parentBlock = toRenderBlock(parent());
- bool parentHasFloats = parentBlock->hasPositionedFloats();
+ bool parentHasFloats = false;
RenderObject* prev = previousSibling();
while (prev && (prev->isFloatingOrPositioned() || !prev->isBox() || !prev->isRenderBlock() || toRenderBlock(prev)->avoidsFloats())) {
if (prev->isFloating())
@@ -4164,19 +4061,19 @@ void RenderBlock::clearFloats(BlockLayoutPass layoutPass)
LayoutUnit logicalLeftOffset = 0;
if (prev)
logicalTopOffset -= toRenderBox(prev)->logicalTop();
- else if (!parentHasFloats) {
+ else {
prev = parentBlock;
logicalLeftOffset += parentBlock->logicalLeftOffsetForContent();
}
// Add overhanging floats from the previous RenderBlock, but only if it has a float that intrudes into our space.
RenderBlock* block = toRenderBlock(prev);
- if (block && block->m_floatingObjects && block->lowestFloatLogicalBottomIncludingPositionedFloats() > logicalTopOffset)
+ if (block->m_floatingObjects && block->lowestFloatLogicalBottom() > logicalTopOffset)
addIntrudingFloats(block, logicalLeftOffset, logicalTopOffset);
if (childrenInline()) {
- LayoutUnit changeLogicalTop = numeric_limits<LayoutUnit>::max();
- LayoutUnit changeLogicalBottom = numeric_limits<LayoutUnit>::min();
+ LayoutUnit changeLogicalTop = MAX_LAYOUT_UNIT;
+ LayoutUnit changeLogicalBottom = MIN_LAYOUT_UNIT;
if (m_floatingObjects) {
const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
FloatingObjectSetIterator end = floatingObjectSet.end();
@@ -4218,7 +4115,7 @@ void RenderBlock::clearFloats(BlockLayoutPass layoutPass)
RendererToFloatInfoMap::iterator end = floatMap.end();
for (RendererToFloatInfoMap::iterator it = floatMap.begin(); it != end; ++it) {
FloatingObject* floatingObject = (*it).second;
- if (!floatingObject->m_isDescendant) {
+ if (!floatingObject->isDescendant()) {
changeLogicalTop = 0;
changeLogicalBottom = max(changeLogicalBottom, logicalBottomForFloat(floatingObject));
}
@@ -4226,6 +4123,19 @@ void RenderBlock::clearFloats(BlockLayoutPass layoutPass)
deleteAllValues(floatMap);
markLinesDirtyInBlockRange(changeLogicalTop, changeLogicalBottom);
+ } else if (!oldIntrudingFloatSet.isEmpty()) {
+ // If there are previously intruding floats that no longer intrude, then children with floats
+ // should also get layout because they might need their floating object lists cleared.
+ if (m_floatingObjects->set().size() < oldIntrudingFloatSet.size())
+ markAllDescendantsWithFloatsForLayout();
+ else {
+ const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
+ FloatingObjectSetIterator end = floatingObjectSet.end();
+ for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end && !oldIntrudingFloatSet.isEmpty(); ++it)
+ oldIntrudingFloatSet.remove((*it)->m_renderer);
+ if (!oldIntrudingFloatSet.isEmpty())
+ markAllDescendantsWithFloatsForLayout();
+ }
}
}
@@ -4244,7 +4154,7 @@ LayoutUnit RenderBlock::addOverhangingFloats(RenderBlock* child, bool makeChildP
FloatingObjectSetIterator childEnd = child->m_floatingObjects->set().end();
for (FloatingObjectSetIterator childIt = child->m_floatingObjects->set().begin(); childIt != childEnd; ++childIt) {
FloatingObject* r = *childIt;
- LayoutUnit logicalBottomForFloat = min(this->logicalBottomForFloat(r), numeric_limits<LayoutUnit>::max() - childLogicalTop);
+ LayoutUnit logicalBottomForFloat = min(this->logicalBottomForFloat(r), MAX_LAYOUT_UNIT - childLogicalTop);
LayoutUnit logicalBottom = childLogicalTop + logicalBottomForFloat;
lowestFloatLogicalBottom = max(lowestFloatLogicalBottom, logicalBottom);
@@ -4261,11 +4171,11 @@ LayoutUnit RenderBlock::addOverhangingFloats(RenderBlock* child, bool makeChildP
// far out as we can, to the outermost block that overlaps the float, stopping only
// if we hit a self-painting layer boundary.
if (r->m_renderer->enclosingFloatPaintingLayer() == enclosingFloatPaintingLayer())
- r->m_shouldPaint = false;
+ r->setShouldPaint(false);
else
- floatingObj->m_shouldPaint = false;
-
- floatingObj->m_isDescendant = true;
+ floatingObj->setShouldPaint(false);
+
+ floatingObj->setIsDescendant(true);
// We create the floating object list lazily.
if (!m_floatingObjects)
@@ -4274,19 +4184,19 @@ LayoutUnit RenderBlock::addOverhangingFloats(RenderBlock* child, bool makeChildP
m_floatingObjects->add(floatingObj);
}
} else {
- if (makeChildPaintOtherFloats && !r->m_shouldPaint && !r->m_renderer->hasSelfPaintingLayer() &&
- r->m_renderer->isDescendantOf(child) && r->m_renderer->enclosingFloatPaintingLayer() == child->enclosingFloatPaintingLayer()) {
+ if (makeChildPaintOtherFloats && !r->shouldPaint() && !r->m_renderer->hasSelfPaintingLayer()
+ && r->m_renderer->isDescendantOf(child) && r->m_renderer->enclosingFloatPaintingLayer() == child->enclosingFloatPaintingLayer()) {
// The float is not overhanging from this block, so if it is a descendant of the child, the child should
// paint it (the other case is that it is intruding into the child), unless it has its own layer or enclosing
// layer.
// If makeChildPaintOtherFloats is false, it means that the child must already know about all the floats
// it should paint.
- r->m_shouldPaint = true;
+ r->setShouldPaint(true);
}
// Since the float doesn't overhang, it didn't get put into our list. We need to go ahead and add its overflow in to the
// child now.
- if (r->m_isDescendant)
+ if (r->isDescendant())
child->addOverflowFromChild(r->m_renderer, LayoutSize(xPositionForFloatIncludingMargin(r), yPositionForFloatIncludingMargin(r)));
}
}
@@ -4337,7 +4247,7 @@ void RenderBlock::addIntrudingFloats(RenderBlock* prev, LayoutUnit logicalLeftOf
floatingObj->setY(floatingObj->y() + prev->marginTop());
}
- floatingObj->m_shouldPaint = false; // We are not in the direct inheritance chain for this float. We will never paint it.
+ floatingObj->setShouldPaint(false); // We are not in the direct inheritance chain for this float. We will never paint it.
floatingObj->m_renderer = r->m_renderer;
// We create the floating object list lazily.
@@ -4365,7 +4275,8 @@ void RenderBlock::markAllDescendantsWithFloatsForLayout(RenderBox* floatToRemove
if (!everHadLayout())
return;
- setChildNeedsLayout(true, !inLayout);
+ MarkingBehavior markParents = inLayout ? MarkOnlyThis : MarkContainingBlockChain;
+ setChildNeedsLayout(true, markParents);
if (floatToRemove)
removeFloatingObject(floatToRemove);
@@ -4386,26 +4297,21 @@ void RenderBlock::markSiblingsWithFloatsForLayout(RenderBox* floatToRemove)
{
if (!m_floatingObjects)
return;
+
const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
FloatingObjectSetIterator end = floatingObjectSet.end();
- for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
- if (logicalBottomForFloat(*it) > logicalHeight()) {
+
+ for (RenderObject* next = nextSibling(); next; next = next->nextSibling()) {
+ if (!next->isRenderBlock() || next->isFloatingOrPositioned() || toRenderBlock(next)->avoidsFloats())
+ continue;
+
+ RenderBlock* nextBlock = toRenderBlock(next);
+ for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
RenderBox* floatingBox = (*it)->renderer();
if (floatToRemove && floatingBox != floatToRemove)
continue;
-
- RenderObject* next = nextSibling();
- while (next) {
- if (next->isRenderBlock() && !next->isFloatingOrPositioned() && !toRenderBlock(next)->avoidsFloats()) {
- RenderBlock* nextBlock = toRenderBlock(next);
- if (nextBlock->containsFloat(floatingBox))
- nextBlock->markAllDescendantsWithFloatsForLayout(floatingBox);
- else
- break;
- }
-
- next = next->nextSibling();
- }
+ if (nextBlock->containsFloat(floatingBox))
+ nextBlock->markAllDescendantsWithFloatsForLayout(floatingBox);
}
}
}
@@ -4434,7 +4340,7 @@ LayoutUnit RenderBlock::getClearDelta(RenderBox* child, LayoutUnit logicalTop)
}
// We also clear floats if we are too big to sit on the same line as a float (and wish to avoid floats by default).
- LayoutUnit result = clearSet ? max<LayoutUnit>(0, logicalBottom - logicalTop) : zeroLayoutUnit;
+ LayoutUnit result = clearSet ? max<LayoutUnit>(0, logicalBottom - logicalTop) : ZERO_LAYOUT_UNIT;
if (!result && child->avoidsFloats()) {
LayoutUnit newLogicalTop = logicalTop;
while (true) {
@@ -4474,10 +4380,10 @@ LayoutUnit RenderBlock::getClearDelta(RenderBox* child, LayoutUnit logicalTop)
bool RenderBlock::isPointInOverflowControl(HitTestResult& result, const LayoutPoint& pointInContainer, const LayoutPoint& accumulatedOffset)
{
- if (!scrollsOverflow() || !hasLayer())
+ if (!scrollsOverflow())
return false;
- return layer()->hitTestOverflowControls(result, pointInContainer - toLayoutSize(accumulatedOffset));
+ return layer()->hitTestOverflowControls(result, roundedIntPoint(pointInContainer - toLayoutSize(accumulatedOffset)));
}
bool RenderBlock::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const LayoutPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
@@ -4554,7 +4460,7 @@ bool RenderBlock::hitTestFloats(const HitTestRequest& request, HitTestResult& re
for (FloatingObjectSetIterator it = floatingObjectSet.end(); it != begin;) {
--it;
FloatingObject* floatingObject = *it;
- if (floatingObject->m_shouldPaint && !floatingObject->m_renderer->hasSelfPaintingLayer()) {
+ if (floatingObject->shouldPaint() && !floatingObject->m_renderer->hasSelfPaintingLayer()) {
LayoutUnit xOffset = xPositionForFloatIncludingMargin(floatingObject) - floatingObject->m_renderer->x();
LayoutUnit yOffset = yPositionForFloatIncludingMargin(floatingObject) - floatingObject->m_renderer->y();
LayoutPoint childPoint = flipFloatForWritingModeForChild(floatingObject, adjustedLocation + LayoutSize(xOffset, yOffset));
@@ -4884,7 +4790,10 @@ int RenderBlock::columnGap() const
}
void RenderBlock::calcColumnWidth()
-{
+{
+ if (document()->regionBasedColumnsEnabled())
+ return;
+
// Calculate our column width and column count.
// FIXME: Can overflow on fast/block/float/float-not-removed-from-next-sibling4.html, see https://bugs.webkit.org/show_bug.cgi?id=68744
unsigned desiredColumnCount = 1;
@@ -5018,7 +4927,7 @@ bool RenderBlock::layoutColumns(bool hasSpecifiedPageLogicalHeight, LayoutUnit p
view()->layoutState()->pageLogicalOffset(borderBefore() + paddingBefore() + contentLogicalHeight()) - colInfo->forcedBreakOffset());
columnHeight = max(colInfo->minimumColumnHeight(), distanceBetweenBreaks);
}
- } else if (contentLogicalHeight() > pageLogicalHeight * desiredColumnCount) {
+ } else if (contentLogicalHeight() > boundedMultiply(pageLogicalHeight, desiredColumnCount)) {
// Now that we know the intrinsic height of the columns, we have to rebalance them.
columnHeight = max<LayoutUnit>(colInfo->minimumColumnHeight(), ceilf((float)contentLogicalHeight() / desiredColumnCount));
}
@@ -5211,11 +5120,11 @@ void RenderBlock::adjustForColumns(LayoutSize& offset, const LayoutPoint& point)
ColumnInfo* colInfo = columnInfo();
LayoutUnit logicalLeft = logicalLeftOffsetForContent();
- size_t colCount = columnCount(colInfo);
+ unsigned colCount = columnCount(colInfo);
LayoutUnit colLogicalWidth = colInfo->desiredColumnWidth();
LayoutUnit colLogicalHeight = colInfo->columnHeight();
- for (size_t i = 0; i < colCount; ++i) {
+ for (unsigned i = 0; i < colCount; ++i) {
// Compute the edges for a given column in the block progression direction.
LayoutRect sliceRect = LayoutRect(logicalLeft, borderBefore() + paddingBefore() + i * colLogicalHeight, colLogicalWidth, colLogicalHeight);
if (!isHorizontalWritingMode())
@@ -5409,7 +5318,7 @@ static inline void stripTrailingSpace(float& inlineMax, float& inlineMin,
static inline void updatePreferredWidth(LayoutUnit& preferredWidth, float& result)
{
- LayoutUnit snappedResult = ceiledLayoutUnit(result);
+ LayoutUnit snappedResult = ceilf(result);
preferredWidth = max(snappedResult, preferredWidth);
}
@@ -5420,7 +5329,7 @@ void RenderBlock::computeInlinePreferredLogicalWidths()
RenderStyle* styleToUse = style();
RenderBlock* containingBlock = this->containingBlock();
- LayoutUnit cw = containingBlock ? containingBlock->contentLogicalWidth() : zeroLayoutUnit;
+ LayoutUnit cw = containingBlock ? containingBlock->contentLogicalWidth() : ZERO_LAYOUT_UNIT;
// If we are at the start of a line, we want to ignore all white-space.
// Also strip spaces if we previously had text that ended in a trailing space.
@@ -5541,7 +5450,7 @@ void RenderBlock::computeInlinePreferredLogicalWidths()
LayoutUnit ti = 0;
if (!addedTextIndent) {
addedTextIndent = true;
- ti = styleToUse->textIndent().calcMinValue(cw);
+ ti = minimumValueForLength(styleToUse->textIndent(), cw, view());
childMin += ti;
childMax += ti;
}
@@ -5612,7 +5521,7 @@ void RenderBlock::computeInlinePreferredLogicalWidths()
LayoutUnit ti = 0;
if (!addedTextIndent) {
addedTextIndent = true;
- ti = styleToUse->textIndent().calcMinValue(cw);
+ ti = minimumValueForLength(styleToUse->textIndent(), cw, view());
childMin+=ti; beginMin += ti;
childMax+=ti; beginMax += ti;
}
@@ -5806,11 +5715,11 @@ LayoutUnit RenderBlock::lineHeight(bool firstLine, LineDirectionMode direction,
if (firstLine && document()->usesFirstLineRules()) {
RenderStyle* s = style(firstLine);
if (s != style())
- return s->computedLineHeight();
+ return s->computedLineHeight(view());
}
if (m_lineHeight == -1)
- m_lineHeight = style()->computedLineHeight();
+ m_lineHeight = style()->computedLineHeight(view());
return m_lineHeight;
}
@@ -5838,9 +5747,9 @@ LayoutUnit RenderBlock::baselinePosition(FontBaseline baselineType, bool firstLi
bool ignoreBaseline = (layer() && (layer()->marquee() || (direction == HorizontalLine ? (layer()->verticalScrollbar() || layer()->scrollYOffset() != 0)
: (layer()->horizontalScrollbar() || layer()->scrollXOffset() != 0)))) || (isWritingModeRoot() && !isRubyRun());
- int baselinePos = ignoreBaseline ? LayoutUnit(-1) : lastLineBoxBaseline();
+ LayoutUnit baselinePos = ignoreBaseline ? static_cast<LayoutUnit>(-1) : lastLineBoxBaseline();
- int bottomOfContent = direction == HorizontalLine ? borderTop() + paddingTop() + contentHeight() : borderRight() + paddingRight() + contentWidth();
+ LayoutUnit bottomOfContent = direction == HorizontalLine ? borderTop() + paddingTop() + contentHeight() : borderRight() + paddingRight() + contentWidth();
if (baselinePos != -1 && baselinePos <= bottomOfContent)
return direction == HorizontalLine ? marginTop() + baselinePos : marginRight() + baselinePos;
@@ -5993,120 +5902,67 @@ static inline RenderObject* findFirstLetterBlock(RenderBlock* start)
return 0;
}
-void RenderBlock::updateFirstLetter()
+void RenderBlock::updateFirstLetterStyle(RenderObject* firstLetterBlock, RenderObject* currentChild)
{
- if (!document()->usesFirstLetterRules())
- return;
- // Don't recur
- if (style()->styleType() == FIRST_LETTER)
- return;
-
- // FIXME: We need to destroy the first-letter object if it is no longer the first child. Need to find
- // an efficient way to check for that situation though before implementing anything.
- RenderObject* firstLetterBlock = findFirstLetterBlock(this);
- if (!firstLetterBlock)
- return;
+ RenderObject* firstLetter = currentChild->parent();
+ RenderObject* firstLetterContainer = firstLetter->parent();
+ RenderStyle* pseudoStyle = styleForFirstLetter(firstLetterBlock, firstLetterContainer);
+ ASSERT(firstLetter->isFloating() || firstLetter->isInline());
- // 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();
- }
+ if (Node::diff(firstLetter->style(), pseudoStyle, document()) == Node::Detach) {
+ // The first-letter renderer needs to be replaced. Create a new renderer of the right type.
+ RenderObject* newFirstLetter;
+ if (pseudoStyle->display() == INLINE)
+ newFirstLetter = new (renderArena()) RenderInline(document());
else
- currChild = currChild->firstChild();
- }
-
- if (!currChild)
- return;
-
- // If the child already has style, then it has already been created, so we just want
- // to update it.
- if (currChild->parent()->style()->styleType() == FIRST_LETTER) {
- RenderObject* firstLetter = currChild->parent();
- RenderObject* firstLetterContainer = firstLetter->parent();
- RenderStyle* pseudoStyle = styleForFirstLetter(firstLetterBlock, firstLetterContainer);
- ASSERT(firstLetter->isFloating() || firstLetter->isInline());
-
- if (Node::diff(firstLetter->style(), pseudoStyle) == Node::Detach) {
- // The first-letter renderer needs to be replaced. Create a new renderer of the right type.
- RenderObject* newFirstLetter;
- if (pseudoStyle->display() == INLINE)
- newFirstLetter = new (renderArena()) RenderInline(document());
- else
- newFirstLetter = new (renderArena()) RenderBlock(document());
- newFirstLetter->setStyle(pseudoStyle);
-
- // Move the first letter into the new renderer.
- LayoutStateDisabler layoutStateDisabler(view());
- while (RenderObject* child = firstLetter->firstChild()) {
- if (child->isText())
- toRenderText(child)->removeAndDestroyTextBoxes();
- firstLetter->removeChild(child);
- newFirstLetter->addChild(child, 0);
- }
-
- RenderTextFragment* remainingText = 0;
- RenderObject* nextSibling = firstLetter->nextSibling();
- RenderObject* remainingTextObject = toRenderBoxModelObject(firstLetter)->firstLetterRemainingText();
- if (remainingTextObject && remainingTextObject->isText() && toRenderText(remainingTextObject)->isTextFragment())
- remainingText = toRenderTextFragment(remainingTextObject);
- if (remainingText) {
- ASSERT(remainingText->isAnonymous() || remainingText->node()->renderer() == remainingText);
- // Replace the old renderer with the new one.
- remainingText->setFirstLetter(newFirstLetter);
- toRenderBoxModelObject(newFirstLetter)->setFirstLetterRemainingText(remainingText);
- }
- firstLetter->destroy();
- firstLetter = newFirstLetter;
- firstLetterContainer->addChild(firstLetter, nextSibling);
- } else
- firstLetter->setStyle(pseudoStyle);
-
- for (RenderObject* genChild = firstLetter->firstChild(); genChild; genChild = genChild->nextSibling()) {
- if (genChild->isText())
- genChild->setStyle(pseudoStyle);
- }
+ newFirstLetter = new (renderArena()) RenderBlock(document());
+ newFirstLetter->setStyle(pseudoStyle);
+
+ // Move the first letter into the new renderer.
+ LayoutStateDisabler layoutStateDisabler(view());
+ while (RenderObject* child = firstLetter->firstChild()) {
+ if (child->isText())
+ toRenderText(child)->removeAndDestroyTextBoxes();
+ firstLetter->removeChild(child);
+ newFirstLetter->addChild(child, 0);
+ }
+
+ RenderTextFragment* remainingText = 0;
+ RenderObject* nextSibling = firstLetter->nextSibling();
+ RenderObject* remainingTextObject = toRenderBoxModelObject(firstLetter)->firstLetterRemainingText();
+ if (remainingTextObject && remainingTextObject->isText() && toRenderText(remainingTextObject)->isTextFragment())
+ remainingText = toRenderTextFragment(remainingTextObject);
+ if (remainingText) {
+ ASSERT(remainingText->isAnonymous() || remainingText->node()->renderer() == remainingText);
+ // Replace the old renderer with the new one.
+ remainingText->setFirstLetter(newFirstLetter);
+ toRenderBoxModelObject(newFirstLetter)->setFirstLetterRemainingText(remainingText);
+ }
+ firstLetter->destroy();
+ firstLetter = newFirstLetter;
+ firstLetterContainer->addChild(firstLetter, nextSibling);
+ } else
+ firstLetter->setStyle(pseudoStyle);
- return;
+ for (RenderObject* genChild = firstLetter->firstChild(); genChild; genChild = genChild->nextSibling()) {
+ if (genChild->isText())
+ genChild->setStyle(pseudoStyle);
}
+}
- if (!currChild->isText() || currChild->isBR())
- return;
-
- // If the child does not already have style, we create it here.
- RenderObject* firstLetterContainer = currChild->parent();
-
- // Our layout state is not valid for the repaints we are going to trigger by
- // adding and removing children of firstLetterContainer.
- LayoutStateDisabler layoutStateDisabler(view());
-
- RenderText* textObj = toRenderText(currChild);
-
- // Create our pseudo style now that we have our firstLetterContainer determined.
+void RenderBlock::createFirstLetterRenderer(RenderObject* firstLetterBlock, RenderObject* currentChild)
+{
+ RenderObject* firstLetterContainer = currentChild->parent();
RenderStyle* pseudoStyle = styleForFirstLetter(firstLetterBlock, firstLetterContainer);
-
RenderObject* firstLetter = 0;
if (pseudoStyle->display() == INLINE)
firstLetter = new (renderArena()) RenderInline(document());
else
firstLetter = new (renderArena()) RenderBlock(document());
firstLetter->setStyle(pseudoStyle);
- firstLetterContainer->addChild(firstLetter, currChild);
+ firstLetterContainer->addChild(firstLetter, currentChild);
+
+ RenderText* textObj = toRenderText(currentChild);
// The original string is going to be either a generated content string or a DOM node's
// string. We want the original string before it got transformed in case first-letter has
@@ -6159,6 +6015,63 @@ void RenderBlock::updateFirstLetter()
}
}
+void RenderBlock::updateFirstLetter()
+{
+ if (!document()->usesFirstLetterRules())
+ return;
+ // Don't recur
+ if (style()->styleType() == FIRST_LETTER)
+ return;
+
+ // FIXME: We need to destroy the first-letter object if it is no longer the first child. Need to find
+ // an efficient way to check for that situation though before implementing anything.
+ RenderObject* firstLetterBlock = findFirstLetterBlock(this);
+ if (!firstLetterBlock)
+ return;
+
+ // 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 (!currChild)
+ return;
+
+ // If the child already has style, then it has already been created, so we just want
+ // to update it.
+ if (currChild->parent()->style()->styleType() == FIRST_LETTER) {
+ updateFirstLetterStyle(firstLetterBlock, currChild);
+ return;
+ }
+
+ 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, currChild);
+}
+
// Helper methods for obtaining the last line, computing line counts and heights for line counts
// (crawling into blocks).
static bool shouldCheckLines(RenderObject* obj)
@@ -6196,7 +6109,7 @@ static int getHeightForLineCount(RenderBlock* block, int l, bool includeBottom,
if (block->childrenInline()) {
for (RootInlineBox* box = block->firstRootBox(); box; box = box->nextRootBox()) {
if (++count == l)
- return box->lineBottom() + (includeBottom ? (block->borderBottom() + block->paddingBottom()) : zeroLayoutUnit);
+ return box->lineBottom() + (includeBottom ? (block->borderBottom() + block->paddingBottom()) : ZERO_LAYOUT_UNIT);
}
}
else {
@@ -6205,7 +6118,7 @@ static int getHeightForLineCount(RenderBlock* block, int l, bool includeBottom,
if (shouldCheckLines(obj)) {
int result = getHeightForLineCount(toRenderBlock(obj), l, false, count);
if (result != -1)
- return result + obj->y() + (includeBottom ? (block->borderBottom() + block->paddingBottom()) : zeroLayoutUnit);
+ return result + obj->y() + (includeBottom ? (block->borderBottom() + block->paddingBottom()) : ZERO_LAYOUT_UNIT);
}
else if (!obj->isFloatingOrPositioned() && !obj->isRunIn())
normalFlowChildWithoutLines = obj;
@@ -6278,7 +6191,7 @@ void RenderBlock::adjustForBorderFit(LayoutUnit x, LayoutUnit& left, LayoutUnit&
for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
FloatingObject* r = *it;
// Only examine the object if our m_shouldPaint flag is set.
- if (r->m_shouldPaint) {
+ if (r->shouldPaint()) {
LayoutUnit floatLeft = xPositionForFloatIncludingMargin(r) - r->m_renderer->x();
LayoutUnit floatRight = floatLeft + r->m_renderer->width();
left = min(left, floatLeft);
@@ -6295,11 +6208,11 @@ void RenderBlock::borderFitAdjust(LayoutRect& rect) const
return;
// Walk any normal flow lines to snugly fit.
- LayoutUnit left = numeric_limits<LayoutUnit>::max();
- LayoutUnit right = numeric_limits<LayoutUnit>::min();
+ LayoutUnit left = MAX_LAYOUT_UNIT;
+ LayoutUnit right = MIN_LAYOUT_UNIT;
LayoutUnit oldWidth = rect.width();
adjustForBorderFit(0, left, right);
- if (left != numeric_limits<LayoutUnit>::max()) {
+ if (left != MAX_LAYOUT_UNIT) {
left = min(left, oldWidth - (borderRight() + paddingRight()));
left -= (borderLeft() + paddingLeft());
@@ -6308,7 +6221,7 @@ void RenderBlock::borderFitAdjust(LayoutRect& rect) const
rect.expand(-left, 0);
}
}
- if (right != numeric_limits<LayoutUnit>::min()) {
+ if (right != MIN_LAYOUT_UNIT) {
right = max(right, borderLeft() + paddingLeft());
right += (borderRight() + paddingRight());
@@ -6365,7 +6278,7 @@ void RenderBlock::setPaginationStrut(LayoutUnit strut)
m_rareData->m_paginationStrut = strut;
}
-void RenderBlock::setPageLogicalOffset(int logicalOffset)
+void RenderBlock::setPageLogicalOffset(LayoutUnit logicalOffset)
{
if (!m_rareData) {
if (!logicalOffset)
@@ -6513,14 +6426,23 @@ LayoutRect RenderBlock::localCaretRect(InlineBox* inlineBox, int caretOffset, La
switch (alignment) {
case alignLeft:
+ if (currentStyle->isLeftToRightDirection())
+ x += textIndentOffset();
break;
case alignCenter:
x = (x + w - (borderRight() + paddingRight())) / 2;
+ if (currentStyle->isLeftToRightDirection())
+ x += textIndentOffset() / 2;
+ else
+ x -= textIndentOffset() / 2;
break;
case alignRight:
x = w - (borderRight() + paddingRight()) - caretWidth;
+ if (!currentStyle->isLeftToRightDirection())
+ x -= textIndentOffset();
break;
}
+ x = min(x, w - borderRight() - paddingRight() - caretWidth);
if (extraWidthToEndOfLine) {
if (isRenderBlock()) {
@@ -6593,52 +6515,13 @@ void RenderBlock::addFocusRingRects(Vector<IntRect>& rects, const LayoutPoint& a
inlineElementContinuation()->addFocusRingRects(rects, flooredLayoutPoint(additionalOffset + inlineElementContinuation()->containingBlock()->location() - location()));
}
-RenderBlock* RenderBlock::createAnonymousBlock(bool isFlexibleBox) const
-{
- RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyle(style());
-
- RenderBlock* newBox = 0;
- if (isFlexibleBox) {
- newStyle->setDisplay(BOX);
- newBox = new (renderArena()) RenderDeprecatedFlexibleBox(document() /* anonymous box */);
- } else {
- newStyle->setDisplay(BLOCK);
- newBox = new (renderArena()) RenderBlock(document() /* anonymous box */);
- }
-
- newBox->setStyle(newStyle.release());
- return newBox;
-}
-
-RenderBlock* RenderBlock::createAnonymousBlockWithSameTypeAs(RenderBlock* otherAnonymousBlock) const
-{
- if (otherAnonymousBlock->isAnonymousColumnsBlock())
- return createAnonymousColumnsBlock();
- if (otherAnonymousBlock->isAnonymousColumnSpanBlock())
- return createAnonymousColumnSpanBlock();
- return createAnonymousBlock(otherAnonymousBlock->style()->display() == BOX);
-}
-
-RenderBlock* RenderBlock::createAnonymousColumnsBlock() const
-{
- RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyle(style());
- newStyle->inheritColumnPropertiesFrom(style());
- newStyle->setDisplay(BLOCK);
-
- RenderBlock* newBox = new (renderArena()) RenderBlock(document() /* anonymous box */);
- newBox->setStyle(newStyle.release());
- return newBox;
-}
-
-RenderBlock* RenderBlock::createAnonymousColumnSpanBlock() const
+RenderBox* RenderBlock::createAnonymousBoxWithSameTypeAs(const RenderObject* parent) const
{
- RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyle(style());
- newStyle->setColumnSpan(ColumnSpanAll);
- newStyle->setDisplay(BLOCK);
-
- RenderBlock* newBox = new (renderArena()) RenderBlock(document() /* anonymous box */);
- newBox->setStyle(newStyle.release());
- return newBox;
+ if (isAnonymousColumnsBlock())
+ return createAnonymousColumnsWithParentRenderer(parent);
+ if (isAnonymousColumnSpanBlock())
+ return createAnonymousColumnSpanWithParentRenderer(parent);
+ return createAnonymousWithParentRendererAndDisplay(parent, style()->display());
}
bool RenderBlock::hasNextPage(LayoutUnit logicalOffset, PageBoundaryRule pageBoundaryRule) const
@@ -6777,7 +6660,7 @@ LayoutUnit RenderBlock::adjustForUnsplittableChild(RenderBox* child, LayoutUnit
|| (checkRegionBreaks && child->style()->regionBreakInside() == PBAVOID);
if (!isUnsplittable)
return logicalOffset;
- LayoutUnit childLogicalHeight = logicalHeightForChild(child) + (includeMargins ? marginBeforeForChild(child) + marginAfterForChild(child) : zeroLayoutUnit);
+ LayoutUnit childLogicalHeight = logicalHeightForChild(child) + (includeMargins ? marginBeforeForChild(child) + marginAfterForChild(child) : ZERO_LAYOUT_UNIT);
LayoutState* layoutState = view()->layoutState();
if (layoutState->m_columnInfo)
layoutState->m_columnInfo->updateMinimumColumnHeight(childLogicalHeight);
@@ -6876,7 +6759,7 @@ LayoutUnit RenderBlock::adjustBlockChildForPagination(LayoutUnit logicalTopAfter
// When the child shifts to clear an item, its width can
// change (because it has more available line width).
// So go ahead and mark the item as dirty.
- child->setChildNeedsLayout(true, false);
+ child->setChildNeedsLayout(true, MarkOnlyThis);
}
if (childRenderBlock) {
@@ -7072,20 +6955,6 @@ LayoutUnit RenderBlock::marginAfterForChild(const RenderBoxModelObject* child) c
return child->marginBottom();
}
-LayoutUnit RenderBlock::marginLogicalLeftForChild(const RenderBoxModelObject* child) const
-{
- if (isHorizontalWritingMode())
- return child->marginLeft();
- return child->marginTop();
-}
-
-LayoutUnit RenderBlock::marginLogicalRightForChild(const RenderBoxModelObject* child) const
-{
- if (isHorizontalWritingMode())
- return child->marginRight();
- return child->marginBottom();
-}
-
LayoutUnit RenderBlock::marginStartForChild(const RenderBoxModelObject* child) const
{
if (isHorizontalWritingMode())
@@ -7168,13 +7037,13 @@ void RenderBlock::setMarginAfterForChild(RenderBox* child, LayoutUnit margin)
RenderBlock::MarginValues RenderBlock::marginValuesForChild(RenderBox* child)
{
- int childBeforePositive = 0;
- int childBeforeNegative = 0;
- int childAfterPositive = 0;
- int childAfterNegative = 0;
+ LayoutUnit childBeforePositive = 0;
+ LayoutUnit childBeforeNegative = 0;
+ LayoutUnit childAfterPositive = 0;
+ LayoutUnit childAfterNegative = 0;
- int beforeMargin = 0;
- int afterMargin = 0;
+ LayoutUnit beforeMargin = 0;
+ LayoutUnit afterMargin = 0;
RenderBlock* childRenderBlock = child->isRenderBlock() ? toRenderBlock(child) : 0;
@@ -7256,34 +7125,29 @@ inline void RenderBlock::FloatingObjects::clear()
m_placedFloatsTree.clear();
m_leftObjectsCount = 0;
m_rightObjectsCount = 0;
- m_positionedObjectsCount = 0;
}
inline void RenderBlock::FloatingObjects::increaseObjectsCount(FloatingObject::Type type)
{
if (type == FloatingObject::FloatLeft)
m_leftObjectsCount++;
- else if (type == FloatingObject::FloatRight)
+ else
m_rightObjectsCount++;
- else
- m_positionedObjectsCount++;
}
inline void RenderBlock::FloatingObjects::decreaseObjectsCount(FloatingObject::Type type)
{
if (type == FloatingObject::FloatLeft)
m_leftObjectsCount--;
- else if (type == FloatingObject::FloatRight)
- m_rightObjectsCount--;
else
- m_positionedObjectsCount--;
+ m_rightObjectsCount--;
}
inline RenderBlock::FloatingObjectInterval RenderBlock::FloatingObjects::intervalForFloatingObject(FloatingObject* floatingObject)
{
if (m_horizontalWritingMode)
- return RenderBlock::FloatingObjectInterval(floatingObject->y(), floatingObject->maxY(), floatingObject);
- return RenderBlock::FloatingObjectInterval(floatingObject->x(), floatingObject->maxX(), floatingObject);
+ return RenderBlock::FloatingObjectInterval(floatingObject->pixelSnappedY(), floatingObject->pixelSnappedMaxY(), floatingObject);
+ return RenderBlock::FloatingObjectInterval(floatingObject->pixelSnappedX(), floatingObject->pixelSnappedMaxX(), floatingObject);
}
void RenderBlock::FloatingObjects::addPlacedObject(FloatingObject* floatingObject)
@@ -7371,6 +7235,45 @@ TextRun RenderBlock::constructTextRun(RenderObject* context, const Font& font, c
return constructTextRun(context, font, string.characters(), string.length(), style, expansion, flags);
}
+RenderBlock* RenderBlock::createAnonymousWithParentRendererAndDisplay(const RenderObject* parent, EDisplay display)
+{
+ // FIXME: Do we need to cover the new flex box here ?
+ // FIXME: Do we need to convert all our inline displays to block-type in the anonymous logic ?
+ EDisplay newDisplay;
+ RenderBlock* newBox = 0;
+ if (display == BOX || display == INLINE_BOX) {
+ newBox = new (parent->renderArena()) RenderDeprecatedFlexibleBox(parent->document() /* anonymous box */);
+ newDisplay = BOX;
+ } else {
+ newBox = new (parent->renderArena()) RenderBlock(parent->document() /* anonymous box */);
+ newDisplay = BLOCK;
+ }
+
+ RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(parent->style(), newDisplay);
+ newBox->setStyle(newStyle.release());
+ return newBox;
+}
+
+RenderBlock* RenderBlock::createAnonymousColumnsWithParentRenderer(const RenderObject* parent)
+{
+ RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(parent->style(), BLOCK);
+ newStyle->inheritColumnPropertiesFrom(parent->style());
+
+ RenderBlock* newBox = new (parent->renderArena()) RenderBlock(parent->document() /* anonymous box */);
+ newBox->setStyle(newStyle.release());
+ return newBox;
+}
+
+RenderBlock* RenderBlock::createAnonymousColumnSpanWithParentRenderer(const RenderObject* parent)
+{
+ RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(parent->style(), BLOCK);
+ newStyle->setColumnSpan(ColumnSpanAll);
+
+ RenderBlock* newBox = new (parent->renderArena()) RenderBlock(parent->document() /* anonymous box */);
+ newBox->setStyle(newStyle.release());
+ return newBox;
+}
+
#ifndef NDEBUG
void RenderBlock::showLineTreeAndMark(const InlineBox* markedBox1, const char* markedLabel1, const InlineBox* markedBox2, const char* markedLabel2, const RenderObject* obj) const
@@ -7388,7 +7291,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->x(), floatingObject->y(), floatingObject->maxX(), floatingObject->maxY());
+ return String::format("%p (%dx%d %dx%d)", floatingObject, floatingObject->pixelSnappedX(), floatingObject->pixelSnappedY(), floatingObject->pixelSnappedMaxX(), floatingObject->pixelSnappedMaxY());
}
#endif
diff --git a/Source/WebCore/rendering/RenderBlock.h b/Source/WebCore/rendering/RenderBlock.h
index cf2317348..2f6f4b6de 100644
--- a/Source/WebCore/rendering/RenderBlock.h
+++ b/Source/WebCore/rendering/RenderBlock.h
@@ -96,8 +96,7 @@ public:
virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0);
virtual void removeChild(RenderObject*);
- enum BlockLayoutPass { NormalLayoutPass, PositionedFloatLayoutPass };
- virtual void layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeight = 0, BlockLayoutPass = NormalLayoutPass);
+ virtual void layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeight = 0);
void insertPositionedObject(RenderBox*);
void removePositionedObject(RenderBox*);
@@ -166,6 +165,17 @@ public:
{
return logicalLeftOffsetForLine(position, logicalLeftOffsetForContent(position), firstLine, 0);
}
+ LayoutUnit pixelSnappedLogicalLeftOffsetForLine(LayoutUnit position, bool firstLine) const
+ {
+ return roundToInt(logicalLeftOffsetForLine(position, firstLine));
+ }
+ LayoutUnit pixelSnappedLogicalRightOffsetForLine(LayoutUnit position, bool firstLine) const
+ {
+ // FIXME: Multicolumn layouts break carrying over subpixel values to the logical right offset because the lines may be shifted
+ // by a subpixel value for all but the first column. This can lead to the actual pixel snapped width of the column being off
+ // by one pixel when rendered versus layed out, which can result in the line being clipped. For now, we have to floor.
+ return floorToInt(logicalRightOffsetForLine(position, firstLine));
+ }
LayoutUnit startOffsetForLine(LayoutUnit position, bool firstLine) const
{
return style()->isLeftToRightDirection() ? logicalLeftOffsetForLine(position, firstLine)
@@ -177,17 +187,6 @@ public:
: logicalWidth() - logicalRightOffsetForLine(position, firstLine);
}
- // FIXME: The implementation for these functions will change once we move to subpixel layout. See bug 60318.
- int pixelSnappedLogicalRightOffsetForLine(LayoutUnit position, bool firstLine) const
- {
- return logicalRightOffsetForLine(position, logicalRightOffsetForContent(position), firstLine, 0);
- }
-
- int pixelSnappedLogicalLeftOffsetForLine(LayoutUnit position, bool firstLine) const
- {
- return roundToInt(logicalLeftOffsetForLine(position, logicalLeftOffsetForContent(position), firstLine, 0));
- }
-
LayoutUnit startAlignedOffsetForLine(RenderBox* child, LayoutUnit position, bool firstLine);
LayoutUnit textIndentOffset() const;
@@ -210,6 +209,8 @@ public:
LayoutRect logicalRightSelectionGap(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
RenderObject* selObj, LayoutUnit logicalRight, LayoutUnit logicalTop, LayoutUnit logicalHeight, const PaintInfo*);
void getSelectionGapInfo(SelectionState, bool& leftGap, bool& rightGap);
+ RenderBlock* blockBeforeWithinSelectionRoot(LayoutSize& offset) const;
+
LayoutRect logicalRectToPhysicalRect(const LayoutPoint& physicalPosition, const LayoutRect& logicalRect);
// Helper methods for computing line counts and heights for line counts.
@@ -233,12 +234,14 @@ public:
using RenderBoxModelObject::continuation;
using RenderBoxModelObject::setContinuation;
- // This function is a convenience helper for creating an anonymous block that inherits its
- // style from this RenderBlock.
- RenderBlock* createAnonymousBlock(bool isFlexibleBox = false) const;
- RenderBlock* createAnonymousColumnsBlock() const;
- RenderBlock* createAnonymousColumnSpanBlock() const;
- RenderBlock* createAnonymousBlockWithSameTypeAs(RenderBlock* otherAnonymousBlock) const;
+ static RenderBlock* createAnonymousWithParentRendererAndDisplay(const RenderObject*, EDisplay = BLOCK);
+ static RenderBlock* createAnonymousColumnsWithParentRenderer(const RenderObject*);
+ static RenderBlock* createAnonymousColumnSpanWithParentRenderer(const RenderObject*);
+ RenderBlock* createAnonymousBlock(EDisplay display = BLOCK) const { return createAnonymousWithParentRendererAndDisplay(this, display); }
+ RenderBlock* createAnonymousColumnsBlock() const { return createAnonymousColumnsWithParentRenderer(this); }
+ RenderBlock* createAnonymousColumnSpanBlock() const { return createAnonymousColumnSpanWithParentRenderer(this); }
+
+ virtual RenderBox* createAnonymousBoxWithSameTypeAs(const RenderObject* parent) const OVERRIDE;
static void appendRunsForObject(BidiRunList<BidiRun>&, int start, int end, RenderObject*, InlineBidiResolver&);
@@ -255,13 +258,13 @@ public:
unsigned columnCount(ColumnInfo*) const;
LayoutRect columnRectAt(ColumnInfo*, unsigned) const;
- LayoutUnit paginationStrut() const { return m_rareData ? m_rareData->m_paginationStrut : zeroLayoutUnit; }
+ LayoutUnit paginationStrut() const { return m_rareData ? m_rareData->m_paginationStrut : ZERO_LAYOUT_UNIT; }
void setPaginationStrut(LayoutUnit);
// The page logical offset is the object's offset from the top of the page in the page progression
// direction (so an x-offset in vertical text and a y-offset for horizontal text).
- LayoutUnit pageLogicalOffset() const { return m_rareData ? m_rareData->m_pageLogicalOffset : zeroLayoutUnit; }
- void setPageLogicalOffset(int);
+ LayoutUnit pageLogicalOffset() const { return m_rareData ? m_rareData->m_pageLogicalOffset : ZERO_LAYOUT_UNIT; }
+ void setPageLogicalOffset(LayoutUnit);
RootInlineBox* lineGridBox() const { return m_rareData ? m_rareData->m_lineGridBox : 0; }
void setLineGridBox(RootInlineBox* box)
@@ -279,15 +282,12 @@ public:
LayoutUnit logicalWidthForChild(const RenderBox* child) { return isHorizontalWritingMode() ? child->width() : child->height(); }
LayoutUnit logicalHeightForChild(const RenderBox* child) { return isHorizontalWritingMode() ? child->height() : child->width(); }
LayoutUnit logicalTopForChild(const RenderBox* child) { return isHorizontalWritingMode() ? child->y() : child->x(); }
- LayoutUnit logicalLeftForChild(const RenderBox* child) { return isHorizontalWritingMode() ? child->x() : child->y(); }
void setLogicalLeftForChild(RenderBox* child, LayoutUnit logicalLeft, ApplyLayoutDeltaMode = DoNotApplyLayoutDelta);
void setLogicalTopForChild(RenderBox* child, LayoutUnit logicalTop, ApplyLayoutDeltaMode = DoNotApplyLayoutDelta);
LayoutUnit marginBeforeForChild(const RenderBoxModelObject* child) const;
LayoutUnit marginAfterForChild(const RenderBoxModelObject* child) const;
LayoutUnit marginStartForChild(const RenderBoxModelObject* child) const;
LayoutUnit marginEndForChild(const RenderBoxModelObject* child) const;
- LayoutUnit marginLogicalLeftForChild(const RenderBoxModelObject* child) const;
- LayoutUnit marginLogicalRightForChild(const RenderBoxModelObject* child) const;
void setMarginStartForChild(RenderBox* child, LayoutUnit);
void setMarginEndForChild(RenderBox* child, LayoutUnit);
void setMarginBeforeForChild(RenderBox* child, LayoutUnit);
@@ -371,8 +371,7 @@ public:
void setStaticInlinePositionForChild(RenderBox*, LayoutUnit blockOffset, LayoutUnit inlinePosition);
- LayoutUnit computeStartPositionDeltaForChildAvoidingFloats(const RenderBox* child, LayoutUnit childMarginStart,
- LayoutUnit childLogicalWidth, RenderRegion* = 0, LayoutUnit offsetFromLogicalTopOfFirstPage = 0);
+ LayoutUnit computeStartPositionDeltaForChildAvoidingFloats(const RenderBox* child, LayoutUnit childMarginStart, RenderRegion* = 0, LayoutUnit offsetFromLogicalTopOfFirstPage = 0);
#ifndef NDEBUG
void showLineTreeAndMark(const InlineBox* = 0, const char* = 0, const InlineBox* = 0, const char* = 0, const RenderObject* = 0) const;
@@ -381,32 +380,6 @@ public:
protected:
virtual void willBeDestroyed();
- void updateScrollInfoAfterLayout();
-
- // 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(RenderBlock* to, RenderObject* child, bool fullRemoveInsert = false)
- {
- return moveChildTo(to, child, 0, fullRemoveInsert);
- }
- void moveChildTo(RenderBlock* toBlock, RenderObject* child, RenderObject* beforeChild, bool fullRemoveInsert = false);
- void moveAllChildrenTo(RenderBlock* toBlock, bool fullRemoveInsert = false)
- {
- return moveAllChildrenTo(toBlock, 0, fullRemoveInsert);
- }
- void moveAllChildrenTo(RenderBlock* toBlock, RenderObject* beforeChild, bool fullRemoveInsert = false)
- {
- return moveChildrenTo(toBlock, firstChild(), 0, beforeChild, fullRemoveInsert);
- }
- // Move all of the kids from |startChild| up to but excluding |endChild|. 0 can be passed as the endChild to denote
- // that all the kids from |startChild| onwards should be added.
- void moveChildrenTo(RenderBlock* toBlock, RenderObject* startChild, RenderObject* endChild, bool fullRemoveInsert = false)
- {
- return moveChildrenTo(toBlock, startChild, endChild, 0, fullRemoveInsert);
- }
- void moveChildrenTo(RenderBlock* toBlock, RenderObject* startChild, RenderObject* endChild, RenderObject* beforeChild, bool fullRemoveInsert = false);
-
LayoutUnit maxPositiveMarginBefore() const { return m_rareData ? m_rareData->m_margins.positiveMarginBefore() : RenderBlockRareData::positiveMarginBeforeDefault(this); }
LayoutUnit maxNegativeMarginBefore() const { return m_rareData ? m_rareData->m_margins.negativeMarginBefore() : RenderBlockRareData::negativeMarginBeforeDefault(this); }
LayoutUnit maxPositiveMarginAfter() const { return m_rareData ? m_rareData->m_margins.positiveMarginAfter() : RenderBlockRareData::positiveMarginAfterDefault(this); }
@@ -426,7 +399,7 @@ protected:
virtual void layout();
- bool layoutPositionedObjects(bool relayoutChildren);
+ void layoutPositionedObjects(bool relayoutChildren);
virtual void paint(PaintInfo&, const LayoutPoint&);
virtual void paintObject(PaintInfo&, const LayoutPoint&);
@@ -480,6 +453,7 @@ protected:
{
LayoutUnit repaintLogicalTop = 0;
LayoutUnit repaintLogicalBottom = 0;
+ clearFloats();
layoutInlineChildren(true, repaintLogicalTop, repaintLogicalBottom);
}
#endif
@@ -529,6 +503,9 @@ private:
// Called to lay out the legend for a fieldset or the ruby text of a ruby run.
virtual RenderObject* layoutSpecialExcludedChild(bool /*relayoutChildren*/) { return 0; }
+ void createFirstLetterRenderer(RenderObject* firstLetterBlock, RenderObject* currentChild);
+ void updateFirstLetterStyle(RenderObject* firstLetterBlock, RenderObject* firstLetterContainer);
+
struct FloatWithRect {
FloatWithRect(RenderBox* f)
: object(f)
@@ -545,15 +522,14 @@ private:
struct FloatingObject {
WTF_MAKE_NONCOPYABLE(FloatingObject); WTF_MAKE_FAST_ALLOCATED;
public:
- // FloatLeftRight is a mask to query for both left and right but not positioned.
- // FloatAll is a mask to query for all types of floats.
- enum Type { FloatLeft = 1, FloatRight = 2, FloatLeftRight = 3, FloatPositioned = 4, FloatAll = 7 };
+ // Note that Type uses bits so you can use FloatLeftRight as a mask to query for both left and right.
+ enum Type { FloatLeft = 1, FloatRight = 2, FloatLeftRight = 3 };
FloatingObject(EFloat type)
: m_renderer(0)
, m_originatingLine(0)
, m_paginationStrut(0)
- , m_shouldPaint(false)
+ , m_shouldPaint(true)
, m_isDescendant(false)
, m_isPlaced(false)
#ifndef NDEBUG
@@ -564,9 +540,7 @@ private:
if (type == LeftFloat)
m_type = FloatLeft;
else if (type == RightFloat)
- m_type = FloatRight;
- else if (type == PositionedFloat)
- m_type = FloatPositioned;
+ m_type = FloatRight;
}
FloatingObject(Type type, const LayoutRect& frameRect)
@@ -575,7 +549,7 @@ private:
, m_frameRect(frameRect)
, m_paginationStrut(0)
, m_type(type)
- , m_shouldPaint(type != FloatPositioned)
+ , m_shouldPaint(true)
, m_isDescendant(false)
, m_isPlaced(true)
#ifndef NDEBUG
@@ -597,13 +571,12 @@ private:
LayoutUnit width() const { return m_frameRect.width(); }
LayoutUnit height() const { return m_frameRect.height(); }
- // FIXME: The implementation for these functions will change once we move to subpixel layout. See bug 60318.
- int pixelSnappedX() const { return x(); }
- int pixelSnappedMaxX() const { return maxX(); }
- int pixelSnappedY() const { return y(); }
- int pixelSnappedMaxY() const { return maxY(); }
- int pixelSnappedWidth() const { return width(); }
- int pixelSnappedHeight() const { return height(); }
+ int pixelSnappedX() const { ASSERT(isPlaced()); return m_frameRect.pixelSnappedX(); }
+ int pixelSnappedMaxX() const { ASSERT(isPlaced()); return m_frameRect.pixelSnappedMaxX(); }
+ int pixelSnappedY() const { ASSERT(isPlaced()); return m_frameRect.pixelSnappedY(); }
+ int pixelSnappedMaxY() const { ASSERT(isPlaced()); return m_frameRect.pixelSnappedMaxY(); }
+ int pixelSnappedWidth() const { return m_frameRect.pixelSnappedWidth(); }
+ 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); }
@@ -618,16 +591,23 @@ private:
void setIsInPlacedTree(bool value) { m_isInPlacedTree = value; }
#endif
+ bool shouldPaint() const { return m_shouldPaint; }
+ void setShouldPaint(bool shouldPaint) { m_shouldPaint = shouldPaint; }
+ bool isDescendant() const { return m_isDescendant; }
+ void setIsDescendant(bool isDescendant) { m_isDescendant = isDescendant; }
+
RenderBox* m_renderer;
RootInlineBox* m_originatingLine;
LayoutRect m_frameRect;
int m_paginationStrut;
- unsigned m_type : 3; // Type (left/right aligned or positioned)
- bool m_shouldPaint : 1;
- bool m_isDescendant : 1;
- bool m_isPlaced : 1;
+
+ private:
+ unsigned m_type : 2; // Type (left or right aligned)
+ unsigned m_shouldPaint : 1;
+ unsigned m_isDescendant : 1;
+ unsigned m_isPlaced : 1;
#ifndef NDEBUG
- bool m_isInPlacedTree : 1;
+ unsigned m_isInPlacedTree : 1;
#endif
};
@@ -759,23 +739,18 @@ private:
// Returns true if and only if it has positioned any floats.
bool positionNewFloats();
- bool hasPositionedFloats() const { return m_hasPositionedFloats; }
- void addPositionedFloats();
- bool positionedFloatsNeedRelayout();
+ void clearFloats();
- void clearFloats(BlockLayoutPass);
LayoutUnit getClearDelta(RenderBox* child, LayoutUnit yPos);
virtual bool avoidsFloats() const;
- bool hasOverhangingFloats() { return parent() && !hasColumns() && containsFloats() && lowestFloatLogicalBottomIncludingPositionedFloats() > logicalHeight(); }
+ bool hasOverhangingFloats() { return parent() && !hasColumns() && containsFloats() && lowestFloatLogicalBottom() > logicalHeight(); }
bool hasOverhangingFloat(RenderBox*);
void addIntrudingFloats(RenderBlock* prev, LayoutUnit xoffset, LayoutUnit yoffset);
LayoutUnit addOverhangingFloats(RenderBlock* child, bool makeChildPaintOtherFloats);
- LayoutUnit lowestFloatLogicalBottom() const { return lowestFloatLogicalBottom(FloatingObject::FloatLeftRight); }
- LayoutUnit lowestFloatLogicalBottomIncludingPositionedFloats() const { return lowestFloatLogicalBottom(FloatingObject::FloatAll); }
- LayoutUnit lowestFloatLogicalBottom(FloatingObject::Type) const;
+ LayoutUnit lowestFloatLogicalBottom(FloatingObject::Type = FloatingObject::FloatLeftRight) const;
LayoutUnit nextFloatLogicalBottomBelow(LayoutUnit) const;
virtual bool hitTestColumns(const HitTestRequest&, HitTestResult&, const LayoutPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction);
@@ -814,7 +789,7 @@ private:
LayoutUnit lastLogicalTop, LayoutUnit lastLogicalLeft, LayoutUnit lastLogicalRight, LayoutUnit logicalBottom, const PaintInfo*);
LayoutUnit logicalLeftSelectionOffset(RenderBlock* rootBlock, LayoutUnit position);
LayoutUnit logicalRightSelectionOffset(RenderBlock* rootBlock, LayoutUnit position);
-
+
virtual void absoluteRects(Vector<IntRect>&, const LayoutPoint& accumulatedOffset) const;
virtual void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const;
@@ -844,8 +819,8 @@ private:
bool expandsToEncloseOverhangingFloats() const;
- RenderObject* splitAnonymousBlocksAroundChild(RenderObject* beforeChild);
- RenderObject* splitTablePartsAroundChild(RenderObject* beforeChild);
+ void updateScrollInfoAfterLayout();
+
void splitBlocks(RenderBlock* fromBlock, RenderBlock* toBlock, RenderBlock* middleBlock,
RenderObject* beforeChild, RenderBoxModelObject* oldCont);
void splitFlow(RenderObject* beforeChild, RenderBlock* newBlockBox,
@@ -983,6 +958,8 @@ protected:
virtual bool requiresColumns(int desiredColumnCount) const;
+ virtual bool recomputeLogicalWidth();
+
public:
LayoutUnit offsetFromLogicalTopOfFirstPage() const;
RenderRegion* regionAtBlockOffset(LayoutUnit) const;
@@ -1034,7 +1011,6 @@ protected:
: m_placedFloatsTree(UninitializedTree)
, m_leftObjectsCount(0)
, m_rightObjectsCount(0)
- , m_positionedObjectsCount(0)
, m_horizontalWritingMode(horizontalWritingMode)
, m_renderer(renderer)
{
@@ -1049,7 +1025,6 @@ protected:
bool hasLeftObjects() const { return m_leftObjectsCount > 0; }
bool hasRightObjects() const { return m_rightObjectsCount > 0; }
- bool hasPositionedObjects() const { return m_positionedObjectsCount > 0; }
const FloatingObjectSet& set() const { return m_set; }
const FloatingObjectTree& placedFloatsTree()
{
@@ -1071,7 +1046,6 @@ protected:
FloatingObjectTree m_placedFloatsTree;
unsigned m_leftObjectsCount;
unsigned m_rightObjectsCount;
- unsigned m_positionedObjectsCount;
bool m_horizontalWritingMode;
const RenderBlock* m_renderer;
};
@@ -1122,10 +1096,9 @@ protected:
RenderObjectChildList m_children;
RenderLineBoxList m_lineBoxes; // All of the root line boxes created for this block flow. For example, <div>Hello<br>world.</div> will have two total lines for the <div>.
- mutable signed m_lineHeight : 29;
- bool m_beingDestroyed : 1;
- bool m_hasPositionedFloats : 1;
- bool m_hasMarkupTruncation : 1;
+ mutable signed m_lineHeight : 30;
+ unsigned m_beingDestroyed : 1;
+ unsigned m_hasMarkupTruncation : 1;
// RenderRubyBase objects need to be able to split and merge, moving their children around
// (calling moveChildTo, moveAllChildrenTo, and makeChildrenNonInline).
diff --git a/Source/WebCore/rendering/RenderBlockLineLayout.cpp b/Source/WebCore/rendering/RenderBlockLineLayout.cpp
index e98db5c79..bceb24ac7 100755
--- a/Source/WebCore/rendering/RenderBlockLineLayout.cpp
+++ b/Source/WebCore/rendering/RenderBlockLineLayout.cpp
@@ -123,18 +123,18 @@ inline void LineWidth::updateAvailableWidth()
inline void LineWidth::shrinkAvailableWidthForNewFloatIfNeeded(RenderBlock::FloatingObject* newFloat)
{
- int height = m_block->logicalHeight();
+ LayoutUnit height = m_block->logicalHeight();
if (height < m_block->logicalTopForFloat(newFloat) || height >= m_block->logicalBottomForFloat(newFloat))
return;
if (newFloat->type() == RenderBlock::FloatingObject::FloatLeft) {
m_left = m_block->pixelSnappedLogicalRightForFloat(newFloat);
if (m_isFirstLine && m_block->style()->isLeftToRightDirection())
- m_left += m_block->textIndentOffset();
+ m_left += floorToInt(m_block->textIndentOffset());
} else {
m_right = m_block->pixelSnappedLogicalLeftForFloat(newFloat);
if (m_isFirstLine && !m_block->style()->isLeftToRightDirection())
- m_right -= m_block->textIndentOffset();
+ m_right -= floorToInt(m_block->textIndentOffset());
}
computeAvailableWidthFromLeftAndRight();
@@ -159,8 +159,8 @@ void LineWidth::fitBelowFloats()
ASSERT(!m_committedWidth);
ASSERT(!fitsOnLine());
- int floatLogicalBottom;
- int lastFloatLogicalBottom = m_block->logicalHeight();
+ LayoutUnit floatLogicalBottom;
+ LayoutUnit lastFloatLogicalBottom = m_block->logicalHeight();
float newLineWidth = m_availableWidth;
float newLineLeft = m_left;
float newLineRight = m_right;
@@ -522,7 +522,7 @@ RootInlineBox* RenderBlock::constructLine(BidiRunList<BidiRun>& bidiRuns, const
InlineTextBox* text = toInlineTextBox(box);
text->setStart(r->m_start);
text->setLen(r->m_stop - r->m_start);
- text->m_dirOverride = r->dirOverride(visuallyOrdered);
+ text->setDirOverride(r->dirOverride(visuallyOrdered));
if (r->m_hasHyphen)
text->setHasHyphen(true);
}
@@ -654,7 +654,7 @@ static inline void setLogicalWidthForTextRun(RootInlineBox* lineBox, BidiRun* ru
glyphOverflow.computeBounds = true;
}
- int hyphenWidth = 0;
+ LayoutUnit hyphenWidth = 0;
if (toInlineTextBox(run->m_box)->hasHyphen()) {
const Font& font = renderer->style(lineInfo.isFirstLine())->font();
hyphenWidth = measureHyphenWidth(renderer, font);
@@ -662,14 +662,14 @@ static inline void setLogicalWidthForTextRun(RootInlineBox* lineBox, BidiRun* ru
run->m_box->setLogicalWidth(renderer->width(run->m_start, run->m_stop - run->m_start, xPos, lineInfo.isFirstLine(), &fallbackFonts, &glyphOverflow) + hyphenWidth);
if (!fallbackFonts.isEmpty()) {
ASSERT(run->m_box->isText());
- GlyphOverflowAndFallbackFontsMap::iterator it = textBoxDataMap.add(toInlineTextBox(run->m_box), make_pair(Vector<const SimpleFontData*>(), GlyphOverflow())).first;
+ GlyphOverflowAndFallbackFontsMap::iterator it = textBoxDataMap.add(toInlineTextBox(run->m_box), make_pair(Vector<const SimpleFontData*>(), GlyphOverflow())).iterator;
ASSERT(it->second.first.isEmpty());
copyToVector(fallbackFonts, it->second.first);
run->m_box->parent()->clearDescendantsHaveSameLineHeightAndBaseline();
}
if ((glyphOverflow.top || glyphOverflow.bottom || glyphOverflow.left || glyphOverflow.right)) {
ASSERT(run->m_box->isText());
- GlyphOverflowAndFallbackFontsMap::iterator it = textBoxDataMap.add(toInlineTextBox(run->m_box), make_pair(Vector<const SimpleFontData*>(), GlyphOverflow())).first;
+ GlyphOverflowAndFallbackFontsMap::iterator it = textBoxDataMap.add(toInlineTextBox(run->m_box), make_pair(Vector<const SimpleFontData*>(), GlyphOverflow())).iterator;
it->second.second = glyphOverflow;
run->m_box->clearKnownToHaveNoOverflow();
}
@@ -1096,8 +1096,8 @@ public:
void updateRepaintRangeFromBox(RootInlineBox* box, LayoutUnit paginationDelta = 0)
{
m_usesRepaintBounds = true;
- m_repaintLogicalTop = min(m_repaintLogicalTop, box->logicalTopVisualOverflow() + min(paginationDelta, zeroLayoutUnit));
- m_repaintLogicalBottom = max(m_repaintLogicalBottom, box->logicalBottomVisualOverflow() + max(paginationDelta, zeroLayoutUnit));
+ m_repaintLogicalTop = min(m_repaintLogicalTop, box->logicalTopVisualOverflow() + min(paginationDelta, ZERO_LAYOUT_UNIT));
+ m_repaintLogicalBottom = max(m_repaintLogicalBottom, box->logicalBottomVisualOverflow() + max(paginationDelta, ZERO_LAYOUT_UNIT));
}
bool endLineMatched() const { return m_endLineMatched; }
@@ -1109,8 +1109,8 @@ public:
LineInfo& lineInfo() { return m_lineInfo; }
const LineInfo& lineInfo() const { return m_lineInfo; }
- int endLineLogicalTop() const { return m_endLineLogicalTop; }
- void setEndLineLogicalTop(int logicalTop) { m_endLineLogicalTop = logicalTop; }
+ LayoutUnit endLineLogicalTop() const { return m_endLineLogicalTop; }
+ void setEndLineLogicalTop(LayoutUnit logicalTop) { m_endLineLogicalTop = logicalTop; }
RootInlineBox* endLine() const { return m_endLine; }
void setEndLine(RootInlineBox* line) { m_endLine = line; }
@@ -1129,7 +1129,7 @@ private:
RootInlineBox* m_endLine;
LineInfo m_lineInfo;
unsigned m_floatIndex;
- int m_endLineLogicalTop;
+ LayoutUnit m_endLineLogicalTop;
bool m_endLineMatched;
bool m_checkForFloatsFromLastLine;
@@ -1171,8 +1171,7 @@ void RenderBlock::layoutRunsAndFloats(LineLayoutState& layoutState, bool hasInli
// determineStartPosition can change the fullLayout flag we have to do this here. Failure to call
// determineStartPosition first will break fast/repaint/line-flow-with-floats-9.html.
if (layoutState.isFullLayout() && hasInlineChild && !selfNeedsLayout()) {
- setNeedsLayout(true, false); // Mark ourselves as needing a full layout. This way we'll repaint like
- // we're supposed to.
+ setNeedsLayout(true, MarkOnlyThis); // Mark as needing a full layout to force us to repaint.
RenderView* v = view();
if (v && !v->doingFullRepaint() && hasLayer()) {
// Because we waited until we were already inside layout to discover
@@ -1400,19 +1399,19 @@ void RenderBlock::linkToEndLineIfNeeded(LineLayoutState& layoutState)
// This has to be done before adding in the bottom border/padding, or the float will
// include the padding incorrectly. -dwh
if (layoutState.checkForFloatsFromLastLine()) {
- int bottomVisualOverflow = lastRootBox()->logicalBottomVisualOverflow();
- int bottomLayoutOverflow = lastRootBox()->logicalBottomLayoutOverflow();
+ LayoutUnit bottomVisualOverflow = lastRootBox()->logicalBottomVisualOverflow();
+ LayoutUnit bottomLayoutOverflow = lastRootBox()->logicalBottomLayoutOverflow();
TrailingFloatsRootInlineBox* trailingFloatsLineBox = new (renderArena()) TrailingFloatsRootInlineBox(this);
m_lineBoxes.appendLineBox(trailingFloatsLineBox);
trailingFloatsLineBox->setConstructed();
GlyphOverflowAndFallbackFontsMap textBoxDataMap;
VerticalPositionCache verticalPositionCache;
- int blockLogicalHeight = logicalHeight();
+ LayoutUnit blockLogicalHeight = logicalHeight();
trailingFloatsLineBox->alignBoxesInBlockDirection(blockLogicalHeight, textBoxDataMap, verticalPositionCache);
trailingFloatsLineBox->setLineTopBottomPositions(blockLogicalHeight, blockLogicalHeight, blockLogicalHeight, blockLogicalHeight);
trailingFloatsLineBox->setPaginatedLineWidth(availableLogicalWidthForContent(blockLogicalHeight));
- IntRect logicalLayoutOverflow(0, blockLogicalHeight, 1, bottomLayoutOverflow - blockLogicalHeight);
- IntRect logicalVisualOverflow(0, blockLogicalHeight, 1, bottomVisualOverflow - blockLogicalHeight);
+ LayoutRect logicalLayoutOverflow(0, blockLogicalHeight, 1, bottomLayoutOverflow - blockLogicalHeight);
+ LayoutRect logicalVisualOverflow(0, blockLogicalHeight, 1, bottomVisualOverflow - blockLogicalHeight);
trailingFloatsLineBox->setOverflowFromLogicalRects(logicalLayoutOverflow, logicalVisualOverflow, trailingFloatsLineBox->lineTop(), trailingFloatsLineBox->lineBottom());
}
@@ -1487,11 +1486,11 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, LayoutUnit& repain
RenderBox* box = toRenderBox(o);
if (relayoutChildren || box->hasRelativeDimensions())
- o->setChildNeedsLayout(true, false);
+ o->setChildNeedsLayout(true, MarkOnlyThis);
// If relayoutChildren is set and the child has percentage padding or an embedded content box, we also need to invalidate the childs pref widths.
if (relayoutChildren && box->needsPreferredWidthsRecalculation())
- o->setPreferredLogicalWidthsDirty(true, false);
+ o->setPreferredLogicalWidthsDirty(true, MarkOnlyThis);
if (o->isPositioned())
o->containingBlock()->insertPositionedObject(box);
@@ -1517,7 +1516,7 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, LayoutUnit& repain
// Expand the last line to accommodate Ruby and emphasis marks.
int lastLineAnnotationsAdjustment = 0;
if (lastRootBox()) {
- int lowestAllowedPosition = max(lastRootBox()->lineBottom(), logicalHeight() + paddingAfter());
+ LayoutUnit lowestAllowedPosition = max(lastRootBox()->lineBottom(), logicalHeight() + paddingAfter());
if (!style()->isFlippedLinesWritingMode())
lastLineAnnotationsAdjustment = lastRootBox()->computeUnderAnnotationAdjustment(lowestAllowedPosition);
else
@@ -1557,7 +1556,7 @@ void RenderBlock::checkFloatsInCleanLine(RootInlineBox* line, Vector<FloatWithRe
LayoutUnit floatTop = isHorizontalWritingMode() ? floats[floatIndex].rect.y() : floats[floatIndex].rect.x();
LayoutUnit floatHeight = isHorizontalWritingMode() ? max(floats[floatIndex].rect.height(), newSize.height())
: max(floats[floatIndex].rect.width(), newSize.width());
- floatHeight = min(floatHeight, numeric_limits<LayoutUnit>::max() - floatTop);
+ floatHeight = min(floatHeight, MAX_LAYOUT_UNIT - floatTop);
line->markDirty();
markLinesDirtyInBlockRange(line->lineBottomWithLeading(), floatTop + floatHeight, line);
floats[floatIndex].rect.setSize(newSize);
@@ -1758,7 +1757,7 @@ bool RenderBlock::checkPaginationAndFloatsAtEndLine(LineLayoutState& layoutState
while (RootInlineBox* nextLine = lastLine->nextRootBox())
lastLine = nextLine;
- LayoutUnit logicalBottom = lastLine->lineBottomWithLeading() + abs(lineDelta);
+ LayoutUnit logicalBottom = lastLine->lineBottomWithLeading() + absoluteValue(lineDelta);
const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
FloatingObjectSetIterator end = floatingObjectSet.end();
@@ -1948,6 +1947,7 @@ static inline float textWidth(RenderText* text, unsigned from, unsigned len, con
run.setCharactersLength(text->textLength() - from);
ASSERT(run.charactersLength() >= run.length());
+ run.setCharacterScanForCodePath(!text->canUseSimpleFontCodePath());
run.setAllowTabs(!collapseWhiteSpace);
run.setXPos(xPos);
return font.width(run);
@@ -2666,7 +2666,7 @@ InlineIterator RenderBlock::LineBreaker::nextLineBreak(InlineBidiResolver& resol
void RenderBlock::addOverflowFromInlineChildren()
{
- LayoutUnit endPadding = hasOverflowClip() ? paddingEnd() : zeroLayoutUnit;
+ 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())
endPadding = 1;
@@ -2690,8 +2690,8 @@ void RenderBlock::checkLinesForTextOverflow()
const Font& font = style()->font();
DEFINE_STATIC_LOCAL(AtomicString, ellipsisStr, (&horizontalEllipsis, 1));
const Font& firstLineFont = firstLineStyle()->font();
- LayoutUnit firstLineEllipsisWidth = firstLineFont.width(constructTextRun(this, firstLineFont, &horizontalEllipsis, 1, firstLineStyle()));
- LayoutUnit ellipsisWidth = (font == firstLineFont) ? firstLineEllipsisWidth : font.width(constructTextRun(this, font, &horizontalEllipsis, 1, style()));
+ int firstLineEllipsisWidth = firstLineFont.width(constructTextRun(this, firstLineFont, &horizontalEllipsis, 1, firstLineStyle()));
+ int ellipsisWidth = (font == firstLineFont) ? firstLineEllipsisWidth : font.width(constructTextRun(this, font, &horizontalEllipsis, 1, style()));
// For LTR text truncation, we want to get the right edge of our padding box, and then we want to see
// if the right edge of a line box exceeds that. For RTL, we use the left edge of the padding box and
@@ -2750,7 +2750,7 @@ bool RenderBlock::positionNewFloatOnLine(FloatingObject* newFloat, FloatingObjec
RenderBox* o = f->m_renderer;
setLogicalTopForChild(o, logicalTopForChild(o) + marginBeforeForChild(o) + paginationStrut);
if (o->isRenderBlock())
- toRenderBlock(o)->setChildNeedsLayout(true, false);
+ toRenderBlock(o)->setChildNeedsLayout(true, MarkOnlyThis);
o->layoutIfNeeded();
// Save the old logical top before calling removePlacedObject which will set
// isPlaced to false. Otherwise it will trigger an assert in logicalTopForFloat.
diff --git a/Source/WebCore/rendering/RenderBox.cpp b/Source/WebCore/rendering/RenderBox.cpp
index bafdc376a..b906ec94d 100644
--- a/Source/WebCore/rendering/RenderBox.cpp
+++ b/Source/WebCore/rendering/RenderBox.cpp
@@ -253,19 +253,25 @@ void RenderBox::willBeDestroyed()
if (styleToUse && (styleToUse->logicalHeight().isPercent() || styleToUse->logicalMinHeight().isPercent() || styleToUse->logicalMaxHeight().isPercent()))
RenderBlock::removePercentHeightDescendant(this);
- // If this renderer is owning renderer for the frameview's custom scrollbars,
- // we need to clear it from the scrollbar. See webkit bug 64737.
- if (styleToUse && styleToUse->hasPseudoStyle(SCROLLBAR) && frame() && frame()->view())
- frame()->view()->clearOwningRendererForCustomScrollbars(this);
+ if (styleToUse) {
+ if (RenderView* view = this->view()) {
+ if (FrameView* frameView = view->frameView()) {
+ // If this renderer is owning renderer for the FrameView's custom scrollbars,
+ // we need to clear it from the scrollbar. See webkit bug 64737.
+ if (styleToUse->hasPseudoStyle(SCROLLBAR))
+ frameView->clearOwningRendererForCustomScrollbars(this);
+
+ if (styleToUse->position() == FixedPosition)
+ frameView->removeFixedObject();
+ }
+ }
+ }
// If the following assertion fails, logicalHeight()/logicalMinHeight()/
// logicalMaxHeight() values are changed from a percent value to a non-percent
// value during laying out. It causes a use-after-free bug.
ASSERT(!RenderBlock::hasPercentHeightDescendant(this));
- if (hasOverflowClip() && everHadLayout() && !hasLayer())
- clearCachedSizeForOverflowClip();
-
RenderBoxModelObject::willBeDestroyed();
}
@@ -363,7 +369,7 @@ void RenderBox::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle
// If our zoom factor changes and we have a defined scrollLeft/Top, we need to adjust that value into the
// new zoomed coordinate space.
- if (hasOverflowClipWithLayer() && oldStyle && newStyle && oldStyle->effectiveZoom() != newStyle->effectiveZoom()) {
+ if (hasOverflowClip() && oldStyle && newStyle && oldStyle->effectiveZoom() != newStyle->effectiveZoom()) {
if (int left = layer()->scrollXOffset()) {
left = (left / oldStyle->effectiveZoom()) * newStyle->effectiveZoom();
layer()->scrollToXOffset(left);
@@ -419,7 +425,7 @@ void RenderBox::updateBoxModelInfoFromStyle()
setHasBoxDecorations(true);
setPositioned(styleToUse->isPositioned());
- setFloating(styleToUse->isFloating() && (!isPositioned() || styleToUse->floating() == PositionedFloat));
+ setFloating(!isPositioned() && styleToUse->isFloating());
// We also handle <body> and <html>, whose overflow applies to the viewport.
if (styleToUse->overflowX() != OVISIBLE && !isRootObject && (isRenderBlock() || isTableRow() || isTableSection())) {
@@ -466,10 +472,6 @@ void RenderBox::layout()
child = child->nextSibling();
}
statePusher.pop();
-
- if (hasOverflowClip() && !hasLayer())
- updateCachedSizeForOverflowClip();
-
setNeedsLayout(false);
}
@@ -487,53 +489,53 @@ LayoutUnit RenderBox::clientHeight() const
int RenderBox::pixelSnappedClientWidth() const
{
- return snapSizeToPixel(clientWidth(), clientLeft());
+ return snapSizeToPixel(clientWidth(), x() + clientLeft());
}
int RenderBox::pixelSnappedClientHeight() const
{
- return snapSizeToPixel(clientHeight(), clientTop());
+ return snapSizeToPixel(clientHeight(), y() + clientTop());
}
int RenderBox::scrollWidth() const
{
- if (hasOverflowClipWithLayer())
+ if (hasOverflowClip())
return layer()->scrollWidth();
// For objects with visible overflow, this matches IE.
// FIXME: Need to work right with writing modes.
if (style()->isLeftToRightDirection())
- return max(clientWidth(), maxXLayoutOverflow() - borderLeft());
- return clientWidth() - min(0, minXLayoutOverflow() - borderLeft());
+ return snapSizeToPixel(max(clientWidth(), maxXLayoutOverflow() - borderLeft()), clientLeft());
+ return clientWidth() - min(ZERO_LAYOUT_UNIT, minXLayoutOverflow() - borderLeft());
}
int RenderBox::scrollHeight() const
{
- if (hasOverflowClipWithLayer())
+ if (hasOverflowClip())
return layer()->scrollHeight();
// For objects with visible overflow, this matches IE.
// FIXME: Need to work right with writing modes.
- return max(pixelSnappedClientHeight(), maxYLayoutOverflow() - borderTop());
+ return snapSizeToPixel(max(clientHeight(), maxYLayoutOverflow() - borderTop()), clientTop());
}
int RenderBox::scrollLeft() const
{
- return hasOverflowClipWithLayer() ? layer()->scrollXOffset() : 0;
+ return hasOverflowClip() ? layer()->scrollXOffset() : 0;
}
int RenderBox::scrollTop() const
{
- return hasOverflowClipWithLayer() ? layer()->scrollYOffset() : 0;
+ return hasOverflowClip() ? layer()->scrollYOffset() : 0;
}
void RenderBox::setScrollLeft(int newLeft)
{
- if (hasOverflowClipWithLayer())
+ if (hasOverflowClip())
layer()->scrollToXOffset(newLeft, RenderLayer::ScrollOffsetClamped);
}
void RenderBox::setScrollTop(int newTop)
{
- if (hasOverflowClipWithLayer())
+ if (hasOverflowClip())
layer()->scrollToYOffset(newTop, RenderLayer::ScrollOffsetClamped);
}
@@ -554,9 +556,9 @@ void RenderBox::updateLayerTransform()
layer()->updateTransform();
}
-LayoutRect RenderBox::absoluteContentBox() const
+IntRect RenderBox::absoluteContentBox() const
{
- LayoutRect rect = contentBoxRect();
+ IntRect rect = pixelSnappedIntRect(contentBoxRect());
FloatPoint absPos = localToAbsolute(FloatPoint());
rect.move(absPos.x(), absPos.y());
return rect;
@@ -622,9 +624,10 @@ int RenderBox::reflectionOffset() const
{
if (!style()->boxReflect())
return 0;
+ RenderView* renderView = view();
if (style()->boxReflect()->direction() == ReflectionLeft || style()->boxReflect()->direction() == ReflectionRight)
- return style()->boxReflect()->offset().calcValue(borderBoxRect().width());
- return style()->boxReflect()->offset().calcValue(borderBoxRect().height());
+ return valueForLength(style()->boxReflect()->offset(), borderBoxRect().width(), renderView);
+ return valueForLength(style()->boxReflect()->offset(), borderBoxRect().height(), renderView);
}
LayoutRect RenderBox::reflectedRect(const LayoutRect& r) const
@@ -658,13 +661,13 @@ bool RenderBox::fixedElementLaysOutRelativeToFrame(Frame* frame, FrameView* fram
bool RenderBox::includeVerticalScrollbarSize() const
{
- return hasOverflowClipWithLayer() && !layer()->hasOverlayScrollbars()
+ return hasOverflowClip() && !layer()->hasOverlayScrollbars()
&& (style()->overflowY() == OSCROLL || style()->overflowY() == OAUTO);
}
bool RenderBox::includeHorizontalScrollbarSize() const
{
- return hasOverflowClipWithLayer() && !layer()->hasOverlayScrollbars()
+ return hasOverflowClip() && !layer()->hasOverlayScrollbars()
&& (style()->overflowX() == OSCROLL || style()->overflowX() == OAUTO);
}
@@ -756,56 +759,15 @@ bool RenderBox::needsPreferredWidthsRecalculation() const
IntSize RenderBox::scrolledContentOffset() const
{
ASSERT(hasOverflowClip());
-
- if (hasLayer())
- return layer()->scrolledContentOffset();
-
- // If we have no layer, it means that we have no overflowing content as we lazily
- // allocate it on demand. Thus we don't have any scroll offset.
- ASSERT(!requiresLayerForOverflowClip());
- return LayoutSize();
-}
-
-typedef HashMap<const RenderBox*, LayoutSize> RendererSizeCache;
-static RendererSizeCache& cachedSizeForOverflowClipMap()
-{
- DEFINE_STATIC_LOCAL(RendererSizeCache, cachedSizeForOverflowClipMap, ());
- return cachedSizeForOverflowClipMap;
+ ASSERT(hasLayer());
+ return layer()->scrolledContentOffset();
}
-IntSize RenderBox::cachedSizeForOverflowClip() const
+LayoutSize RenderBox::cachedSizeForOverflowClip() const
{
ASSERT(hasOverflowClip());
- if (hasLayer())
- return layer()->size();
-
- ASSERT(!requiresLayerForOverflowClip());
- RendererSizeCache::iterator it = cachedSizeForOverflowClipMap().find(this);
- if (it == cachedSizeForOverflowClipMap().end())
- return LayoutSize();
-
- return it->second;
-}
-
-void RenderBox::updateCachedSizeForOverflowClip()
-{
- ASSERT(hasOverflowClip());
- ASSERT(!requiresLayerForOverflowClip());
- ASSERT(!hasLayer());
-
- cachedSizeForOverflowClipMap().set(this, size());
-}
-
-void RenderBox::clearCachedSizeForOverflowClip()
-{
- ASSERT(hasOverflowClip());
- ASSERT(!requiresLayerForOverflowClip());
- ASSERT(!hasLayer());
-
- // FIXME: We really would like to enable this ASSERT. However the current updateScrollInfoAfterLayout
- // is not bullet-proof and it triggers in non-obvious ways under NRWT.
- // ASSERT(cachedSizeForOverflowClipMap().contains(this));
- cachedSizeForOverflowClipMap().remove(this);
+ ASSERT(hasLayer());
+ return layer()->size();
}
LayoutUnit RenderBox::minPreferredLogicalWidth() const
@@ -991,7 +953,7 @@ void RenderBox::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint& pai
// To avoid the background color bleeding out behind the border, we'll render background and border
// into a transparency layer, and then clip that in one go (which requires setting up the clip before
// beginning the layer).
- RoundedRect border = style()->getRoundedBorderFor(paintRect);
+ RoundedRect border = style()->getRoundedBorderFor(paintRect, view());
stateSaver.save();
paintInfo.context->addRoundedRectClip(border);
paintInfo.context->beginTransparencyLayer(1);
@@ -999,17 +961,18 @@ void RenderBox::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint& pai
// If we have a native theme appearance, paint that before painting our background.
// The theme will tell us whether or not we should also paint the CSS background.
- bool themePainted = style()->hasAppearance() && !theme()->paint(this, paintInfo, paintRect);
+ IntRect snappedPaintRect(pixelSnappedIntRect(paintRect));
+ bool themePainted = style()->hasAppearance() && !theme()->paint(this, paintInfo, snappedPaintRect);
if (!themePainted) {
paintBackground(paintInfo, paintRect, bleedAvoidance);
if (style()->hasAppearance())
- theme()->paintDecorations(this, paintInfo, pixelSnappedIntRect(paintRect));
+ theme()->paintDecorations(this, paintInfo, snappedPaintRect);
}
paintBoxShadow(paintInfo, paintRect, style(), Inset);
// The theme will tell us whether or not we should also paint the CSS border.
- if ((!style()->hasAppearance() || (!themePainted && theme()->paintBorderOnly(this, paintInfo, pixelSnappedIntRect(paintRect)))) && style()->hasBorder())
+ if ((!style()->hasAppearance() || (!themePainted && theme()->paintBorderOnly(this, paintInfo, snappedPaintRect))) && style()->hasBorder())
paintBorder(paintInfo, paintRect, style(), bleedAvoidance);
if (bleedAvoidance == BackgroundBleedUseTransparencyLayer)
@@ -1049,11 +1012,12 @@ void RenderBox::paintMaskImages(const PaintInfo& paintInfo, const LayoutRect& pa
// Figure out if we need to push a transparency layer to render our mask.
bool pushTransparencyLayer = false;
bool compositedMask = hasLayer() && layer()->hasCompositedMask();
+ bool flattenCompositingLayers = view()->frameView() && view()->frameView()->paintBehavior() & PaintBehaviorFlattenCompositingLayers;
CompositeOperator compositeOp = CompositeSourceOver;
bool allMaskImagesLoaded = true;
- if (!compositedMask) {
+ if (!compositedMask || flattenCompositingLayers) {
pushTransparencyLayer = true;
StyleImage* maskBoxImage = style()->maskBoxImage().image();
const FillLayer* maskLayers = style()->maskLayers();
@@ -1158,7 +1122,7 @@ void RenderBox::imageChanged(WrappedImagePtr image, const IntRect*)
#if USE(ACCELERATED_COMPOSITING)
if (hasLayer() && layer()->hasCompositedMask() && layersUseImage(image, style()->maskLayers()))
- layer()->contentChanged(RenderLayer::MaskImageChanged);
+ layer()->contentChanged(MaskImageChanged);
#endif
}
@@ -1237,7 +1201,7 @@ bool RenderBox::pushContentsClip(PaintInfo& paintInfo, const LayoutPoint& accumu
return false;
bool isControlClip = hasControlClip();
- bool isOverflowClip = hasOverflowClip() && !hasSelfPaintingLayer();
+ bool isOverflowClip = hasOverflowClip() && !layer()->isSelfPaintingLayer();
if (!isControlClip && !isOverflowClip)
return false;
@@ -1259,7 +1223,7 @@ bool RenderBox::pushContentsClip(PaintInfo& paintInfo, const LayoutPoint& accumu
void RenderBox::popContentsClip(PaintInfo& paintInfo, PaintPhase originalPhase, const LayoutPoint& accumulatedOffset)
{
- ASSERT(hasControlClip() || (hasOverflowClip() && !hasSelfPaintingLayer()));
+ ASSERT(hasControlClip() || (hasOverflowClip() && !layer()->isSelfPaintingLayer()));
paintInfo.context->restore();
if (originalPhase == PaintPhaseOutline) {
@@ -1292,9 +1256,10 @@ LayoutRect RenderBox::clipRect(const LayoutPoint& location, RenderRegion* region
{
LayoutRect borderBoxRect = borderBoxRectInRegion(region);
LayoutRect clipRect = LayoutRect(borderBoxRect.location() + location, borderBoxRect.size());
+ RenderView* renderView = view();
if (!style()->clipLeft().isAuto()) {
- LayoutUnit c = style()->clipLeft().calcValue(borderBoxRect.width());
+ LayoutUnit c = valueForLength(style()->clipLeft(), borderBoxRect.width(), renderView);
clipRect.move(c, 0);
clipRect.contract(c, 0);
}
@@ -1303,16 +1268,16 @@ LayoutRect RenderBox::clipRect(const LayoutPoint& location, RenderRegion* region
// from the left and top edges. Therefore it's better to avoid constraining to smaller widths and heights.
if (!style()->clipRight().isAuto())
- clipRect.contract(width() - style()->clipRight().calcValue(width()), 0);
+ clipRect.contract(width() - valueForLength(style()->clipRight(), width(), renderView), 0);
if (!style()->clipTop().isAuto()) {
- LayoutUnit c = style()->clipTop().calcValue(borderBoxRect.height());
+ LayoutUnit c = valueForLength(style()->clipTop(), borderBoxRect.height(), renderView);
clipRect.move(0, c);
clipRect.contract(0, c);
}
if (!style()->clipBottom().isAuto())
- clipRect.contract(0, height() - style()->clipBottom().calcValue(height()));
+ clipRect.contract(0, height() - valueForLength(style()->clipBottom(), height(), renderView));
return clipRect;
}
@@ -1323,7 +1288,7 @@ LayoutUnit RenderBox::shrinkLogicalWidthToAvoidFloats(LayoutUnit childMarginStar
LayoutUnit logicalTopPosition = logicalTop();
LayoutUnit adjustedPageOffsetForContainingBlock = offsetFromLogicalTopOfFirstPage - logicalTop();
if (region) {
- LayoutUnit offsetFromLogicalTopOfRegion = region ? region->offsetFromLogicalTopOfFirstPage() - offsetFromLogicalTopOfFirstPage : zeroLayoutUnit;
+ LayoutUnit offsetFromLogicalTopOfRegion = region ? region->offsetFromLogicalTopOfFirstPage() - offsetFromLogicalTopOfFirstPage : ZERO_LAYOUT_UNIT;
logicalTopPosition = max(logicalTopPosition, logicalTopPosition + offsetFromLogicalTopOfRegion);
containingBlockRegion = cb->clampToStartAndEndRegions(region);
}
@@ -1378,6 +1343,20 @@ LayoutUnit RenderBox::containingBlockLogicalWidthForContentInRegion(RenderRegion
return max<LayoutUnit>(0, result - (cb->logicalWidth() - boxInfo->logicalWidth()));
}
+LayoutUnit RenderBox::containingBlockAvailableLineWidthInRegion(RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage) const
+{
+ RenderBlock* cb = containingBlock();
+ RenderRegion* containingBlockRegion = 0;
+ LayoutUnit logicalTopPosition = logicalTop();
+ LayoutUnit adjustedPageOffsetForContainingBlock = offsetFromLogicalTopOfFirstPage - logicalTop();
+ if (region) {
+ LayoutUnit offsetFromLogicalTopOfRegion = region ? region->offsetFromLogicalTopOfFirstPage() - offsetFromLogicalTopOfFirstPage : ZERO_LAYOUT_UNIT;
+ logicalTopPosition = max(logicalTopPosition, logicalTopPosition + offsetFromLogicalTopOfRegion);
+ containingBlockRegion = cb->clampToStartAndEndRegions(region);
+ }
+ return cb->availableLogicalWidthForLine(logicalTopPosition, false, containingBlockRegion, adjustedPageOffsetForContainingBlock);
+}
+
LayoutUnit RenderBox::perpendicularContainingBlockLogicalHeight() const
{
RenderBlock* cb = containingBlock();
@@ -1396,7 +1375,7 @@ LayoutUnit RenderBox::perpendicularContainingBlockLogicalHeight() const
return cb->computeContentBoxLogicalHeight(logicalHeightLength.value());
}
-void RenderBox::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed, bool useTransforms, TransformState& transformState, bool* wasFixed) const
+void RenderBox::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed, bool useTransforms, TransformState& transformState, ApplyContainerFlipOrNot, bool* wasFixed) const
{
if (repaintContainer == this)
return;
@@ -1450,11 +1429,11 @@ void RenderBox::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool
// Transform from render flow coordinates into region coordinates.
RenderRegion* region = toRenderFlowThread(o)->mapFromFlowToRegion(transformState);
if (region)
- region->mapLocalToContainer(region->containerForRepaint(), fixed, useTransforms, transformState, wasFixed);
+ region->mapLocalToContainer(region->containerForRepaint(), fixed, useTransforms, transformState, DoNotApplyContainerFlip, wasFixed);
return;
}
- o->mapLocalToContainer(repaintContainer, fixed, useTransforms, transformState, wasFixed);
+ o->mapLocalToContainer(repaintContainer, fixed, useTransforms, transformState, DoNotApplyContainerFlip, wasFixed);
}
void RenderBox::mapAbsoluteToLocalPoint(bool fixed, bool useTransforms, TransformState& transformState) const
@@ -1533,7 +1512,7 @@ void RenderBox::positionLineBox(InlineBox* box)
RootInlineBox* root = box->root();
root->block()->setStaticInlinePositionForChild(this, root->lineTopWithLeading(), roundedLayoutUnit(box->logicalLeft()));
if (style()->hasStaticInlinePosition(box->isHorizontal()))
- setChildNeedsLayout(true, false); // Just go ahead and mark the positioned object as needing layout, so it will update its position properly.
+ setChildNeedsLayout(true, MarkOnlyThis); // Just go ahead and mark the positioned object as needing layout, so it will update its position properly.
} else {
// Our object was a block originally, so we make our normal flow position be
// just below the line box (as though all the inlines that came before us got
@@ -1541,7 +1520,7 @@ void RenderBox::positionLineBox(InlineBox* box)
// in flow). This value was cached in the y() of the box.
layer()->setStaticBlockPosition(box->logicalTop());
if (style()->hasStaticBlockPosition(box->isHorizontal()))
- setChildNeedsLayout(true, false); // Just go ahead and mark the positioned object as needing layout, so it will update its position properly.
+ setChildNeedsLayout(true, MarkOnlyThis); // Just go ahead and mark the positioned object as needing layout, so it will update its position properly.
}
// Nuke the box.
@@ -1641,18 +1620,6 @@ void RenderBox::computeRectForRepaint(RenderBoxModelObject* repaintContainer, La
if (isWritingModeRoot() && !isPositioned())
flipForWritingMode(rect);
-#if ENABLE(CSS_FILTERS)
- if (styleToUse->hasFilterOutsets()) {
- LayoutUnit topOutset;
- LayoutUnit rightOutset;
- LayoutUnit bottomOutset;
- LayoutUnit leftOutset;
- styleToUse->filter().getOutsets(topOutset, rightOutset, bottomOutset, leftOutset);
- rect.move(-leftOutset, -topOutset);
- rect.expand(leftOutset + rightOutset, topOutset + bottomOutset);
- }
-#endif
-
LayoutPoint topLeft = rect.location();
topLeft.move(locationOffset());
@@ -1779,10 +1746,11 @@ void RenderBox::computeLogicalWidthInRegion(RenderRegion* region, LayoutUnit off
if (isInline() && !isInlineBlockOrInlineTable()) {
// just calculate margins
- setMarginStart(styleToUse->marginStart().calcMinValue(containerLogicalWidth));
- setMarginEnd(styleToUse->marginEnd().calcMinValue(containerLogicalWidth));
+ RenderView* renderView = view();
+ setMarginStart(minimumValueForLength(styleToUse->marginStart(), containerLogicalWidth, renderView));
+ setMarginEnd(minimumValueForLength(styleToUse->marginEnd(), containerLogicalWidth, renderView));
if (treatAsReplaced)
- setLogicalWidth(max<LayoutUnit>(logicalWidthLength.calcFloatValue(0) + borderAndPaddingLogicalWidth(), minPreferredLogicalWidth()));
+ setLogicalWidth(max<LayoutUnit>(floatValueForLength(logicalWidthLength, 0) + borderAndPaddingLogicalWidth(), minPreferredLogicalWidth()));
return;
}
@@ -1817,12 +1785,17 @@ void RenderBox::computeLogicalWidthInRegion(RenderRegion* region, LayoutUnit off
}
// Margin calculations.
- if (logicalWidthLength.isAuto() || hasPerpendicularContainingBlock) {
- setMarginStart(styleToUse->marginStart().calcMinValue(containerLogicalWidth));
- setMarginEnd(styleToUse->marginEnd().calcMinValue(containerLogicalWidth));
- } else
- computeInlineDirectionMargins(cb, containerLogicalWidth, logicalWidth());
-
+ if (hasPerpendicularContainingBlock || isFloating() || isInline()) {
+ RenderView* renderView = view();
+ setMarginStart(minimumValueForLength(styleToUse->marginStart(), containerLogicalWidth, renderView));
+ setMarginEnd(minimumValueForLength(styleToUse->marginEnd(), containerLogicalWidth, renderView));
+ } else {
+ LayoutUnit containerLogicalWidthForAutoMargins = containerLogicalWidth;
+ if (avoidsFloats() && cb->containsFloats())
+ containerLogicalWidthForAutoMargins = containingBlockAvailableLineWidthInRegion(region, offsetFromLogicalTopOfFirstPage);
+ computeInlineDirectionMargins(cb, containerLogicalWidthForAutoMargins, logicalWidth());
+ }
+
if (!hasPerpendicularContainingBlock && containerLogicalWidth && containerLogicalWidth != (logicalWidth() + marginStart() + marginEnd())
&& !isFloating() && !isInline() && !cb->isFlexibleBoxIncludingDeprecated())
cb->setMarginEndForChild(this, containerLogicalWidth - logicalWidth() - cb->marginStartForChild(this));
@@ -1841,9 +1814,12 @@ LayoutUnit RenderBox::computeLogicalWidthInRegionUsing(LogicalWidthType widthTyp
else
logicalWidth = styleToUse->logicalMaxWidth();
+ ASSERT(!logicalWidth.isUndefined());
+
if (logicalWidth.isIntrinsicOrAuto()) {
- LayoutUnit marginStart = styleToUse->marginStart().calcMinValue(availableLogicalWidth);
- LayoutUnit marginEnd = styleToUse->marginEnd().calcMinValue(availableLogicalWidth);
+ RenderView* renderView = view();
+ LayoutUnit marginStart = minimumValueForLength(styleToUse->marginStart(), availableLogicalWidth, renderView);
+ LayoutUnit marginEnd = minimumValueForLength(styleToUse->marginEnd(), availableLogicalWidth, renderView);
logicalWidthResult = availableLogicalWidth - marginStart - marginEnd;
if (shrinkToAvoidFloats() && cb->containsFloats())
@@ -1854,7 +1830,7 @@ LayoutUnit RenderBox::computeLogicalWidthInRegionUsing(LogicalWidthType widthTyp
logicalWidthResult = min(logicalWidthResult, maxPreferredLogicalWidth());
}
} else // FIXME: If the containing block flow is perpendicular to our direction we need to use the available logical height instead.
- logicalWidthResult = computeBorderBoxLogicalWidth(logicalWidth.calcValue(availableLogicalWidth));
+ logicalWidthResult = computeBorderBoxLogicalWidth(valueForLength(logicalWidth, availableLogicalWidth, view()));
return logicalWidthResult;
}
@@ -1922,11 +1898,12 @@ void RenderBox::computeInlineDirectionMargins(RenderBlock* containingBlock, Layo
const RenderStyle* containingBlockStyle = containingBlock->style();
Length marginStartLength = style()->marginStartUsing(containingBlockStyle);
Length marginEndLength = style()->marginEndUsing(containingBlockStyle);
+ RenderView* renderView = view();
if (isFloating() || isInline()) {
// Inline blocks/tables and floats don't have their margins increased.
- containingBlock->setMarginStartForChild(this, marginStartLength.calcMinValue(containerWidth));
- containingBlock->setMarginEndForChild(this, marginEndLength.calcMinValue(containerWidth));
+ containingBlock->setMarginStartForChild(this, minimumValueForLength(marginStartLength, containerWidth, renderView));
+ containingBlock->setMarginEndForChild(this, minimumValueForLength(marginEndLength, containerWidth, renderView));
return;
}
@@ -1940,7 +1917,7 @@ void RenderBox::computeInlineDirectionMargins(RenderBlock* containingBlock, Layo
// Case Two: The object is being pushed to the start of the containing block's available logical width.
if (marginEndLength.isAuto() && childWidth < containerWidth) {
- containingBlock->setMarginStartForChild(this, marginStartLength.calcValue(containerWidth));
+ containingBlock->setMarginStartForChild(this, valueForLength(marginStartLength, containerWidth, renderView));
containingBlock->setMarginEndForChild(this, containerWidth - childWidth - containingBlock->marginStartForChild(this));
return;
}
@@ -1949,15 +1926,15 @@ void RenderBox::computeInlineDirectionMargins(RenderBlock* containingBlock, Layo
bool pushToEndFromTextAlign = !marginEndLength.isAuto() && ((!containingBlockStyle->isLeftToRightDirection() && containingBlockStyle->textAlign() == WEBKIT_LEFT)
|| (containingBlockStyle->isLeftToRightDirection() && containingBlockStyle->textAlign() == WEBKIT_RIGHT));
if ((marginStartLength.isAuto() && childWidth < containerWidth) || pushToEndFromTextAlign) {
- containingBlock->setMarginEndForChild(this, marginEndLength.calcValue(containerWidth));
+ containingBlock->setMarginEndForChild(this, valueForLength(marginEndLength, containerWidth, renderView));
containingBlock->setMarginStartForChild(this, containerWidth - childWidth - containingBlock->marginEndForChild(this));
return;
}
// Case Four: Either no auto margins, or our width is >= the container width (css2.1, 10.3.3). In that case
// auto margins will just turn into 0.
- containingBlock->setMarginStartForChild(this, marginStartLength.calcMinValue(containerWidth));
- containingBlock->setMarginEndForChild(this, marginEndLength.calcMinValue(containerWidth));
+ containingBlock->setMarginStartForChild(this, minimumValueForLength(marginStartLength, containerWidth, renderView));
+ containingBlock->setMarginEndForChild(this, minimumValueForLength(marginEndLength, containerWidth, renderView));
}
RenderBoxRegionInfo* RenderBox::renderBoxRegionInfo(RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage, RenderBoxRegionInfoFlags cacheFlag) const
@@ -2022,8 +1999,7 @@ RenderBoxRegionInfo* RenderBox::renderBoxRegionInfo(RenderRegion* region, Layout
LayoutUnit logicalLeftOffset = 0;
if (!isPositioned() && avoidsFloats() && cb->containsFloats()) {
- LayoutUnit startPositionDelta = cb->computeStartPositionDeltaForChildAvoidingFloats(this, marginStartInRegion, logicalWidthInRegion,
- region, offsetFromLogicalTopOfFirstPage);
+ LayoutUnit startPositionDelta = cb->computeStartPositionDeltaForChildAvoidingFloats(this, marginStartInRegion, region, offsetFromLogicalTopOfFirstPage);
if (cb->style()->isLeftToRightDirection())
logicalLeftDelta += startPositionDelta;
else
@@ -2152,18 +2128,24 @@ void RenderBox::computeLogicalHeight()
}
}
-LayoutUnit RenderBox::computeLogicalHeightUsing(const Length& h)
+LayoutUnit RenderBox::computeLogicalHeightUsing(const Length& height)
+{
+ LayoutUnit logicalHeight = computeContentLogicalHeightUsing(height);
+ if (logicalHeight != -1)
+ logicalHeight = computeBorderBoxLogicalHeight(logicalHeight);
+ return logicalHeight;
+}
+
+LayoutUnit RenderBox::computeContentLogicalHeightUsing(const Length& height)
{
LayoutUnit logicalHeight = -1;
- if (!h.isAuto()) {
- if (h.isFixed())
- logicalHeight = h.value();
- else if (h.isPercent())
- logicalHeight = computePercentageLogicalHeight(h);
- if (logicalHeight != -1) {
- logicalHeight = computeBorderBoxLogicalHeight(logicalHeight);
- return logicalHeight;
- }
+ if (!height.isAuto()) {
+ if (height.isFixed())
+ logicalHeight = height.value();
+ else if (height.isPercent())
+ logicalHeight = computePercentageLogicalHeight(height);
+ else if (height.isViewportPercentage())
+ logicalHeight = valueForLength(height, 0, view());
}
return logicalHeight;
}
@@ -2241,7 +2223,7 @@ LayoutUnit RenderBox::computePercentageLogicalHeight(const Length& height)
result = cb->computeContentBoxLogicalHeight(cb->availableLogicalHeight());
if (result != -1) {
- result = height.calcValue(result);
+ result = valueForLength(height, result);
if (includeBorderPadding) {
// It is necessary to use the border-box to match WinIE's broken
// box model. This is essential for sizing inside
@@ -2270,13 +2252,18 @@ LayoutUnit RenderBox::computeReplacedLogicalWidthUsing(Length logicalWidth) cons
switch (logicalWidth.type()) {
case Fixed:
return computeContentBoxLogicalWidth(logicalWidth.value());
- case Percent: {
+ case ViewportPercentageWidth:
+ case ViewportPercentageHeight:
+ case ViewportPercentageMin:
+ return computeContentBoxLogicalWidth(valueForLength(logicalWidth, 0, view()));
+ case Percent:
+ case Calculated: {
// FIXME: containingBlockLogicalWidthForContent() is wrong if the replaced element's block-flow is perpendicular to the
// containing block's block-flow.
// https://bugs.webkit.org/show_bug.cgi?id=46496
const LayoutUnit cw = isPositioned() ? containingBlockLogicalWidthForPositioned(toRenderBoxModelObject(container())) : containingBlockLogicalWidthForContent();
if (cw > 0)
- return computeContentBoxLogicalWidth(logicalWidth.calcMinValue(cw));
+ return computeContentBoxLogicalWidth(minimumValueForLength(logicalWidth, cw));
}
// fall through
default:
@@ -2302,6 +2289,7 @@ LayoutUnit RenderBox::computeReplacedLogicalHeightUsing(Length logicalHeight) co
case Fixed:
return computeContentBoxLogicalHeight(logicalHeight.value());
case Percent:
+ case Calculated:
{
RenderObject* cb = isPositioned() ? container() : containingBlock();
while (cb->isAnonymous()) {
@@ -2318,7 +2306,7 @@ LayoutUnit RenderBox::computeReplacedLogicalHeightUsing(Length logicalHeight) co
block->computeLogicalHeight();
LayoutUnit newHeight = block->computeContentBoxLogicalHeight(block->contentHeight());
block->setHeight(oldHeight);
- return computeContentBoxLogicalHeight(logicalHeight.calcValue(newHeight));
+ return computeContentBoxLogicalHeight(valueForLength(logicalHeight, newHeight));
}
// FIXME: availableLogicalHeight() is wrong if the replaced element's block-flow is perpendicular to the
@@ -2339,13 +2327,18 @@ LayoutUnit RenderBox::computeReplacedLogicalHeightUsing(Length logicalHeight) co
// Don't let table cells squeeze percent-height replaced elements
// <http://bugs.webkit.org/show_bug.cgi?id=15359>
availableHeight = max(availableHeight, intrinsicLogicalHeight());
- return logicalHeight.calcValue(availableHeight - borderAndPaddingLogicalHeight());
+ return valueForLength(logicalHeight, availableHeight - borderAndPaddingLogicalHeight());
}
cb = cb->containingBlock();
+ toRenderBlock(cb)->addPercentHeightDescendant(const_cast<RenderBox*>(this));
}
}
- return computeContentBoxLogicalHeight(logicalHeight.calcValue(availableHeight));
+ return computeContentBoxLogicalHeight(valueForLength(logicalHeight, availableHeight));
}
+ case ViewportPercentageWidth:
+ case ViewportPercentageHeight:
+ case ViewportPercentageMin:
+ return computeContentBoxLogicalHeight(valueForLength(logicalHeight, 0, view()));
default:
return intrinsicLogicalHeight();
}
@@ -2379,7 +2372,7 @@ LayoutUnit RenderBox::availableLogicalHeightUsing(const Length& h) const
availableHeight = containingBlockLogicalHeightForPositioned(containingBlock());
else
availableHeight = containingBlock()->availableLogicalHeight();
- return computeContentBoxLogicalHeight(h.calcValue(availableHeight));
+ return computeContentBoxLogicalHeight(valueForLength(h, availableHeight));
}
// FIXME: We can't just check top/bottom here.
@@ -2409,10 +2402,10 @@ void RenderBox::computeBlockDirectionMargins(RenderBlock* containingBlock)
// Margins are calculated with respect to the logical width of
// the containing block (8.3)
LayoutUnit cw = containingBlockLogicalWidthForContent();
-
+ RenderView* renderView = view();
RenderStyle* containingBlockStyle = containingBlock->style();
- containingBlock->setMarginBeforeForChild(this, style()->marginBeforeUsing(containingBlockStyle).calcMinValue(cw));
- containingBlock->setMarginAfterForChild(this, style()->marginAfterUsing(containingBlockStyle).calcMinValue(cw));
+ containingBlock->setMarginBeforeForChild(this, minimumValueForLength(style()->marginBeforeUsing(containingBlockStyle), cw, renderView));
+ containingBlock->setMarginAfterForChild(this, minimumValueForLength(style()->marginAfterUsing(containingBlockStyle), cw, renderView));
}
LayoutUnit RenderBox::containingBlockLogicalWidthForPositioned(const RenderBoxModelObject* containingBlock, RenderRegion* region,
@@ -2735,6 +2728,7 @@ void RenderBox::computePositionedLogicalWidthUsing(Length logicalWidth, const Re
bool logicalWidthIsAuto = logicalWidth.isIntrinsicOrAuto();
bool logicalLeftIsAuto = logicalLeft.isAuto();
bool logicalRightIsAuto = logicalRight.isAuto();
+ RenderView* renderView = view();
if (!logicalLeftIsAuto && !logicalWidthIsAuto && !logicalRightIsAuto) {
/*-----------------------------------------------------------------------*\
@@ -2752,10 +2746,10 @@ void RenderBox::computePositionedLogicalWidthUsing(Length logicalWidth, const Re
// NOTE: It is not necessary to solve for 'right' in the over constrained
// case because the value is not used for any further calculations.
- logicalLeftValue = logicalLeft.calcValue(containerLogicalWidth);
- logicalWidthValue = computeContentBoxLogicalWidth(logicalWidth.calcValue(containerLogicalWidth));
+ logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView);
+ logicalWidthValue = computeContentBoxLogicalWidth(valueForLength(logicalWidth, containerLogicalWidth, renderView));
- const LayoutUnit availableSpace = containerLogicalWidth - (logicalLeftValue + logicalWidthValue + logicalRight.calcValue(containerLogicalWidth) + bordersPlusPadding);
+ const LayoutUnit availableSpace = containerLogicalWidth - (logicalLeftValue + logicalWidthValue + valueForLength(logicalRight, containerLogicalWidth, renderView) + bordersPlusPadding);
// Margins are now the only unknown
if (marginLogicalLeft.isAuto() && marginLogicalRight.isAuto()) {
@@ -2776,16 +2770,16 @@ void RenderBox::computePositionedLogicalWidthUsing(Length logicalWidth, const Re
}
} else if (marginLogicalLeft.isAuto()) {
// Solve for left margin
- marginLogicalRightValue = marginLogicalRight.calcValue(containerLogicalWidth);
+ marginLogicalRightValue = valueForLength(marginLogicalRight, containerLogicalWidth, renderView);
marginLogicalLeftValue = availableSpace - marginLogicalRightValue;
} else if (marginLogicalRight.isAuto()) {
// Solve for right margin
- marginLogicalLeftValue = marginLogicalLeft.calcValue(containerLogicalWidth);
+ marginLogicalLeftValue = valueForLength(marginLogicalLeft, containerLogicalWidth, renderView);
marginLogicalRightValue = availableSpace - marginLogicalLeftValue;
} else {
// Over-constrained, solve for left if direction is RTL
- marginLogicalLeftValue = marginLogicalLeft.calcValue(containerLogicalWidth);
- marginLogicalRightValue = marginLogicalRight.calcValue(containerLogicalWidth);
+ marginLogicalLeftValue = valueForLength(marginLogicalLeft, containerLogicalWidth, renderView);
+ marginLogicalRightValue = valueForLength(marginLogicalRight, containerLogicalWidth, renderView);
// Use the containing block's direction rather than the parent block's
// per CSS 2.1 reference test abspos-non-replaced-width-margin-000.
@@ -2835,8 +2829,8 @@ void RenderBox::computePositionedLogicalWidthUsing(Length logicalWidth, const Re
// because the value is not used for any further calculations.
// Calculate margins, 'auto' margins are ignored.
- marginLogicalLeftValue = marginLogicalLeft.calcMinValue(containerLogicalWidth);
- marginLogicalRightValue = marginLogicalRight.calcMinValue(containerLogicalWidth);
+ marginLogicalLeftValue = minimumValueForLength(marginLogicalLeft, containerLogicalWidth, renderView);
+ marginLogicalRightValue = minimumValueForLength(marginLogicalRight, containerLogicalWidth, renderView);
const LayoutUnit availableSpace = containerLogicalWidth - (marginLogicalLeftValue + marginLogicalRightValue + bordersPlusPadding);
@@ -2844,7 +2838,7 @@ void RenderBox::computePositionedLogicalWidthUsing(Length logicalWidth, const Re
// Use rule/case that applies.
if (logicalLeftIsAuto && logicalWidthIsAuto && !logicalRightIsAuto) {
// RULE 1: (use shrink-to-fit for width, and solve of left)
- LayoutUnit logicalRightValue = logicalRight.calcValue(containerLogicalWidth);
+ LayoutUnit logicalRightValue = valueForLength(logicalRight, containerLogicalWidth, renderView);
// FIXME: would it be better to have shrink-to-fit in one step?
LayoutUnit preferredWidth = maxPreferredLogicalWidth() - bordersPlusPadding;
@@ -2854,7 +2848,7 @@ void RenderBox::computePositionedLogicalWidthUsing(Length logicalWidth, const Re
logicalLeftValue = availableSpace - (logicalWidthValue + logicalRightValue);
} else if (!logicalLeftIsAuto && logicalWidthIsAuto && logicalRightIsAuto) {
// RULE 3: (use shrink-to-fit for width, and no need solve of right)
- logicalLeftValue = logicalLeft.calcValue(containerLogicalWidth);
+ logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView);
// FIXME: would it be better to have shrink-to-fit in one step?
LayoutUnit preferredWidth = maxPreferredLogicalWidth() - bordersPlusPadding;
@@ -2863,16 +2857,16 @@ void RenderBox::computePositionedLogicalWidthUsing(Length logicalWidth, const Re
logicalWidthValue = min(max(preferredMinWidth, availableWidth), preferredWidth);
} else if (logicalLeftIsAuto && !logicalWidthIsAuto && !logicalRightIsAuto) {
// RULE 4: (solve for left)
- logicalWidthValue = computeContentBoxLogicalWidth(logicalWidth.calcValue(containerLogicalWidth));
- logicalLeftValue = availableSpace - (logicalWidthValue + logicalRight.calcValue(containerLogicalWidth));
+ logicalWidthValue = computeContentBoxLogicalWidth(valueForLength(logicalWidth, containerLogicalWidth, renderView));
+ logicalLeftValue = availableSpace - (logicalWidthValue + valueForLength(logicalRight, containerLogicalWidth, renderView));
} else if (!logicalLeftIsAuto && logicalWidthIsAuto && !logicalRightIsAuto) {
// RULE 5: (solve for width)
- logicalLeftValue = logicalLeft.calcValue(containerLogicalWidth);
- logicalWidthValue = availableSpace - (logicalLeftValue + logicalRight.calcValue(containerLogicalWidth));
+ logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView);
+ logicalWidthValue = availableSpace - (logicalLeftValue + valueForLength(logicalRight, containerLogicalWidth, renderView));
} else if (!logicalLeftIsAuto && !logicalWidthIsAuto && logicalRightIsAuto) {
// RULE 6: (no need solve for right)
- logicalLeftValue = logicalLeft.calcValue(containerLogicalWidth);
- logicalWidthValue = computeContentBoxLogicalWidth(logicalWidth.calcValue(containerLogicalWidth));
+ logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView);
+ logicalWidthValue = computeContentBoxLogicalWidth(valueForLength(logicalWidth, containerLogicalWidth, renderView));
}
}
@@ -3068,6 +3062,7 @@ void RenderBox::computePositionedLogicalHeightUsing(Length logicalHeightLength,
bool logicalHeightIsAuto = logicalHeightLength.isAuto();
bool logicalTopIsAuto = logicalTop.isAuto();
bool logicalBottomIsAuto = logicalBottom.isAuto();
+ RenderView* renderView = view();
// Height is never unsolved for tables.
if (isTable()) {
@@ -3087,10 +3082,10 @@ void RenderBox::computePositionedLogicalHeightUsing(Length logicalHeightLength,
// NOTE: It is not necessary to solve for 'bottom' in the over constrained
// case because the value is not used for any further calculations.
- logicalHeightValue = computeContentBoxLogicalHeight(logicalHeightLength.calcValue(containerLogicalHeight));
- logicalTopValue = logicalTop.calcValue(containerLogicalHeight);
+ logicalHeightValue = computeContentBoxLogicalHeight(valueForLength(logicalHeightLength, containerLogicalHeight, renderView));
+ logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView);
- const LayoutUnit availableSpace = containerLogicalHeight - (logicalTopValue + logicalHeightValue + logicalBottom.calcValue(containerLogicalHeight) + bordersPlusPadding);
+ const LayoutUnit availableSpace = containerLogicalHeight - (logicalTopValue + logicalHeightValue + valueForLength(logicalBottom, containerLogicalHeight, renderView) + bordersPlusPadding);
// Margins are now the only unknown
if (marginBefore.isAuto() && marginAfter.isAuto()) {
@@ -3100,16 +3095,16 @@ void RenderBox::computePositionedLogicalHeightUsing(Length logicalHeightLength,
marginAfterValue = availableSpace - marginBeforeValue; // account for odd valued differences
} else if (marginBefore.isAuto()) {
// Solve for top margin
- marginAfterValue = marginAfter.calcValue(containerLogicalHeight);
+ marginAfterValue = valueForLength(marginAfter, containerLogicalHeight, renderView);
marginBeforeValue = availableSpace - marginAfterValue;
} else if (marginAfter.isAuto()) {
// Solve for bottom margin
- marginBeforeValue = marginBefore.calcValue(containerLogicalHeight);
+ marginBeforeValue = valueForLength(marginBefore, containerLogicalHeight, renderView);
marginAfterValue = availableSpace - marginBeforeValue;
} else {
// Over-constrained, (no need solve for bottom)
- marginBeforeValue = marginBefore.calcValue(containerLogicalHeight);
- marginAfterValue = marginAfter.calcValue(containerLogicalHeight);
+ marginBeforeValue = valueForLength(marginBefore, containerLogicalHeight, renderView);
+ marginAfterValue = valueForLength(marginAfter, containerLogicalHeight, renderView);
}
} else {
/*--------------------------------------------------------------------*\
@@ -3138,8 +3133,8 @@ void RenderBox::computePositionedLogicalHeightUsing(Length logicalHeightLength,
// because the value is not used for any further calculations.
// Calculate margins, 'auto' margins are ignored.
- marginBeforeValue = marginBefore.calcMinValue(containerLogicalHeight);
- marginAfterValue = marginAfter.calcMinValue(containerLogicalHeight);
+ marginBeforeValue = minimumValueForLength(marginBefore, containerLogicalHeight, renderView);
+ marginAfterValue = minimumValueForLength(marginAfter, containerLogicalHeight, renderView);
const LayoutUnit availableSpace = containerLogicalHeight - (marginBeforeValue + marginAfterValue + bordersPlusPadding);
@@ -3147,23 +3142,23 @@ void RenderBox::computePositionedLogicalHeightUsing(Length logicalHeightLength,
if (logicalTopIsAuto && logicalHeightIsAuto && !logicalBottomIsAuto) {
// RULE 1: (height is content based, solve of top)
logicalHeightValue = contentLogicalHeight;
- logicalTopValue = availableSpace - (logicalHeightValue + logicalBottom.calcValue(containerLogicalHeight));
+ logicalTopValue = availableSpace - (logicalHeightValue + valueForLength(logicalBottom, containerLogicalHeight, renderView));
} else if (!logicalTopIsAuto && logicalHeightIsAuto && logicalBottomIsAuto) {
// RULE 3: (height is content based, no need solve of bottom)
- logicalTopValue = logicalTop.calcValue(containerLogicalHeight);
+ logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView);
logicalHeightValue = contentLogicalHeight;
} else if (logicalTopIsAuto && !logicalHeightIsAuto && !logicalBottomIsAuto) {
// RULE 4: (solve of top)
- logicalHeightValue = computeContentBoxLogicalHeight(logicalHeightLength.calcValue(containerLogicalHeight));
- logicalTopValue = availableSpace - (logicalHeightValue + logicalBottom.calcValue(containerLogicalHeight));
+ logicalHeightValue = computeContentBoxLogicalHeight(valueForLength(logicalHeightLength, containerLogicalHeight, renderView));
+ logicalTopValue = availableSpace - (logicalHeightValue + valueForLength(logicalBottom, containerLogicalHeight, renderView));
} else if (!logicalTopIsAuto && logicalHeightIsAuto && !logicalBottomIsAuto) {
// RULE 5: (solve of height)
- logicalTopValue = logicalTop.calcValue(containerLogicalHeight);
- logicalHeightValue = max<LayoutUnit>(0, availableSpace - (logicalTopValue + logicalBottom.calcValue(containerLogicalHeight)));
+ logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView);
+ logicalHeightValue = max<LayoutUnit>(0, availableSpace - (logicalTopValue + valueForLength(logicalBottom, containerLogicalHeight, renderView)));
} else if (!logicalTopIsAuto && !logicalHeightIsAuto && logicalBottomIsAuto) {
// RULE 6: (no need solve of bottom)
- logicalHeightValue = computeContentBoxLogicalHeight(logicalHeightLength.calcValue(containerLogicalHeight));
- logicalTopValue = logicalTop.calcValue(containerLogicalHeight);
+ logicalHeightValue = computeContentBoxLogicalHeight(valueForLength(logicalHeightLength, containerLogicalHeight, renderView));
+ logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView);
}
}
@@ -3239,13 +3234,14 @@ void RenderBox::computePositionedLogicalWidthReplaced()
\*-----------------------------------------------------------------------*/
LayoutUnit logicalLeftValue = 0;
LayoutUnit logicalRightValue = 0;
+ RenderView* renderView = view();
if (marginLogicalLeft.isAuto() && marginLogicalRight.isAuto()) {
// 'left' and 'right' cannot be 'auto' due to step 3
ASSERT(!(logicalLeft.isAuto() && logicalRight.isAuto()));
- logicalLeftValue = logicalLeft.calcValue(containerLogicalWidth);
- logicalRightValue = logicalRight.calcValue(containerLogicalWidth);
+ logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView);
+ logicalRightValue = valueForLength(logicalRight, containerLogicalWidth, renderView);
LayoutUnit difference = availableSpace - (logicalLeftValue + logicalRightValue);
if (difference > 0) {
@@ -3268,39 +3264,39 @@ void RenderBox::computePositionedLogicalWidthReplaced()
* that value.
\*-----------------------------------------------------------------------*/
} else if (logicalLeft.isAuto()) {
- marginLogicalLeftAlias = marginLogicalLeft.calcValue(containerLogicalWidth);
- marginLogicalRightAlias = marginLogicalRight.calcValue(containerLogicalWidth);
- logicalRightValue = logicalRight.calcValue(containerLogicalWidth);
+ marginLogicalLeftAlias = valueForLength(marginLogicalLeft, containerLogicalWidth, renderView);
+ marginLogicalRightAlias = valueForLength(marginLogicalRight, containerLogicalWidth, renderView);
+ logicalRightValue = valueForLength(logicalRight, containerLogicalWidth, renderView);
// Solve for 'left'
logicalLeftValue = availableSpace - (logicalRightValue + marginLogicalLeftAlias + marginLogicalRightAlias);
} else if (logicalRight.isAuto()) {
- marginLogicalLeftAlias = marginLogicalLeft.calcValue(containerLogicalWidth);
- marginLogicalRightAlias = marginLogicalRight.calcValue(containerLogicalWidth);
- logicalLeftValue = logicalLeft.calcValue(containerLogicalWidth);
+ marginLogicalLeftAlias = valueForLength(marginLogicalLeft, containerLogicalWidth, renderView);
+ marginLogicalRightAlias = valueForLength(marginLogicalRight, containerLogicalWidth, renderView);
+ logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView);
// Solve for 'right'
logicalRightValue = availableSpace - (logicalLeftValue + marginLogicalLeftAlias + marginLogicalRightAlias);
} else if (marginLogicalLeft.isAuto()) {
- marginLogicalRightAlias = marginLogicalRight.calcValue(containerLogicalWidth);
- logicalLeftValue = logicalLeft.calcValue(containerLogicalWidth);
- logicalRightValue = logicalRight.calcValue(containerLogicalWidth);
+ marginLogicalRightAlias = valueForLength(marginLogicalRight, containerLogicalWidth, renderView);
+ logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView);
+ logicalRightValue = valueForLength(logicalRight, containerLogicalWidth, renderView);
// Solve for 'margin-left'
marginLogicalLeftAlias = availableSpace - (logicalLeftValue + logicalRightValue + marginLogicalRightAlias);
} else if (marginLogicalRight.isAuto()) {
- marginLogicalLeftAlias = marginLogicalLeft.calcValue(containerLogicalWidth);
- logicalLeftValue = logicalLeft.calcValue(containerLogicalWidth);
- logicalRightValue = logicalRight.calcValue(containerLogicalWidth);
+ marginLogicalLeftAlias = valueForLength(marginLogicalLeft, containerLogicalWidth, renderView);
+ logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView);
+ logicalRightValue = valueForLength(logicalRight, containerLogicalWidth, renderView);
// Solve for 'margin-right'
marginLogicalRightAlias = availableSpace - (logicalLeftValue + logicalRightValue + marginLogicalLeftAlias);
} else {
// Nothing is 'auto', just calculate the values.
- marginLogicalLeftAlias = marginLogicalLeft.calcValue(containerLogicalWidth);
- marginLogicalRightAlias = marginLogicalRight.calcValue(containerLogicalWidth);
- logicalRightValue = logicalRight.calcValue(containerLogicalWidth);
- logicalLeftValue = logicalLeft.calcValue(containerLogicalWidth);
+ marginLogicalLeftAlias = valueForLength(marginLogicalLeft, containerLogicalWidth, renderView);
+ marginLogicalRightAlias = valueForLength(marginLogicalRight, containerLogicalWidth, renderView);
+ logicalRightValue = valueForLength(logicalRight, containerLogicalWidth, renderView);
+ logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView);
// If the containing block is right-to-left, then push the left position as far to the right as possible
if (containerDirection == RTL) {
int totalLogicalWidth = logicalWidth() + logicalLeftValue + logicalRightValue + marginLogicalLeftAlias + marginLogicalRightAlias;
@@ -3363,6 +3359,7 @@ void RenderBox::computePositionedLogicalHeightReplaced()
Length logicalTop = style()->logicalTop();
Length logicalBottom = style()->logicalBottom();
+ RenderView* renderView = view();
/*-----------------------------------------------------------------------*\
* 1. The used value of 'height' is determined as for inline replaced
@@ -3406,8 +3403,8 @@ void RenderBox::computePositionedLogicalHeightReplaced()
// 'top' and 'bottom' cannot be 'auto' due to step 2 and 3 combined.
ASSERT(!(logicalTop.isAuto() || logicalBottom.isAuto()));
- logicalTopValue = logicalTop.calcValue(containerLogicalHeight);
- logicalBottomValue = logicalBottom.calcValue(containerLogicalHeight);
+ logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView);
+ logicalBottomValue = valueForLength(logicalBottom, containerLogicalHeight, renderView);
LayoutUnit difference = availableSpace - (logicalTopValue + logicalBottomValue);
// NOTE: This may result in negative values.
@@ -3419,39 +3416,39 @@ void RenderBox::computePositionedLogicalHeightReplaced()
* for that value.
\*-----------------------------------------------------------------------*/
} else if (logicalTop.isAuto()) {
- marginBeforeAlias = marginBefore.calcValue(containerLogicalHeight);
- marginAfterAlias = marginAfter.calcValue(containerLogicalHeight);
- logicalBottomValue = logicalBottom.calcValue(containerLogicalHeight);
+ marginBeforeAlias = valueForLength(marginBefore, containerLogicalHeight, renderView);
+ marginAfterAlias = valueForLength(marginAfter, containerLogicalHeight, renderView);
+ logicalBottomValue = valueForLength(logicalBottom, containerLogicalHeight, renderView);
// Solve for 'top'
logicalTopValue = availableSpace - (logicalBottomValue + marginBeforeAlias + marginAfterAlias);
} else if (logicalBottom.isAuto()) {
- marginBeforeAlias = marginBefore.calcValue(containerLogicalHeight);
- marginAfterAlias = marginAfter.calcValue(containerLogicalHeight);
- logicalTopValue = logicalTop.calcValue(containerLogicalHeight);
+ marginBeforeAlias = valueForLength(marginBefore, containerLogicalHeight, renderView);
+ marginAfterAlias = valueForLength(marginAfter, containerLogicalHeight, renderView);
+ logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView);
// Solve for 'bottom'
// NOTE: It is not necessary to solve for 'bottom' because we don't ever
// use the value.
} else if (marginBefore.isAuto()) {
- marginAfterAlias = marginAfter.calcValue(containerLogicalHeight);
- logicalTopValue = logicalTop.calcValue(containerLogicalHeight);
- logicalBottomValue = logicalBottom.calcValue(containerLogicalHeight);
+ marginAfterAlias = valueForLength(marginAfter, containerLogicalHeight, renderView);
+ logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView);
+ logicalBottomValue = valueForLength(logicalBottom, containerLogicalHeight, renderView);
// Solve for 'margin-top'
marginBeforeAlias = availableSpace - (logicalTopValue + logicalBottomValue + marginAfterAlias);
} else if (marginAfter.isAuto()) {
- marginBeforeAlias = marginBefore.calcValue(containerLogicalHeight);
- logicalTopValue = logicalTop.calcValue(containerLogicalHeight);
- logicalBottomValue = logicalBottom.calcValue(containerLogicalHeight);
+ marginBeforeAlias = valueForLength(marginBefore, containerLogicalHeight, renderView);
+ logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView);
+ logicalBottomValue = valueForLength(logicalBottom, containerLogicalHeight, renderView);
// Solve for 'margin-bottom'
marginAfterAlias = availableSpace - (logicalTopValue + logicalBottomValue + marginBeforeAlias);
} else {
// Nothing is 'auto', just calculate the values.
- marginBeforeAlias = marginBefore.calcValue(containerLogicalHeight);
- marginAfterAlias = marginAfter.calcValue(containerLogicalHeight);
- logicalTopValue = logicalTop.calcValue(containerLogicalHeight);
+ marginBeforeAlias = valueForLength(marginBefore, containerLogicalHeight, renderView);
+ marginAfterAlias = valueForLength(marginAfter, containerLogicalHeight, renderView);
+ logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView);
// NOTE: It is not necessary to solve for 'bottom' because we don't ever
// use the value.
}
@@ -3529,7 +3526,7 @@ VisiblePosition RenderBox::positionForPoint(const LayoutPoint& point)
}
// Pass off to the closest child.
- LayoutUnit minDist = numeric_limits<LayoutUnit>::max();
+ LayoutUnit minDist = MAX_LAYOUT_UNIT;
RenderBox* closestRenderer = 0;
LayoutPoint adjustedPoint = point;
if (isTableRow())
@@ -3545,9 +3542,9 @@ VisiblePosition RenderBox::positionForPoint(const LayoutPoint& point)
RenderBox* renderer = toRenderBox(renderObject);
- LayoutUnit top = renderer->borderTop() + renderer->paddingTop() + (isTableRow() ? zeroLayoutUnit : renderer->y());
+ LayoutUnit top = renderer->borderTop() + renderer->paddingTop() + (isTableRow() ? ZERO_LAYOUT_UNIT : renderer->y());
LayoutUnit bottom = top + renderer->contentHeight();
- LayoutUnit left = renderer->borderLeft() + renderer->paddingLeft() + (isTableRow() ? zeroLayoutUnit : renderer->x());
+ LayoutUnit left = renderer->borderLeft() + renderer->paddingLeft() + (isTableRow() ? ZERO_LAYOUT_UNIT : renderer->x());
LayoutUnit right = left + renderer->contentWidth();
if (point.x() <= right && point.x() >= left && point.y() <= top && point.y() >= bottom) {
@@ -3600,9 +3597,9 @@ bool RenderBox::shrinkToAvoidFloats() const
// Floating objects don't shrink. Objects that don't avoid floats don't shrink. Marquees don't shrink.
if ((isInline() && !isHTMLMarquee()) || !avoidsFloats() || isFloating())
return false;
-
- // All auto-width objects that avoid floats should always use lineWidth.
- return style()->width().isAuto();
+
+ // Only auto width objects can possibly shrink to avoid floats.
+ return style()->width().isAuto();
}
bool RenderBox::avoidsFloats() const
@@ -3612,7 +3609,7 @@ bool RenderBox::avoidsFloats() const
void RenderBox::addVisualEffectOverflow()
{
- if (!style()->boxShadow() && !style()->hasBorderImageOutsets() && !style()->hasFilterOutsets())
+ if (!style()->boxShadow() && !style()->hasBorderImageOutsets())
return;
bool isFlipped = style()->isFlippedBlocksWritingMode();
@@ -3655,21 +3652,6 @@ void RenderBox::addVisualEffectOverflow()
overflowMaxY = max(overflowMaxY, borderBox.maxY() + ((!isFlipped || !isHorizontal) ? borderOutsetBottom : borderOutsetTop));
}
-#if ENABLE(CSS_FILTERS)
- // Compute any filter outset overflow.
- if (style()->hasFilterOutsets()) {
- LayoutUnit filterOutsetLeft;
- LayoutUnit filterOutsetRight;
- LayoutUnit filterOutsetTop;
- LayoutUnit filterOutsetBottom;
- style()->getFilterOutsets(filterOutsetTop, filterOutsetRight, filterOutsetBottom, filterOutsetLeft);
-
- overflowMinX = min(overflowMinX, borderBox.x() - filterOutsetLeft);
- overflowMaxX = max(overflowMaxX, borderBox.maxX() + filterOutsetRight);
- overflowMinY = min(overflowMinY, borderBox.y() - filterOutsetTop);
- overflowMaxY = max(overflowMaxY, borderBox.maxY() + filterOutsetBottom);
- }
-#endif
// Add in the final overflow with shadows and outsets combined.
addVisualOverflow(LayoutRect(overflowMinX, overflowMinY, overflowMaxX - overflowMinX, overflowMaxY - overflowMinY));
}
@@ -3733,10 +3715,6 @@ void RenderBox::addLayoutOverflow(const LayoutRect& rect)
if (!m_overflow)
m_overflow = adoptPtr(new RenderOverflow(clientBox, borderBoxRect()));
- // Lazily allocate our layer as we will need it to hold our scroll information.
- if (hasOverflowClip())
- ensureLayer();
-
m_overflow->addLayoutOverflow(overflowRect);
}
@@ -4029,4 +4007,78 @@ bool RenderBox::hasRelativeDimensions() const
|| style()->minHeight().isPercent() || style()->minWidth().isPercent();
}
+bool RenderBox::hasRelativeLogicalHeight() const
+{
+ return style()->logicalHeight().isPercent()
+ || style()->logicalMinHeight().isPercent()
+ || 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,
+ // we should fix it and remove the table part checks.
+ if (box->isTable())
+ toRenderTable(box)->setNeedsSectionRecalc();
+ else if (box->isTableSection())
+ toRenderTableSection(box)->setNeedsCellRecalc();
+
+ box->setNeedsLayoutAndPrefWidthsRecalc();
+}
+
+RenderObject* RenderBox::splitAnonymousBoxesAroundChild(RenderObject* beforeChild)
+{
+ bool didSplitParentAnonymousBoxes = false;
+
+ while (beforeChild->parent() != this) {
+ RenderBox* boxToSplit = toRenderBox(beforeChild->parent());
+ if (boxToSplit->firstChild() != beforeChild && boxToSplit->isAnonymous()) {
+ didSplitParentAnonymousBoxes = true;
+
+ // We have to split the parent box into two boxes and move children
+ // from |beforeChild| to end into the new post box.
+ RenderBox* postBox = boxToSplit->createAnonymousBoxWithSameTypeAs(this);
+ postBox->setChildrenInline(boxToSplit->childrenInline());
+ RenderBox* parentBox = toRenderBox(boxToSplit->parent());
+ parentBox->virtualChildren()->insertChildNode(parentBox, postBox, boxToSplit->nextSibling());
+ boxToSplit->moveChildrenTo(postBox, beforeChild, 0, boxToSplit->hasLayer());
+
+ markBoxForRelayoutAfterSplit(boxToSplit);
+ markBoxForRelayoutAfterSplit(postBox);
+
+ beforeChild = postBox;
+ } else
+ beforeChild = boxToSplit;
+ }
+
+ if (didSplitParentAnonymousBoxes)
+ markBoxForRelayoutAfterSplit(this);
+
+ ASSERT(beforeChild->parent() == this);
+ return beforeChild;
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/rendering/RenderBox.h b/Source/WebCore/rendering/RenderBox.h
index 2bba71f0b..794ed39e2 100644
--- a/Source/WebCore/rendering/RenderBox.h
+++ b/Source/WebCore/rendering/RenderBox.h
@@ -42,10 +42,7 @@ public:
RenderBox(Node*);
virtual ~RenderBox();
- virtual bool requiresLayer() const OVERRIDE { return isRoot() || isPositioned() || isRelPositioned() || isTransparent() || requiresLayerForOverflowClip() || hasTransform() || hasMask() || hasReflection() || hasFilter() || style()->specifiesColumns(); }
- bool requiresLayerForOverflowClip() const;
-
- bool hasOverflowClipWithLayer() const { return hasOverflowClip() && hasLayer(); }
+ virtual bool requiresLayer() const OVERRIDE { return isRoot() || isPositioned() || isRelPositioned() || isTransparent() || hasOverflowClip() || hasTransform() || hasHiddenBackface() || hasMask() || hasReflection() || hasFilter() || style()->specifiesColumns(); }
// Use this with caution! No type checking is done!
RenderBox* firstChildBox() const;
@@ -56,9 +53,8 @@ public:
LayoutUnit width() const { return m_frameRect.width(); }
LayoutUnit height() const { return m_frameRect.height(); }
- // FIXME: The implementation for these functions will change once we move to subpixel layout. See bug 60318.
- int pixelSnappedWidth() const { return m_frameRect.width(); }
- int pixelSnappedHeight() const { return m_frameRect.height(); }
+ int pixelSnappedWidth() const { return m_frameRect.pixelSnappedWidth(); }
+ int pixelSnappedHeight() const { return m_frameRect.pixelSnappedHeight(); }
// These represent your location relative to your container as a physical offset.
// In layout related methods you almost always want the logical location (e.g. x() and y()).
@@ -123,6 +119,7 @@ public:
LayoutPoint location() const { return m_frameRect.location(); }
LayoutSize locationOffset() const { return LayoutSize(x(), y()); }
LayoutSize size() const { return m_frameRect.size(); }
+ IntSize pixelSnappedSize() const { return m_frameRect.pixelSnappedSize(); }
void setLocation(const LayoutPoint& location) { m_frameRect.setLocation(location); }
@@ -130,20 +127,24 @@ public:
void move(LayoutUnit dx, LayoutUnit dy) { m_frameRect.move(dx, dy); }
LayoutRect frameRect() const { return m_frameRect; }
+ IntRect pixelSnappedFrameRect() const { return pixelSnappedIntRect(m_frameRect); }
void setFrameRect(const LayoutRect& rect) { m_frameRect = rect; }
- // FIXME: We shouldn't be returning this as a LayoutRect, since it loses its position and won't properly pixel snap.
LayoutRect borderBoxRect() const { return LayoutRect(LayoutPoint(), size()); }
- IntRect pixelSnappedBorderBoxRect() const { return IntRect(IntPoint(), IntSize(m_frameRect.pixelSnappedWidth(), m_frameRect.pixelSnappedHeight())); }
- virtual IntRect borderBoundingBox() const { return pixelSnappedBorderBoxRect(); }
+ IntRect pixelSnappedBorderBoxRect() const { return IntRect(IntPoint(), m_frameRect.pixelSnappedSize()); }
+ virtual IntRect borderBoundingBox() const { return pixelSnappedBorderBoxRect(); }
- // The content area of the box (excludes padding and border).
- LayoutRect contentBoxRect(PaddingOptions paddingOption = ExcludeIntrinsicPadding) const { return LayoutRect(borderLeft() + paddingLeft(paddingOption), borderTop() + paddingTop(paddingOption), contentWidth(paddingOption), contentHeight(paddingOption)); }
+ // The content area of the box (excludes padding - and intrinsic padding for table cells, etc... - and border).
+ LayoutRect contentBoxRect() const { return LayoutRect(borderLeft() + paddingLeft(), borderTop() + paddingTop(), contentWidth(), contentHeight()); }
// The content box in absolute coords. Ignores transforms.
- LayoutRect absoluteContentBox() const;
+ IntRect absoluteContentBox() const;
// The content box converted to absolute coords (taking transforms into account).
FloatQuad absoluteContentQuad() const;
+ // This returns the content area of the box (excluding padding and border). The only difference with contentBoxRect is that computedCSSContentBoxRect
+ // does include the intrinsic padding in the content box as this is what some callers expect (like getComputedStyle).
+ LayoutRect computedCSSContentBoxRect() const { return LayoutRect(borderLeft() + computedCSSPaddingLeft(), borderTop() + computedCSSPaddingTop(), clientWidth() - computedCSSPaddingLeft() - computedCSSPaddingRight(), clientHeight() - computedCSSPaddingTop() - computedCSSPaddingBottom()); }
+
// Bounds of the outline box in absolute coords. Respects transforms
virtual LayoutRect outlineBoundsForRepaint(RenderBoxModelObject* /*repaintContainer*/, LayoutPoint* cachedOffsetToRepaintContainer) const;
virtual void addFocusRingRects(Vector<IntRect>&, const LayoutPoint&);
@@ -159,18 +160,18 @@ public:
// but it is on the right in vertical-rl.
LayoutRect layoutOverflowRect() const { return m_overflow ? m_overflow->layoutOverflowRect() : clientBoxRect(); }
IntRect pixelSnappedLayoutOverflowRect() const { return pixelSnappedIntRect(layoutOverflowRect()); }
- LayoutUnit minYLayoutOverflow() const { return m_overflow? m_overflow->minYLayoutOverflow() : borderTop(); }
- LayoutUnit maxYLayoutOverflow() const { return m_overflow ? m_overflow->maxYLayoutOverflow() : borderTop() + clientHeight(); }
- LayoutUnit minXLayoutOverflow() const { return m_overflow ? m_overflow->minXLayoutOverflow() : borderLeft(); }
- LayoutUnit maxXLayoutOverflow() const { return m_overflow ? m_overflow->maxXLayoutOverflow() : borderLeft() + clientWidth(); }
+ LayoutUnit minYLayoutOverflow() const { return m_overflow? m_overflow->minYLayoutOverflow() : static_cast<LayoutUnit>(borderTop()); }
+ LayoutUnit maxYLayoutOverflow() const { return m_overflow ? m_overflow->maxYLayoutOverflow() : static_cast<LayoutUnit>(borderTop()) + clientHeight(); }
+ LayoutUnit minXLayoutOverflow() const { return m_overflow ? m_overflow->minXLayoutOverflow() : static_cast<LayoutUnit>(borderLeft()); }
+ LayoutUnit maxXLayoutOverflow() const { return m_overflow ? m_overflow->maxXLayoutOverflow() : static_cast<LayoutUnit>(borderLeft()) + clientWidth(); }
LayoutSize maxLayoutOverflow() const { return LayoutSize(maxXLayoutOverflow(), maxYLayoutOverflow()); }
LayoutUnit logicalLeftLayoutOverflow() const { return style()->isHorizontalWritingMode() ? minXLayoutOverflow() : minYLayoutOverflow(); }
LayoutUnit logicalRightLayoutOverflow() const { return style()->isHorizontalWritingMode() ? maxXLayoutOverflow() : maxYLayoutOverflow(); }
virtual LayoutRect visualOverflowRect() const { return m_overflow ? m_overflow->visualOverflowRect() : borderBoxRect(); }
- LayoutUnit minYVisualOverflow() const { return m_overflow? m_overflow->minYVisualOverflow() : zeroLayoutUnit; }
+ LayoutUnit minYVisualOverflow() const { return m_overflow? m_overflow->minYVisualOverflow() : ZERO_LAYOUT_UNIT; }
LayoutUnit maxYVisualOverflow() const { return m_overflow ? m_overflow->maxYVisualOverflow() : height(); }
- LayoutUnit minXVisualOverflow() const { return m_overflow ? m_overflow->minXVisualOverflow() : zeroLayoutUnit; }
+ LayoutUnit minXVisualOverflow() const { return m_overflow ? m_overflow->minXVisualOverflow() : ZERO_LAYOUT_UNIT; }
LayoutUnit maxXVisualOverflow() const { return m_overflow ? m_overflow->maxXVisualOverflow() : width(); }
LayoutUnit logicalLeftVisualOverflow() const { return style()->isHorizontalWritingMode() ? minXVisualOverflow() : minYVisualOverflow(); }
LayoutUnit logicalRightVisualOverflow() const { return style()->isHorizontalWritingMode() ? maxXVisualOverflow() : maxYVisualOverflow(); }
@@ -185,10 +186,10 @@ public:
void updateLayerTransform();
- LayoutUnit contentWidth(PaddingOptions paddingOption = ExcludeIntrinsicPadding) const { return clientWidth() - paddingLeft(paddingOption) - paddingRight(paddingOption); }
- LayoutUnit contentHeight(PaddingOptions paddingOption = ExcludeIntrinsicPadding) const { return clientHeight() - paddingTop(paddingOption) - paddingBottom(paddingOption); }
- LayoutUnit contentLogicalWidth(PaddingOptions paddingOption = ExcludeIntrinsicPadding) const { return style()->isHorizontalWritingMode() ? contentWidth(paddingOption) : contentHeight(paddingOption); }
- LayoutUnit contentLogicalHeight(PaddingOptions paddingOption = ExcludeIntrinsicPadding) const { return style()->isHorizontalWritingMode() ? contentHeight(paddingOption) : contentWidth(paddingOption); }
+ LayoutUnit contentWidth() const { return clientWidth() - paddingLeft() - paddingRight(); }
+ LayoutUnit contentHeight() const { return clientHeight() - paddingTop() - paddingBottom(); }
+ LayoutUnit contentLogicalWidth() const { return style()->isHorizontalWritingMode() ? contentWidth() : contentHeight(); }
+ LayoutUnit contentLogicalHeight() const { return style()->isHorizontalWritingMode() ? contentHeight() : contentWidth(); }
// IE extensions. Used to calculate offsetWidth/Height. Overridden by inlines (RenderFlow)
// to return the remaining width on a given line (and the height of a single line).
@@ -315,13 +316,14 @@ public:
virtual LayoutUnit containingBlockLogicalWidthForContent() const;
LayoutUnit containingBlockLogicalWidthForContentInRegion(RenderRegion*, LayoutUnit offsetFromLogicalTopOfFirstPage) const;
+ LayoutUnit containingBlockAvailableLineWidthInRegion(RenderRegion*, LayoutUnit offsetFromLogicalTopOfFirstPage) const;
LayoutUnit perpendicularContainingBlockLogicalHeight() const;
virtual void computeLogicalWidth();
virtual void computeLogicalHeight();
RenderBoxRegionInfo* renderBoxRegionInfo(RenderRegion*, LayoutUnit offsetFromLogicalTopOfFirstPage, RenderBoxRegionInfoFlags = CacheRenderBoxRegionInfo) const;
- void computeLogicalWidthInRegion(RenderRegion* = 0, LayoutUnit offsetFromLogicalTopOfFirstPage = zeroLayoutUnit);
+ void computeLogicalWidthInRegion(RenderRegion* = 0, LayoutUnit offsetFromLogicalTopOfFirstPage = ZERO_LAYOUT_UNIT);
bool stretchesToViewport() const
{
@@ -341,6 +343,7 @@ public:
LayoutUnit computeLogicalWidthInRegionUsing(LogicalWidthType, LayoutUnit availableLogicalWidth, const RenderBlock* containingBlock, RenderRegion*, LayoutUnit offsetFromLogicalTopOfFirstPage);
LayoutUnit computeLogicalHeightUsing(const Length& height);
+ LayoutUnit computeContentLogicalHeightUsing(const Length& height);
LayoutUnit computeReplacedLogicalWidthUsing(Length width) const;
LayoutUnit computeReplacedLogicalWidthRespectingMinMaxWidth(LayoutUnit logicalWidth, bool includeMaxWidth = true) const;
LayoutUnit computeReplacedLogicalHeightUsing(Length height) const;
@@ -455,11 +458,10 @@ public:
virtual void computeIntrinsicRatioInformation(FloatSize& /* intrinsicSize */, double& /* intrinsicRatio */, bool& /* isPercentageIntrinsicSize */) const { }
IntSize scrolledContentOffset() const;
- IntSize cachedSizeForOverflowClip() const;
- void updateCachedSizeForOverflowClip();
- void clearCachedSizeForOverflowClip();
+ LayoutSize cachedSizeForOverflowClip() const;
virtual bool hasRelativeDimensions() const;
+ virtual bool hasRelativeLogicalHeight() const;
bool hasHorizontalLayoutOverflow() const
{
@@ -483,6 +485,12 @@ public:
return false;
}
+ virtual RenderBox* createAnonymousBoxWithSameTypeAs(const RenderObject*) const
+ {
+ ASSERT_NOT_REACHED();
+ return 0;
+ }
+
protected:
virtual void willBeDestroyed();
@@ -508,11 +516,37 @@ protected:
virtual bool shouldComputeSizeAsReplaced() const { return isReplaced() && !isInlineBlockOrInlineTable(); }
- virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed, bool useTransforms, TransformState&, bool* wasFixed = 0) const;
+ virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed, bool useTransforms, TransformState&, ApplyContainerFlipOrNot = ApplyContainerFlip, bool* wasFixed = 0) const;
virtual void mapAbsoluteToLocalPoint(bool fixed, bool useTransforms, TransformState&) const;
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:
bool fixedElementLaysOutRelativeToFrame(Frame*, FrameView*) const;
@@ -611,24 +645,6 @@ inline RenderBox* RenderBox::lastChildBox() const
return toRenderBox(lastChild());
}
-inline bool RenderBox::requiresLayerForOverflowClip() const
-{
- if (!hasOverflowClip())
- return false;
-
- // The resizer is attached to the RenderLayer so we need one.
- if (style()->resize() != RESIZE_NONE)
- return true;
-
- // FIXME: overflow: auto could also lazily create its layer but some repainting
- // issues are arising from that.
- bool onlyOverflowHidden = style()->overflowX() == OHIDDEN && style()->overflowY() == OHIDDEN;
-
- // Currently {push|pop}ContentsClip do not handle properly all cases involving a clip
- // with a border radius so we need a RenderLayer to handle them.
- return !onlyOverflowHidden || style()->hasBorderRadius();
-}
-
} // namespace WebCore
#endif // RenderBox_h
diff --git a/Source/WebCore/rendering/RenderBoxModelObject.cpp b/Source/WebCore/rendering/RenderBoxModelObject.cpp
index c709705bc..eed3577a3 100644
--- a/Source/WebCore/rendering/RenderBoxModelObject.cpp
+++ b/Source/WebCore/rendering/RenderBoxModelObject.cpp
@@ -26,6 +26,7 @@
#include "config.h"
#include "RenderBoxModelObject.h"
+#include "FilterOperations.h"
#include "GraphicsContext.h"
#include "HTMLFrameOwnerElement.h"
#include "HTMLNames.h"
@@ -40,6 +41,11 @@
#include "TransformState.h"
#include <wtf/CurrentTime.h>
+#if USE(ACCELERATED_COMPOSITING)
+#include "RenderLayerBacking.h"
+#include "RenderLayerCompositor.h"
+#endif
+
using namespace std;
namespace WebCore {
@@ -240,6 +246,70 @@ void RenderBoxModelObject::setSelectionState(SelectionState state)
containingBlock->setSelectionState(state);
}
+#if USE(ACCELERATED_COMPOSITING)
+void RenderBoxModelObject::contentChanged(ContentChangeType changeType)
+{
+ if (!hasLayer())
+ return;
+
+ layer()->contentChanged(changeType);
+}
+
+bool RenderBoxModelObject::hasAcceleratedCompositing() const
+{
+ return view()->compositor()->hasAcceleratedCompositing();
+}
+
+bool RenderBoxModelObject::startTransition(double timeOffset, CSSPropertyID propertyId, const RenderStyle* fromStyle, const RenderStyle* toStyle)
+{
+ ASSERT(hasLayer());
+ ASSERT(isComposited());
+ return layer()->backing()->startTransition(timeOffset, propertyId, fromStyle, toStyle);
+}
+
+void RenderBoxModelObject::transitionPaused(double timeOffset, CSSPropertyID propertyId)
+{
+ ASSERT(hasLayer());
+ ASSERT(isComposited());
+ layer()->backing()->transitionPaused(timeOffset, propertyId);
+}
+
+void RenderBoxModelObject::transitionFinished(CSSPropertyID propertyId)
+{
+ ASSERT(hasLayer());
+ ASSERT(isComposited());
+ layer()->backing()->transitionFinished(propertyId);
+}
+
+bool RenderBoxModelObject::startAnimation(double timeOffset, const Animation* animation, const KeyframeList& keyframes)
+{
+ ASSERT(hasLayer());
+ ASSERT(isComposited());
+ return layer()->backing()->startAnimation(timeOffset, animation, keyframes);
+}
+
+void RenderBoxModelObject::animationPaused(double timeOffset, const String& name)
+{
+ ASSERT(hasLayer());
+ ASSERT(isComposited());
+ layer()->backing()->animationPaused(timeOffset, name);
+}
+
+void RenderBoxModelObject::animationFinished(const String& name)
+{
+ ASSERT(hasLayer());
+ ASSERT(isComposited());
+ layer()->backing()->animationFinished(name);
+}
+
+void RenderBoxModelObject::suspendAnimations(double time)
+{
+ ASSERT(hasLayer());
+ ASSERT(isComposited());
+ layer()->backing()->suspendAnimations(time);
+}
+#endif
+
bool RenderBoxModelObject::shouldPaintAtLowQuality(GraphicsContext* context, Image* image, const void* layer, const LayoutSize& size)
{
return imageQualityController()->shouldPaintAtLowQuality(context, this, image, layer, size);
@@ -329,9 +399,13 @@ void RenderBoxModelObject::styleWillChange(StyleDifference diff, const RenderSty
|| !(oldStyle->clip() == newStyle->clip())
|| oldStyle->hasClip() != newStyle->hasClip()
|| oldStyle->opacity() != newStyle->opacity()
- || oldStyle->transform() != newStyle->transform())
+ || oldStyle->transform() != newStyle->transform()
+#if ENABLE(CSS_FILTERS)
+ || oldStyle->filter() != newStyle->filter()
+#endif
+ )
layer()->repaintIncludingDescendants();
- } else if (newStyle->hasTransform() || newStyle->opacity() < 1) {
+ } else if (newStyle->hasTransform() || newStyle->opacity() < 1 || newStyle->hasFilter()) {
// If we don't have a layer yet, but we are going to get one because of transform or opacity,
// then we need to repaint the old position of the object.
repaint();
@@ -351,28 +425,18 @@ void RenderBoxModelObject::styleWillChange(StyleDifference diff, const RenderSty
RenderObject::styleWillChange(diff, newStyle);
}
-void RenderBoxModelObject::ensureLayer()
-{
- if (m_layer)
- return;
-
- m_layer = new (renderArena()) RenderLayer(this);
- setHasLayer(true);
- m_layer->insertOnlyThisLayer();
-}
-
void RenderBoxModelObject::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
RenderObject::styleDidChange(diff, oldStyle);
updateBoxModelInfoFromStyle();
-
+
if (requiresLayer()) {
if (!layer() && layerCreationAllowedForSubtree()) {
if (s_wasFloating && isFloating())
setChildNeedsLayout(true);
-
- ensureLayer();
-
+ m_layer = new (renderArena()) RenderLayer(this);
+ setHasLayer(true);
+ m_layer->insertOnlyThisLayer();
if (parent() && !needsLayout() && containingBlock()) {
m_layer->setRepaintStatus(NeedsFullRepaint);
// There is only one layer to update, it is not worth using |cachedOffset| since
@@ -388,8 +452,6 @@ void RenderBoxModelObject::styleDidChange(StyleDifference diff, const RenderStyl
setChildNeedsLayout(true);
if (s_hadTransform)
setNeedsLayoutAndPrefWidthsRecalc();
- if (hasOverflowClip())
- toRenderBox(this)->updateCachedSizeForOverflowClip();
}
if (layer()) {
@@ -437,12 +499,12 @@ LayoutUnit RenderBoxModelObject::relativePositionOffsetX() const
if (!style()->left().isAuto()) {
RenderBlock* cb = containingBlock();
if (!style()->right().isAuto() && !cb->style()->isLeftToRightDirection())
- return -style()->right().calcValue(cb->availableWidth());
- return offset + style()->left().calcValue(cb->availableWidth());
+ return -valueForLength(style()->right(), cb->availableWidth(), view());
+ return offset + valueForLength(style()->left(), cb->availableWidth(), view());
}
if (!style()->right().isAuto()) {
RenderBlock* cb = containingBlock();
- return offset + -style()->right().calcValue(cb->availableWidth());
+ return offset + -valueForLength(style()->right(), cb->availableWidth(), view());
}
return offset;
}
@@ -462,13 +524,13 @@ LayoutUnit RenderBoxModelObject::relativePositionOffsetY() const
&& (!containingBlock->style()->height().isAuto()
|| !style()->top().isPercent()
|| containingBlock->stretchesToViewport()))
- return offset + style()->top().calcValue(containingBlock->availableHeight());
+ return offset + valueForLength(style()->top(), containingBlock->availableHeight(), view());
if (!style()->bottom().isAuto()
&& (!containingBlock->style()->height().isAuto()
|| !style()->bottom().isPercent()
|| containingBlock->stretchesToViewport()))
- return offset + -style()->bottom().calcValue(containingBlock->availableHeight());
+ return offset + -valueForLength(style()->bottom(), containingBlock->availableHeight(), view());
return offset;
}
@@ -481,7 +543,7 @@ LayoutUnit RenderBoxModelObject::offsetLeft() const
return 0;
RenderBoxModelObject* offsetPar = offsetParent();
- LayoutUnit xPos = (isBox() ? toRenderBox(this)->left() : zeroLayoutUnit);
+ LayoutUnit xPos = (isBox() ? toRenderBox(this)->left() : ZERO_LAYOUT_UNIT);
// If the offsetParent of the element is null, or is the HTML body element,
// return the distance between the canvas origin and the left border edge
@@ -515,7 +577,7 @@ LayoutUnit RenderBoxModelObject::offsetTop() const
return 0;
RenderBoxModelObject* offsetPar = offsetParent();
- LayoutUnit yPos = (isBox() ? toRenderBox(this)->top() : zeroLayoutUnit);
+ LayoutUnit yPos = (isBox() ? toRenderBox(this)->top() : ZERO_LAYOUT_UNIT);
// If the offsetParent of the element is null, or is the HTML body element,
// return the distance between the canvas origin and the top border edge
@@ -542,92 +604,117 @@ LayoutUnit RenderBoxModelObject::offsetTop() const
int RenderBoxModelObject::pixelSnappedOffsetWidth() const
{
- return offsetWidth();
+ return snapSizeToPixel(offsetWidth(), offsetLeft());
}
int RenderBoxModelObject::pixelSnappedOffsetHeight() const
{
- return offsetHeight();
+ return snapSizeToPixel(offsetHeight(), offsetTop());
}
-LayoutUnit RenderBoxModelObject::paddingTop(PaddingOptions) const
+LayoutUnit RenderBoxModelObject::computedCSSPaddingTop() const
{
LayoutUnit w = 0;
+ RenderView* renderView = 0;
Length padding = style()->paddingTop();
if (padding.isPercent())
w = containingBlock()->availableLogicalWidth();
- return padding.calcMinValue(w);
+ else if (padding.isViewportPercentage())
+ renderView = view();
+ return minimumValueForLength(padding, w, renderView);
}
-LayoutUnit RenderBoxModelObject::paddingBottom(PaddingOptions) const
+LayoutUnit RenderBoxModelObject::computedCSSPaddingBottom() const
{
LayoutUnit w = 0;
+ RenderView* renderView = 0;
Length padding = style()->paddingBottom();
if (padding.isPercent())
w = containingBlock()->availableLogicalWidth();
- return padding.calcMinValue(w);
+ else if (padding.isViewportPercentage())
+ renderView = view();
+ return minimumValueForLength(padding, w, renderView);
}
-LayoutUnit RenderBoxModelObject::paddingLeft(PaddingOptions) const
+LayoutUnit RenderBoxModelObject::computedCSSPaddingLeft() const
{
LayoutUnit w = 0;
+ RenderView* renderView = 0;
Length padding = style()->paddingLeft();
if (padding.isPercent())
w = containingBlock()->availableLogicalWidth();
- return padding.calcMinValue(w);
+ else if (padding.isViewportPercentage())
+ renderView = view();
+ return minimumValueForLength(padding, w, renderView);
}
-LayoutUnit RenderBoxModelObject::paddingRight(PaddingOptions) const
+LayoutUnit RenderBoxModelObject::computedCSSPaddingRight() const
{
LayoutUnit w = 0;
+ RenderView* renderView = 0;
Length padding = style()->paddingRight();
if (padding.isPercent())
w = containingBlock()->availableLogicalWidth();
- return padding.calcMinValue(w);
+ else if (padding.isViewportPercentage())
+ renderView = view();
+ return minimumValueForLength(padding, w, renderView);
}
-LayoutUnit RenderBoxModelObject::paddingBefore(PaddingOptions) const
+LayoutUnit RenderBoxModelObject::computedCSSPaddingBefore() const
{
LayoutUnit w = 0;
+ RenderView* renderView = 0;
Length padding = style()->paddingBefore();
if (padding.isPercent())
w = containingBlock()->availableLogicalWidth();
- return padding.calcMinValue(w);
+ else if (padding.isViewportPercentage())
+ renderView = view();
+ return minimumValueForLength(padding, w, renderView);
}
-LayoutUnit RenderBoxModelObject::paddingAfter(PaddingOptions) const
+LayoutUnit RenderBoxModelObject::computedCSSPaddingAfter() const
{
LayoutUnit w = 0;
+ RenderView* renderView = 0;
Length padding = style()->paddingAfter();
if (padding.isPercent())
w = containingBlock()->availableLogicalWidth();
- return padding.calcMinValue(w);
+ else if (padding.isViewportPercentage())
+ renderView = view();
+ return minimumValueForLength(padding, w, renderView);
}
-LayoutUnit RenderBoxModelObject::paddingStart(PaddingOptions) const
+LayoutUnit RenderBoxModelObject::computedCSSPaddingStart() const
{
LayoutUnit w = 0;
+ RenderView* renderView = 0;
Length padding = style()->paddingStart();
if (padding.isPercent())
w = containingBlock()->availableLogicalWidth();
- return padding.calcMinValue(w);
+ else if (padding.isViewportPercentage())
+ renderView = view();
+ return minimumValueForLength(padding, w, renderView);
}
-LayoutUnit RenderBoxModelObject::paddingEnd(PaddingOptions) const
+LayoutUnit RenderBoxModelObject::computedCSSPaddingEnd() const
{
LayoutUnit w = 0;
+ RenderView* renderView = 0;
Length padding = style()->paddingEnd();
if (padding.isPercent())
w = containingBlock()->availableLogicalWidth();
- return padding.calcMinValue(w);
+ else if (padding.isViewportPercentage())
+ renderView = view();
+ return minimumValueForLength(padding, w, renderView);
}
RoundedRect RenderBoxModelObject::getBackgroundRoundedRect(const LayoutRect& borderRect, InlineFlowBox* box, LayoutUnit inlineBoxWidth, LayoutUnit inlineBoxHeight,
bool includeLogicalLeftEdge, bool includeLogicalRightEdge)
{
- RoundedRect border = style()->getRoundedBorderFor(borderRect, includeLogicalLeftEdge, includeLogicalRightEdge);
+ RenderView* renderView = view();
+ RoundedRect border = style()->getRoundedBorderFor(borderRect, renderView, includeLogicalLeftEdge, includeLogicalRightEdge);
if (box && (box->nextLineBox() || box->prevLineBox())) {
- RoundedRect segmentBorder = style()->getRoundedBorderFor(LayoutRect(0, 0, inlineBoxWidth, inlineBoxHeight), includeLogicalLeftEdge, includeLogicalRightEdge);
+ RoundedRect segmentBorder = style()->getRoundedBorderFor(LayoutRect(0, 0, inlineBoxWidth, inlineBoxHeight), renderView, includeLogicalLeftEdge, includeLogicalRightEdge);
border.setRadii(segmentBorder.radii());
}
@@ -731,10 +818,10 @@ void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, co
context->addRoundedRectClip(border);
}
- LayoutUnit bLeft = includeLeftEdge ? borderLeft() : zeroLayoutUnit;
- LayoutUnit bRight = includeRightEdge ? borderRight() : zeroLayoutUnit;
- LayoutUnit pLeft = includeLeftEdge ? paddingLeft() : zeroLayoutUnit;
- LayoutUnit pRight = includeRightEdge ? paddingRight() : zeroLayoutUnit;
+ int bLeft = includeLeftEdge ? borderLeft() : 0;
+ int bRight = includeRightEdge ? borderRight() : 0;
+ LayoutUnit pLeft = includeLeftEdge ? paddingLeft() : ZERO_LAYOUT_UNIT;
+ LayoutUnit pRight = includeRightEdge ? paddingRight() : ZERO_LAYOUT_UNIT;
GraphicsContextStateSaver clipWithScrollingStateSaver(*context, clippedWithLocalScrolling);
LayoutRect scrolledPaintRect = rect;
@@ -757,10 +844,10 @@ void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, co
if (bgLayer->clip() == PaddingFillBox || bgLayer->clip() == ContentFillBox) {
// Clip to the padding or content boxes as necessary.
bool includePadding = bgLayer->clip() == ContentFillBox;
- LayoutRect clipRect = LayoutRect(scrolledPaintRect.x() + bLeft + (includePadding ? pLeft : zeroLayoutUnit),
- scrolledPaintRect.y() + borderTop() + (includePadding ? paddingTop() : zeroLayoutUnit),
- scrolledPaintRect.width() - bLeft - bRight - (includePadding ? pLeft + pRight : zeroLayoutUnit),
- scrolledPaintRect.height() - borderTop() - borderBottom() - (includePadding ? paddingTop() + paddingBottom() : zeroLayoutUnit));
+ LayoutRect clipRect = LayoutRect(scrolledPaintRect.x() + bLeft + (includePadding ? pLeft : ZERO_LAYOUT_UNIT),
+ scrolledPaintRect.y() + borderTop() + (includePadding ? paddingTop() : ZERO_LAYOUT_UNIT),
+ scrolledPaintRect.width() - bLeft - bRight - (includePadding ? pLeft + pRight : ZERO_LAYOUT_UNIT),
+ scrolledPaintRect.height() - borderTop() - borderBottom() - (includePadding ? paddingTop() + paddingBottom() : ZERO_LAYOUT_UNIT));
backgroundClipStateSaver.save();
context->clip(clipRect);
} else if (bgLayer->clip() == TextFillBox) {
@@ -879,102 +966,96 @@ void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, co
}
}
-static inline LayoutUnit resolveWidthForRatio(LayoutUnit height, const FloatSize& intrinsicRatio)
+static inline int resolveWidthForRatio(int height, const FloatSize& intrinsicRatio)
{
- // FIXME: Remove unnecessary rounding when layout is off ints: webkit.org/b/63656
- return static_cast<LayoutUnit>(ceilf(height * intrinsicRatio.width() / intrinsicRatio.height()));
+ return ceilf(height * intrinsicRatio.width() / intrinsicRatio.height());
}
-static inline LayoutUnit resolveHeightForRatio(LayoutUnit width, const FloatSize& intrinsicRatio)
+static inline int resolveHeightForRatio(int width, const FloatSize& intrinsicRatio)
{
- // FIXME: Remove unnecessary rounding when layout is off ints: webkit.org/b/63656
- return static_cast<LayoutUnit>(ceilf(width * intrinsicRatio.height() / intrinsicRatio.width()));
+ return ceilf(width * intrinsicRatio.height() / intrinsicRatio.width());
}
-static inline LayoutSize resolveAgainstIntrinsicWidthOrHeightAndRatio(const LayoutSize& size, const FloatSize& intrinsicRatio, LayoutUnit useWidth, LayoutUnit useHeight)
+static inline IntSize resolveAgainstIntrinsicWidthOrHeightAndRatio(const IntSize& size, const FloatSize& intrinsicRatio, int useWidth, int useHeight)
{
if (intrinsicRatio.isEmpty()) {
if (useWidth)
- return LayoutSize(useWidth, size.height());
- return LayoutSize(size.width(), useHeight);
+ return IntSize(useWidth, size.height());
+ return IntSize(size.width(), useHeight);
}
if (useWidth)
- return LayoutSize(useWidth, resolveHeightForRatio(useWidth, intrinsicRatio));
- return LayoutSize(resolveWidthForRatio(useHeight, intrinsicRatio), useHeight);
+ return IntSize(useWidth, resolveHeightForRatio(useWidth, intrinsicRatio));
+ return IntSize(resolveWidthForRatio(useHeight, intrinsicRatio), useHeight);
}
-static inline LayoutSize resolveAgainstIntrinsicRatio(const LayoutSize& size, const FloatSize& intrinsicRatio)
+static inline IntSize resolveAgainstIntrinsicRatio(const IntSize& size, const FloatSize& intrinsicRatio)
{
// Two possible solutions: (size.width(), solutionHeight) or (solutionWidth, size.height())
// "... must be assumed to be the largest dimensions..." = easiest answer: the rect with the largest surface area.
- LayoutUnit solutionWidth = resolveWidthForRatio(size.height(), intrinsicRatio);
- LayoutUnit solutionHeight = resolveHeightForRatio(size.width(), intrinsicRatio);
+ int solutionWidth = resolveWidthForRatio(size.height(), intrinsicRatio);
+ int solutionHeight = resolveHeightForRatio(size.width(), intrinsicRatio);
if (solutionWidth <= size.width()) {
if (solutionHeight <= size.height()) {
// If both solutions fit, choose the one covering the larger area.
- LayoutUnit areaOne = solutionWidth * size.height();
- LayoutUnit areaTwo = size.width() * solutionHeight;
+ int areaOne = solutionWidth * size.height();
+ int areaTwo = size.width() * solutionHeight;
if (areaOne < areaTwo)
- return LayoutSize(size.width(), solutionHeight);
- return LayoutSize(solutionWidth, size.height());
+ return IntSize(size.width(), solutionHeight);
+ return IntSize(solutionWidth, size.height());
}
// Only the first solution fits.
- return LayoutSize(solutionWidth, size.height());
+ return IntSize(solutionWidth, size.height());
}
// Only the second solution fits, assert that.
ASSERT(solutionHeight <= size.height());
- return LayoutSize(size.width(), solutionHeight);
+ return IntSize(size.width(), solutionHeight);
}
IntSize RenderBoxModelObject::calculateImageIntrinsicDimensions(StyleImage* image, const IntSize& positioningAreaSize) const
{
- int resolvedWidth = 0;
- int resolvedHeight = 0;
+ // A generated image without a fixed size, will always return the container size as intrinsic size.
+ if (image->isGeneratedImage() && image->usesImageContainerSize())
+ return IntSize(positioningAreaSize.width(), positioningAreaSize.height());
+
+ Length intrinsicWidth;
+ Length intrinsicHeight;
FloatSize intrinsicRatio;
+ image->computeIntrinsicDimensions(this, intrinsicWidth, intrinsicHeight, intrinsicRatio);
- // A generated image without a fixed size, will always return the container size as intrinsic size.
- if (image->isGeneratedImage() && image->usesImageContainerSize()) {
- resolvedWidth = positioningAreaSize.width();
- resolvedHeight = positioningAreaSize.height();
- } else {
- Length intrinsicWidth;
- Length intrinsicHeight;
- image->computeIntrinsicDimensions(this, intrinsicWidth, intrinsicHeight, intrinsicRatio);
-
- // Intrinsic dimensions expressed as percentages must be resolved relative to the dimensions of the rectangle
- // that establishes the coordinate system for the 'background-position' property.
-
- // FIXME: Remove unnecessary rounding when layout is off ints: webkit.org/b/63656
- if (intrinsicWidth.isPercent() && intrinsicHeight.isPercent() && intrinsicRatio.isEmpty()) {
- // Resolve width/height percentages against positioningAreaSize, only if no intrinsic ratio is provided.
- resolvedWidth = static_cast<int>(round(positioningAreaSize.width() * intrinsicWidth.percent() / 100));
- resolvedHeight = static_cast<int>(round(positioningAreaSize.height() * intrinsicHeight.percent() / 100));
- } else {
- if (intrinsicWidth.isFixed())
- resolvedWidth = static_cast<int>(intrinsicWidth.value() * style()->effectiveZoom());
- if (intrinsicHeight.isFixed())
- resolvedHeight = static_cast<int>(intrinsicHeight.value() * style()->effectiveZoom());
- }
+ // Intrinsic dimensions expressed as percentages must be resolved relative to the dimensions of the rectangle
+ // that establishes the coordinate system for the 'background-position' property.
+
+ // FIXME: Remove unnecessary rounding when layout is off ints: webkit.org/b/63656
+ if (intrinsicWidth.isPercent() && intrinsicHeight.isPercent() && intrinsicRatio.isEmpty()) {
+ // Resolve width/height percentages against positioningAreaSize, only if no intrinsic ratio is provided.
+ int resolvedWidth = static_cast<int>(round(positioningAreaSize.width() * intrinsicWidth.percent() / 100));
+ int resolvedHeight = static_cast<int>(round(positioningAreaSize.height() * intrinsicHeight.percent() / 100));
+ return IntSize(resolvedWidth, resolvedHeight);
}
- if (resolvedWidth > 0 && resolvedHeight > 0)
- return IntSize(resolvedWidth, resolvedHeight);
+ IntSize resolvedSize(intrinsicWidth.isFixed() ? intrinsicWidth.value() : 0, intrinsicHeight.isFixed() ? intrinsicHeight.value() : 0);
+ IntSize minimumSize(resolvedSize.width() > 0 ? 1 : 0, resolvedSize.height() > 0 ? 1 : 0);
+ resolvedSize.scale(style()->effectiveZoom());
+ resolvedSize.clampToMinimumSize(minimumSize);
+
+ if (!resolvedSize.isEmpty())
+ return resolvedSize;
// If the image has one of either an intrinsic width or an intrinsic height:
// * and an intrinsic aspect ratio, then the missing dimension is calculated from the given dimension and the ratio.
// * and no intrinsic aspect ratio, then the missing dimension is assumed to be the size of the rectangle that
// establishes the coordinate system for the 'background-position' property.
- if ((resolvedWidth && !resolvedHeight) || (!resolvedWidth && resolvedHeight))
- return resolveAgainstIntrinsicWidthOrHeightAndRatio(positioningAreaSize, intrinsicRatio, resolvedWidth, resolvedHeight);
+ if (resolvedSize.width() > 0 || resolvedSize.height() > 0)
+ return resolveAgainstIntrinsicWidthOrHeightAndRatio(positioningAreaSize, intrinsicRatio, resolvedSize.width(), resolvedSize.height());
// If the image has no intrinsic dimensions and has an intrinsic ratio the dimensions must be assumed to be the
// largest dimensions at that ratio such that neither dimension exceeds the dimensions of the rectangle that
// establishes the coordinate system for the 'background-position' property.
- if (!resolvedWidth && !resolvedHeight && !intrinsicRatio.isEmpty())
+ if (!intrinsicRatio.isEmpty())
return resolveAgainstIntrinsicRatio(positioningAreaSize, intrinsicRatio);
// If the image has no intrinsic ratio either, then the dimensions must be assumed to be the rectangle that
@@ -988,7 +1069,8 @@ IntSize RenderBoxModelObject::calculateFillTileSize(const FillLayer* fillLayer,
EFillSizeType type = fillLayer->size().type;
IntSize imageIntrinsicSize = calculateImageIntrinsicDimensions(image, positioningAreaSize);
-
+ imageIntrinsicSize.scale(1 / image->imageScaleFactor(), 1 / image->imageScaleFactor());
+ RenderView* renderView = view();
switch (type) {
case SizeLength: {
int w = positioningAreaSize.width();
@@ -999,13 +1081,13 @@ IntSize RenderBoxModelObject::calculateFillTileSize(const FillLayer* fillLayer,
if (layerWidth.isFixed())
w = layerWidth.value();
- else if (layerWidth.isPercent())
- w = layerWidth.calcValue(positioningAreaSize.width());
+ else if (layerWidth.isPercent() || layerHeight.isViewportPercentage())
+ w = valueForLength(layerWidth, positioningAreaSize.width(), renderView);
if (layerHeight.isFixed())
h = layerHeight.value();
- else if (layerHeight.isPercent())
- h = layerHeight.calcValue(positioningAreaSize.height());
+ else if (layerHeight.isPercent() || layerHeight.isViewportPercentage())
+ h = valueForLength(layerHeight, positioningAreaSize.height(), renderView);
// If one of the values is auto we have to use the appropriate
// scale to maintain our aspect ratio.
@@ -1083,6 +1165,7 @@ void RenderBoxModelObject::calculateBackgroundImageGeometry(const FillLayer* fil
LayoutUnit left = 0;
LayoutUnit top = 0;
IntSize positioningAreaSize;
+ IntRect snappedPaintRect = pixelSnappedIntRect(paintRect);
// Determine the background positioning area and set destRect to the background painting area.
// destRect will be adjusted later if the background is non-repeating.
@@ -1099,7 +1182,7 @@ void RenderBoxModelObject::calculateBackgroundImageGeometry(const FillLayer* fil
#endif
if (!fixedAttachment) {
- geometry.setDestRect(paintRect);
+ geometry.setDestRect(snappedPaintRect);
LayoutUnit right = 0;
LayoutUnit bottom = 0;
@@ -1121,11 +1204,13 @@ void RenderBoxModelObject::calculateBackgroundImageGeometry(const FillLayer* fil
// its margins. Since those were added in already, we have to factor them out when computing
// the background positioning area.
if (isRoot()) {
- positioningAreaSize = LayoutSize(toRenderBox(this)->width() - left - right, toRenderBox(this)->height() - top - bottom);
+ positioningAreaSize = IntSize(snapSizeToPixel(toRenderBox(this)->width() - left - right, toRenderBox(this)->x()),
+ snapSizeToPixel(toRenderBox(this)->height() - top - bottom, toRenderBox(this)->y()));
left += marginLeft();
top += marginTop();
} else
- positioningAreaSize = LayoutSize(paintRect.width() - left - right, paintRect.height() - top - bottom);
+ positioningAreaSize = IntSize(snapSizeToPixel(paintRect.width() - left - right, paintRect.x()),
+ snapSizeToPixel(paintRect.height() - top - bottom, paintRect.y()));
} else {
geometry.setDestRect(pixelSnappedIntRect(viewRect()));
positioningAreaSize = geometry.destRect().size();
@@ -1137,33 +1222,34 @@ void RenderBoxModelObject::calculateBackgroundImageGeometry(const FillLayer* fil
EFillRepeat backgroundRepeatX = fillLayer->repeatX();
EFillRepeat backgroundRepeatY = fillLayer->repeatY();
+ RenderView* renderView = view();
- LayoutUnit xPosition = fillLayer->xPosition().calcMinValue(positioningAreaSize.width() - geometry.tileSize().width(), true);
+ LayoutUnit xPosition = minimumValueForLength(fillLayer->xPosition(), positioningAreaSize.width() - geometry.tileSize().width(), renderView, true);
if (backgroundRepeatX == RepeatFill)
- geometry.setPhaseX(geometry.tileSize().width() ? layoutMod(geometry.tileSize().width() - (xPosition + left), geometry.tileSize().width()) : LayoutUnit(0));
+ geometry.setPhaseX(geometry.tileSize().width() ? geometry.tileSize().width() - roundToInt(xPosition + left) % geometry.tileSize().width() : 0);
else
geometry.setNoRepeatX(xPosition + left);
- LayoutUnit yPosition = fillLayer->yPosition().calcMinValue(positioningAreaSize.height() - geometry.tileSize().height(), true);
+ LayoutUnit yPosition = minimumValueForLength(fillLayer->yPosition(), positioningAreaSize.height() - geometry.tileSize().height(), renderView, true);
if (backgroundRepeatY == RepeatFill)
- geometry.setPhaseY(geometry.tileSize().height() ? layoutMod(geometry.tileSize().height() - (yPosition + top), geometry.tileSize().height()) : LayoutUnit(0));
+ geometry.setPhaseY(geometry.tileSize().height() ? geometry.tileSize().height() - roundToInt(yPosition + top) % geometry.tileSize().height() : 0);
else
geometry.setNoRepeatY(yPosition + top);
if (fixedAttachment)
- geometry.useFixedAttachment(paintRect.location());
+ geometry.useFixedAttachment(snappedPaintRect.location());
- geometry.clip(paintRect);
+ geometry.clip(snappedPaintRect);
geometry.setDestOrigin(geometry.destRect().location());
}
-static LayoutUnit computeBorderImageSide(Length borderSlice, LayoutUnit borderSide, LayoutUnit imageSide, LayoutUnit boxExtent)
+static LayoutUnit computeBorderImageSide(Length borderSlice, LayoutUnit borderSide, LayoutUnit imageSide, LayoutUnit boxExtent, RenderView* renderView)
{
if (borderSlice.isRelative())
return borderSlice.value() * borderSide;
if (borderSlice.isAuto())
return imageSide;
- return borderSlice.calcValue(boxExtent);
+ return valueForLength(borderSlice, boxExtent, renderView);
}
bool RenderBoxModelObject::paintNinePieceImage(GraphicsContext* graphicsContext, const LayoutRect& rect, const RenderStyle* style,
@@ -1191,7 +1277,7 @@ bool RenderBoxModelObject::paintNinePieceImage(GraphicsContext* graphicsContext,
LayoutUnit bottomWithOutset = rect.maxY() + bottomOutset;
LayoutUnit leftWithOutset = rect.x() - leftOutset;
LayoutUnit rightWithOutset = rect.maxX() + rightOutset;
- LayoutRect borderImageRect = LayoutRect(leftWithOutset, topWithOutset, rightWithOutset - leftWithOutset, bottomWithOutset - topWithOutset);
+ IntRect borderImageRect = pixelSnappedIntRect(leftWithOutset, topWithOutset, rightWithOutset - leftWithOutset, bottomWithOutset - topWithOutset);
IntSize imageSize = calculateImageIntrinsicDimensions(styleImage, borderImageRect.size());
@@ -1200,19 +1286,21 @@ bool RenderBoxModelObject::paintNinePieceImage(GraphicsContext* graphicsContext,
int imageWidth = imageSize.width() / style->effectiveZoom();
int imageHeight = imageSize.height() / style->effectiveZoom();
+ RenderView* renderView = view();
- int topSlice = min<int>(imageHeight, ninePieceImage.imageSlices().top().calcValue(imageHeight));
- int rightSlice = min<int>(imageWidth, ninePieceImage.imageSlices().right().calcValue(imageWidth));
- int bottomSlice = min<int>(imageHeight, ninePieceImage.imageSlices().bottom().calcValue(imageHeight));
- int leftSlice = min<int>(imageWidth, ninePieceImage.imageSlices().left().calcValue(imageWidth));
+ float imageScaleFactor = styleImage->imageScaleFactor();
+ int topSlice = min<int>(imageHeight, valueForLength(ninePieceImage.imageSlices().top(), imageHeight, renderView)) * imageScaleFactor;
+ int rightSlice = min<int>(imageWidth, valueForLength(ninePieceImage.imageSlices().right(), imageWidth, renderView)) * imageScaleFactor;
+ int bottomSlice = min<int>(imageHeight, valueForLength(ninePieceImage.imageSlices().bottom(), imageHeight, renderView)) * imageScaleFactor;
+ int leftSlice = min<int>(imageWidth, valueForLength(ninePieceImage.imageSlices().left(), imageWidth, renderView)) * imageScaleFactor;
ENinePieceImageRule hRule = ninePieceImage.horizontalRule();
ENinePieceImageRule vRule = ninePieceImage.verticalRule();
-
- LayoutUnit topWidth = computeBorderImageSide(ninePieceImage.borderSlices().top(), style->borderTopWidth(), topSlice, borderImageRect.height());
- LayoutUnit rightWidth = computeBorderImageSide(ninePieceImage.borderSlices().right(), style->borderRightWidth(), rightSlice, borderImageRect.width());
- LayoutUnit bottomWidth = computeBorderImageSide(ninePieceImage.borderSlices().bottom(), style->borderBottomWidth(), bottomSlice, borderImageRect.height());
- LayoutUnit leftWidth = computeBorderImageSide(ninePieceImage.borderSlices().left(), style->borderLeftWidth(), leftSlice, borderImageRect.width());
+
+ LayoutUnit topWidth = computeBorderImageSide(ninePieceImage.borderSlices().top(), style->borderTopWidth(), topSlice, borderImageRect.height(), renderView);
+ LayoutUnit rightWidth = computeBorderImageSide(ninePieceImage.borderSlices().right(), style->borderRightWidth(), rightSlice, borderImageRect.width(), renderView);
+ LayoutUnit bottomWidth = computeBorderImageSide(ninePieceImage.borderSlices().bottom(), style->borderBottomWidth(), bottomSlice, borderImageRect.height(), renderView);
+ LayoutUnit leftWidth = computeBorderImageSide(ninePieceImage.borderSlices().left(), style->borderLeftWidth(), leftSlice, borderImageRect.width(), renderView);
// Reduce the widths if they're too large.
// The spec says: Given Lwidth as the width of the border image area, Lheight as its height, and Wside as the border image width
@@ -1755,27 +1843,27 @@ void RenderBoxModelObject::paintBorder(const PaintInfo& info, const LayoutRect&
return;
BorderEdge edges[4];
- getBorderEdgeInfo(edges, includeLogicalLeftEdge, includeLogicalRightEdge);
-
- RoundedRect outerBorder = style->getRoundedBorderFor(rect, includeLogicalLeftEdge, includeLogicalRightEdge);
+ getBorderEdgeInfo(edges, style, includeLogicalLeftEdge, includeLogicalRightEdge);
+ RoundedRect outerBorder = style->getRoundedBorderFor(rect, view(), includeLogicalLeftEdge, includeLogicalRightEdge);
RoundedRect innerBorder = style->getRoundedInnerBorderFor(rect, includeLogicalLeftEdge, includeLogicalRightEdge);
bool haveAlphaColor = false;
bool haveAllSolidEdges = true;
- bool allEdgesVisible = true;
+ bool haveAllDoubleEdges = true;
+ int numEdgesVisible = 4;
bool allEdgesShareColor = true;
int firstVisibleEdge = -1;
for (int i = BSTop; i <= BSLeft; ++i) {
const BorderEdge& currEdge = edges[i];
if (currEdge.presentButInvisible()) {
- allEdgesVisible = false;
+ --numEdgesVisible;
allEdgesShareColor = false;
continue;
}
if (!currEdge.width) {
- allEdgesVisible = false;
+ --numEdgesVisible;
continue;
}
@@ -1789,6 +1877,9 @@ void RenderBoxModelObject::paintBorder(const PaintInfo& info, const LayoutRect&
if (currEdge.style != SOLID)
haveAllSolidEdges = false;
+
+ if (currEdge.style != DOUBLE)
+ haveAllDoubleEdges = false;
}
// If no corner intersects the clip region, we can pretend outerBorder is
@@ -1797,9 +1888,10 @@ void RenderBoxModelObject::paintBorder(const PaintInfo& info, const LayoutRect&
outerBorder.setRadii(RoundedRect::Radii());
// isRenderable() check avoids issue described in https://bugs.webkit.org/show_bug.cgi?id=38787
- if (haveAllSolidEdges && allEdgesShareColor && innerBorder.isRenderable()) {
- // Fast path for drawing all solid edges.
- if (allEdgesVisible && (outerBorder.isRounded() || haveAlphaColor)) {
+ if ((haveAllSolidEdges || haveAllDoubleEdges) && allEdgesShareColor && innerBorder.isRenderable()) {
+ // Fast path for drawing all solid edges and all unrounded double edges
+ if (numEdgesVisible == 4 && (outerBorder.isRounded() || haveAlphaColor)
+ && (haveAllSolidEdges || (!outerBorder.isRounded() && !innerBorder.isRounded()))) {
Path path;
if (outerBorder.isRounded() && bleedAvoidance != BackgroundBleedUseTransparencyLayer)
@@ -1807,6 +1899,45 @@ void RenderBoxModelObject::paintBorder(const PaintInfo& info, const LayoutRect&
else
path.addRect(outerBorder.rect());
+ if (haveAllDoubleEdges) {
+ IntRect innerThirdRect = outerBorder.rect();
+ IntRect outerThirdRect = outerBorder.rect();
+ for (int side = BSTop; side <= BSLeft; ++side) {
+ int outerWidth;
+ int innerWidth;
+ edges[side].getDoubleBorderStripeWidths(outerWidth, innerWidth);
+
+ if (side == BSTop) {
+ innerThirdRect.shiftYEdgeTo(innerThirdRect.y() + innerWidth);
+ outerThirdRect.shiftYEdgeTo(outerThirdRect.y() + outerWidth);
+ } else if (side == BSBottom) {
+ innerThirdRect.setHeight(innerThirdRect.height() - innerWidth);
+ outerThirdRect.setHeight(outerThirdRect.height() - outerWidth);
+ } else if (side == BSLeft) {
+ innerThirdRect.shiftXEdgeTo(innerThirdRect.x() + innerWidth);
+ outerThirdRect.shiftXEdgeTo(outerThirdRect.x() + outerWidth);
+ } else {
+ innerThirdRect.setWidth(innerThirdRect.width() - innerWidth);
+ outerThirdRect.setWidth(outerThirdRect.width() - outerWidth);
+ }
+ }
+
+ RoundedRect outerThird = outerBorder;
+ RoundedRect innerThird = innerBorder;
+ innerThird.setRect(innerThirdRect);
+ outerThird.setRect(outerThirdRect);
+
+ if (outerThird.isRounded() && bleedAvoidance != BackgroundBleedUseTransparencyLayer)
+ path.addRoundedRect(outerThird);
+ else
+ path.addRect(outerThird.rect());
+
+ if (innerThird.isRounded() && bleedAvoidance != BackgroundBleedUseTransparencyLayer)
+ path.addRoundedRect(innerThird);
+ else
+ path.addRect(innerThird.rect());
+ }
+
if (innerBorder.isRounded())
path.addRoundedRect(innerBorder);
else
@@ -1818,7 +1949,7 @@ void RenderBoxModelObject::paintBorder(const PaintInfo& info, const LayoutRect&
return;
}
// Avoid creating transparent layers
- if (!allEdgesVisible && !outerBorder.isRounded() && haveAlphaColor) {
+ if (haveAllSolidEdges && numEdgesVisible != 4 && !outerBorder.isRounded() && haveAlphaColor) {
Path path;
for (int i = BSTop; i <= BSLeft; ++i) {
@@ -1848,7 +1979,8 @@ void RenderBoxModelObject::paintBorder(const PaintInfo& info, const LayoutRect&
graphicsContext->clipOutRoundedRect(innerBorder);
}
- bool antialias = shouldAntialiasLines(graphicsContext);
+ // If only one edge visible antialiasing doesn't create seams
+ bool antialias = shouldAntialiasLines(graphicsContext) || numEdgesVisible == 1;
if (haveAlphaColor)
paintTranslucentBorderSides(graphicsContext, style, outerBorder, innerBorder, edges, bleedAvoidance, includeLogicalLeftEdge, includeLogicalRightEdge, antialias);
else
@@ -2042,7 +2174,7 @@ void RenderBoxModelObject::paintBorder(const PaintInfo& info, const IntRect& rec
GraphicsContextStateSaver stateSaver(*graphicsContext, false);
if (style->hasBorderRadius()) {
- border.includeLogicalEdges(style->getRoundedBorderFor(border.rect()).radii(),
+ border.includeLogicalEdges(style->getRoundedBorderFor(border.rect(), view()).radii(),
horizontal, includeLogicalLeftEdge, includeLogicalRightEdge);
if (border.isRounded()) {
stateSaver.save();
@@ -2560,9 +2692,8 @@ void RenderBoxModelObject::clipBorderSideForComplexInnerPath(GraphicsContext* gr
graphicsContext->clipOutRoundedRect(calculateAdjustedInnerBorder(innerBorder, side));
}
-void RenderBoxModelObject::getBorderEdgeInfo(BorderEdge edges[], bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
+void RenderBoxModelObject::getBorderEdgeInfo(BorderEdge edges[], const RenderStyle* style, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
{
- const RenderStyle* style = this->style();
bool horizontal = style->isHorizontalWritingMode();
edges[BSTop] = BorderEdge(style->borderTopWidth(),
@@ -2593,7 +2724,7 @@ void RenderBoxModelObject::getBorderEdgeInfo(BorderEdge edges[], bool includeLog
bool RenderBoxModelObject::borderObscuresBackgroundEdge(const FloatSize& contextScale) const
{
BorderEdge edges[4];
- getBorderEdgeInfo(edges);
+ getBorderEdgeInfo(edges, style());
for (int i = BSTop; i <= BSLeft; ++i) {
const BorderEdge& currEdge = edges[i];
@@ -2616,7 +2747,7 @@ bool RenderBoxModelObject::borderObscuresBackground() const
return false;
BorderEdge edges[4];
- getBorderEdgeInfo(edges);
+ getBorderEdgeInfo(edges, style());
for (int i = BSTop; i <= BSLeft; ++i) {
const BorderEdge& currEdge = edges[i];
@@ -2674,16 +2805,16 @@ bool RenderBoxModelObject::boxShadowShouldBeAppliedToBackground(BackgroundBleedA
return true;
}
-static inline LayoutRect areaCastingShadowInHole(const LayoutRect& holeRect, int shadowBlur, int shadowSpread, const LayoutSize& shadowOffset)
+static inline IntRect areaCastingShadowInHole(const IntRect& holeRect, int shadowBlur, int shadowSpread, const IntSize& shadowOffset)
{
- LayoutRect bounds(holeRect);
+ IntRect bounds(holeRect);
bounds.inflate(shadowBlur);
if (shadowSpread < 0)
bounds.inflate(-shadowSpread);
- LayoutRect offsetBounds = bounds;
+ IntRect offsetBounds = bounds;
offsetBounds.move(-shadowOffset);
return unionRect(bounds, offsetBounds);
}
@@ -2696,7 +2827,7 @@ void RenderBoxModelObject::paintBoxShadow(const PaintInfo& info, const LayoutRec
return;
RoundedRect border = (shadowStyle == Inset) ? s->getRoundedInnerBorderFor(paintRect, includeLogicalLeftEdge, includeLogicalRightEdge)
- : s->getRoundedBorderFor(paintRect, includeLogicalLeftEdge, includeLogicalRightEdge);
+ : s->getRoundedBorderFor(paintRect, view(), includeLogicalLeftEdge, includeLogicalRightEdge);
bool hasBorderRadius = s->hasBorderRadius();
bool isHorizontal = s->isHorizontalWritingMode();
@@ -2706,9 +2837,9 @@ void RenderBoxModelObject::paintBoxShadow(const PaintInfo& info, const LayoutRec
if (shadow->style() != shadowStyle)
continue;
- LayoutSize shadowOffset(shadow->x(), shadow->y());
- LayoutUnit shadowBlur = shadow->blur();
- LayoutUnit shadowSpread = shadow->spread();
+ IntSize shadowOffset(shadow->x(), shadow->y());
+ int shadowBlur = shadow->blur();
+ int shadowSpread = shadow->spread();
if (shadowOffset.isZero() && !shadowBlur && !shadowSpread)
continue;
@@ -2721,7 +2852,7 @@ void RenderBoxModelObject::paintBoxShadow(const PaintInfo& info, const LayoutRec
if (fillRect.isEmpty())
continue;
- LayoutRect shadowRect(border.rect());
+ IntRect shadowRect(border.rect());
shadowRect.inflate(shadowBlur + shadowSpread);
shadowRect.move(shadowOffset);
@@ -2730,7 +2861,7 @@ void RenderBoxModelObject::paintBoxShadow(const PaintInfo& info, const LayoutRec
// Move the fill just outside the clip, adding 1 pixel separation so that the fill does not
// bleed in (due to antialiasing) if the context is transformed.
- LayoutSize extraOffset(paintRect.width() + max<LayoutUnit>(0, shadowOffset.width()) + shadowBlur + 2 * shadowSpread + 1, 0);
+ IntSize extraOffset(paintRect.pixelSnappedWidth() + max(0, shadowOffset.width()) + shadowBlur + 2 * shadowSpread + 1, 0);
shadowOffset -= extraOffset;
fillRect.move(extraOffset);
@@ -2752,7 +2883,7 @@ void RenderBoxModelObject::paintBoxShadow(const PaintInfo& info, const LayoutRec
if (!rectToClipOut.isEmpty())
context->clipOutRoundedRect(rectToClipOut);
- RoundedRect influenceRect(pixelSnappedIntRect(shadowRect), border.radii());
+ RoundedRect influenceRect(shadowRect, border.radii());
influenceRect.expandRadii(2 * shadowBlur + shadowSpread);
if (allCornersClippedOut(influenceRect, info.rect))
context->fillRect(fillRect.rect(), Color::black, s->colorSpace());
@@ -2761,7 +2892,7 @@ void RenderBoxModelObject::paintBoxShadow(const PaintInfo& info, const LayoutRec
context->fillRoundedRect(fillRect, Color::black, s->colorSpace());
}
} else {
- LayoutRect rectToClipOut = border.rect();
+ IntRect rectToClipOut = border.rect();
// If the box is opaque, it is unnecessary to clip it out. However, doing so saves time
// when painting the shadow. On the other hand, it introduces subpixel gaps along the
@@ -2776,12 +2907,12 @@ void RenderBoxModelObject::paintBoxShadow(const PaintInfo& info, const LayoutRec
}
if (!rectToClipOut.isEmpty())
- context->clipOut(pixelSnappedIntRect(rectToClipOut));
+ context->clipOut(rectToClipOut);
context->fillRect(fillRect.rect(), Color::black, s->colorSpace());
}
} else {
// Inset shadow.
- LayoutRect holeRect(border.rect());
+ IntRect holeRect(border.rect());
holeRect.inflate(-shadowSpread);
if (holeRect.isEmpty()) {
@@ -2794,24 +2925,24 @@ void RenderBoxModelObject::paintBoxShadow(const PaintInfo& info, const LayoutRec
if (!includeLogicalLeftEdge) {
if (isHorizontal) {
- holeRect.move(-max<LayoutUnit>(shadowOffset.width(), 0) - shadowBlur, 0);
- holeRect.setWidth(holeRect.width() + max<LayoutUnit>(shadowOffset.width(), 0) + shadowBlur);
+ holeRect.move(-max(shadowOffset.width(), 0) - shadowBlur, 0);
+ holeRect.setWidth(holeRect.width() + max(shadowOffset.width(), 0) + shadowBlur);
} else {
- holeRect.move(0, -max<LayoutUnit>(shadowOffset.height(), 0) - shadowBlur);
- holeRect.setHeight(holeRect.height() + max<LayoutUnit>(shadowOffset.height(), 0) + shadowBlur);
+ holeRect.move(0, -max(shadowOffset.height(), 0) - shadowBlur);
+ holeRect.setHeight(holeRect.height() + max(shadowOffset.height(), 0) + shadowBlur);
}
}
if (!includeLogicalRightEdge) {
if (isHorizontal)
- holeRect.setWidth(holeRect.width() - min<LayoutUnit>(shadowOffset.width(), 0) + shadowBlur);
+ holeRect.setWidth(holeRect.width() - min(shadowOffset.width(), 0) + shadowBlur);
else
- holeRect.setHeight(holeRect.height() - min<LayoutUnit>(shadowOffset.height(), 0) + shadowBlur);
+ holeRect.setHeight(holeRect.height() - min(shadowOffset.height(), 0) + shadowBlur);
}
Color fillColor(shadowColor.red(), shadowColor.green(), shadowColor.blue(), 255);
- LayoutRect outerRect = areaCastingShadowInHole(border.rect(), shadowBlur, shadowSpread, shadowOffset);
- RoundedRect roundedHole(pixelSnappedIntRect(holeRect), border.radii());
+ IntRect outerRect = areaCastingShadowInHole(border.rect(), shadowBlur, shadowSpread, shadowOffset);
+ RoundedRect roundedHole(holeRect, border.radii());
GraphicsContextStateSaver stateSaver(*context);
if (hasBorderRadius) {
@@ -2822,7 +2953,7 @@ void RenderBoxModelObject::paintBoxShadow(const PaintInfo& info, const LayoutRec
} else
context->clip(border.rect());
- LayoutSize extraOffset(2 * paintRect.width() + max<LayoutUnit>(0, shadowOffset.width()) + shadowBlur - 2 * shadowSpread + 1, 0);
+ IntSize extraOffset(2 * paintRect.pixelSnappedWidth() + max(0, shadowOffset.width()) + shadowBlur - 2 * shadowSpread + 1, 0);
context->translate(extraOffset.width(), extraOffset.height());
shadowOffset -= extraOffset;
@@ -2831,7 +2962,7 @@ void RenderBoxModelObject::paintBoxShadow(const PaintInfo& info, const LayoutRec
else
context->setShadow(shadowOffset, shadowBlur, shadowColor, s->colorSpace());
- context->fillRectWithRoundedHole(pixelSnappedIntRect(outerRect), roundedHole, fillColor, s->colorSpace());
+ context->fillRectWithRoundedHole(outerRect, roundedHole, fillColor, s->colorSpace());
}
}
}
diff --git a/Source/WebCore/rendering/RenderBoxModelObject.h b/Source/WebCore/rendering/RenderBoxModelObject.h
index 553584769..8e7fdb088 100644
--- a/Source/WebCore/rendering/RenderBoxModelObject.h
+++ b/Source/WebCore/rendering/RenderBoxModelObject.h
@@ -40,7 +40,15 @@ enum BackgroundBleedAvoidance {
BackgroundBleedUseTransparencyLayer
};
-enum PaddingOptions { IncludeIntrinsicPadding, ExcludeIntrinsicPadding };
+enum ContentChangeType {
+ ImageChanged,
+ MaskImageChanged,
+ CanvasChanged,
+ VideoChanged,
+ FullScreenChanged
+};
+
+class KeyframeList;
// This class is the base for all objects that adhere to the CSS box model as described
// at http://www.w3.org/TR/CSS21/box.html
@@ -64,7 +72,6 @@ public:
int pixelSnappedOffsetLeft() const { return roundToInt(offsetLeft()); }
int pixelSnappedOffsetTop() const { return roundToInt(offsetTop()); }
- // FIXME: The implementation for these functions will change once we move to subpixel layout. See bug 60318.
int pixelSnappedOffsetWidth() const;
int pixelSnappedOffsetHeight() const;
@@ -74,20 +81,31 @@ public:
bool hasSelfPaintingLayer() const;
RenderLayer* layer() const { return m_layer; }
- virtual bool requiresLayer() const { return isRoot() || isPositioned() || isRelPositioned() || isTransparent() || hasTransform() || hasMask() || hasReflection() || hasFilter() || style()->specifiesColumns(); }
+ virtual bool requiresLayer() const { return isRoot() || isPositioned() || isRelPositioned() || isTransparent() || hasTransform() || hasHiddenBackface() || hasMask() || hasReflection() || hasFilter() || style()->specifiesColumns(); }
// This will work on inlines to return the bounding box of all of the lines' border boxes.
- virtual LayoutRect borderBoundingBox() const = 0;
-
- // Virtual since table cells override
- virtual LayoutUnit paddingTop(PaddingOptions = IncludeIntrinsicPadding) const;
- virtual LayoutUnit paddingBottom(PaddingOptions = IncludeIntrinsicPadding) const;
- virtual LayoutUnit paddingLeft(PaddingOptions = IncludeIntrinsicPadding) const;
- virtual LayoutUnit paddingRight(PaddingOptions = IncludeIntrinsicPadding) const;
- virtual LayoutUnit paddingBefore(PaddingOptions = IncludeIntrinsicPadding) const;
- virtual LayoutUnit paddingAfter(PaddingOptions = IncludeIntrinsicPadding) const;
- virtual LayoutUnit paddingStart(PaddingOptions = IncludeIntrinsicPadding) const;
- virtual LayoutUnit paddingEnd(PaddingOptions = IncludeIntrinsicPadding) const;
+ virtual IntRect borderBoundingBox() const = 0;
+
+ // These return the CSS computed padding values.
+ LayoutUnit computedCSSPaddingTop() const;
+ LayoutUnit computedCSSPaddingBottom() const;
+ LayoutUnit computedCSSPaddingLeft() const;
+ LayoutUnit computedCSSPaddingRight() const;
+ LayoutUnit computedCSSPaddingBefore() const;
+ LayoutUnit computedCSSPaddingAfter() const;
+ LayoutUnit computedCSSPaddingStart() const;
+ LayoutUnit computedCSSPaddingEnd() const;
+
+ // These functions are used during layout. Table cells and the MathML
+ // code override them to include some extra intrinsic padding.
+ virtual LayoutUnit paddingTop() const { return computedCSSPaddingTop(); }
+ virtual LayoutUnit paddingBottom() const { return computedCSSPaddingBottom(); }
+ virtual LayoutUnit paddingLeft() const { return computedCSSPaddingLeft(); }
+ virtual LayoutUnit paddingRight() const { return computedCSSPaddingRight(); }
+ virtual LayoutUnit paddingBefore() const { return computedCSSPaddingBefore(); }
+ virtual LayoutUnit paddingAfter() const { return computedCSSPaddingAfter(); }
+ virtual LayoutUnit paddingStart() const { return computedCSSPaddingStart(); }
+ virtual LayoutUnit paddingEnd() const { return computedCSSPaddingEnd(); }
virtual int borderTop() const { return style()->borderTopWidth(); }
virtual int borderBottom() const { return style()->borderBottomWidth(); }
@@ -146,6 +164,21 @@ public:
virtual void setSelectionState(SelectionState s);
+#if USE(ACCELERATED_COMPOSITING)
+ void contentChanged(ContentChangeType);
+ bool hasAcceleratedCompositing() const;
+
+ bool startTransition(double, CSSPropertyID, const RenderStyle* fromStyle, const RenderStyle* toStyle);
+ void transitionPaused(double timeOffset, CSSPropertyID);
+ void transitionFinished(CSSPropertyID);
+
+ bool startAnimation(double timeOffset, const Animation*, const KeyframeList& keyframes);
+ void animationPaused(double timeOffset, const String& name);
+ void animationFinished(const String& name);
+
+ void suspendAnimations(double time = 0);
+#endif
+
protected:
virtual void willBeDestroyed();
@@ -195,7 +228,7 @@ protected:
};
void calculateBackgroundImageGeometry(const FillLayer*, const LayoutRect& paintRect, BackgroundImageGeometry&);
- void getBorderEdgeInfo(class BorderEdge[], bool includeLogicalLeftEdge = true, bool includeLogicalRightEdge = true) const;
+ void getBorderEdgeInfo(class BorderEdge[], const RenderStyle*, bool includeLogicalLeftEdge = true, bool includeLogicalRightEdge = true) const;
bool borderObscuresBackgroundEdge(const FloatSize& contextScale) const;
bool borderObscuresBackground() const;
@@ -211,8 +244,6 @@ public:
RenderObject* firstLetterRemainingText() const;
void setFirstLetterRemainingText(RenderObject*);
- void ensureLayer();
-
private:
virtual bool isBoxModelObject() const { return true; }
diff --git a/Source/WebCore/rendering/RenderButton.cpp b/Source/WebCore/rendering/RenderButton.cpp
index 380c5da35..5477f9e50 100644
--- a/Source/WebCore/rendering/RenderButton.cpp
+++ b/Source/WebCore/rendering/RenderButton.cpp
@@ -49,8 +49,7 @@ void RenderButton::addChild(RenderObject* newChild, RenderObject* beforeChild)
if (!m_inner) {
// Create an anonymous block.
ASSERT(!firstChild());
- bool isFlexibleBox = style()->display() == BOX || style()->display() == INLINE_BOX;
- m_inner = createAnonymousBlock(isFlexibleBox);
+ m_inner = createAnonymousBlock(style()->display());
setupInnerStyle(m_inner->style());
RenderDeprecatedFlexibleBox::addChild(m_inner);
}
diff --git a/Source/WebCore/rendering/RenderButton.h b/Source/WebCore/rendering/RenderButton.h
index fb94af988..5be62b012 100644
--- a/Source/WebCore/rendering/RenderButton.h
+++ b/Source/WebCore/rendering/RenderButton.h
@@ -40,6 +40,8 @@ public:
virtual const char* renderName() const { return "RenderButton"; }
virtual bool isRenderButton() const { return true; }
+ virtual bool canBeSelectionLeaf() const OVERRIDE { return node() && node()->rendererIsEditable(); }
+
virtual void addChild(RenderObject* newChild, RenderObject *beforeChild = 0);
virtual void removeChild(RenderObject*);
virtual void removeLeftoverAnonymousBlock(RenderBlock*) { }
diff --git a/Source/WebCore/rendering/RenderCounter.cpp b/Source/WebCore/rendering/RenderCounter.cpp
index 0807ea9dd..29c0f1ccb 100644
--- a/Source/WebCore/rendering/RenderCounter.cpp
+++ b/Source/WebCore/rendering/RenderCounter.cpp
@@ -41,7 +41,7 @@ namespace WebCore {
using namespace HTMLNames;
typedef HashMap<RefPtr<AtomicStringImpl>, RefPtr<CounterNode> > CounterMap;
-typedef HashMap<const RenderObject*, CounterMap*> CounterMaps;
+typedef HashMap<const RenderObject*, OwnPtr<CounterMap> > CounterMaps;
static CounterNode* makeCounterNode(RenderObject*, const AtomicString& identifier, bool alwaysCreateCounter);
@@ -440,7 +440,7 @@ static CounterNode* makeCounterNode(RenderObject* object, const AtomicString& id
nodeMap = counterMaps().get(object);
else {
nodeMap = new CounterMap;
- counterMaps().set(object, nodeMap);
+ counterMaps().set(object, adoptPtr(nodeMap));
object->setHasCounterNodeMap(true);
}
nodeMap->set(identifier.impl(), newNode);
@@ -563,14 +563,13 @@ void RenderCounter::destroyCounterNodes(RenderObject* owner)
CounterMaps::iterator mapsIterator = maps.find(owner);
if (mapsIterator == maps.end())
return;
- CounterMap* map = mapsIterator->second;
+ CounterMap* map = mapsIterator->second.get();
CounterMap::const_iterator end = map->end();
for (CounterMap::const_iterator it = map->begin(); it != end; ++it) {
AtomicString identifier(it->first.get());
destroyCounterNodeWithoutMapRemoval(identifier, it->second.get());
}
maps.remove(mapsIterator);
- delete map;
owner->setHasCounterNodeMap(false);
}
diff --git a/Source/WebCore/rendering/RenderDeprecatedFlexibleBox.cpp b/Source/WebCore/rendering/RenderDeprecatedFlexibleBox.cpp
index add01a0c2..b956d3946 100644
--- a/Source/WebCore/rendering/RenderDeprecatedFlexibleBox.cpp
+++ b/Source/WebCore/rendering/RenderDeprecatedFlexibleBox.cpp
@@ -218,7 +218,7 @@ void RenderDeprecatedFlexibleBox::computePreferredLogicalWidths()
setPreferredLogicalWidthsDirty(false);
}
-void RenderDeprecatedFlexibleBox::layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeight, BlockLayoutPass layoutPass)
+void RenderDeprecatedFlexibleBox::layoutBlock(bool relayoutChildren, LayoutUnit)
{
ASSERT(needsLayout());
@@ -272,7 +272,7 @@ void RenderDeprecatedFlexibleBox::layoutBlock(bool relayoutChildren, LayoutUnit
if (previousSize.height() != height())
relayoutChildren = true;
- bool needAnotherLayoutPass = layoutPositionedObjects(relayoutChildren || isRoot());
+ layoutPositionedObjects(relayoutChildren || isRoot());
computeRegionRangeForBlock();
@@ -305,16 +305,13 @@ void RenderDeprecatedFlexibleBox::layoutBlock(bool relayoutChildren, LayoutUnit
// Update our scrollbars if we're overflow:auto/scroll/hidden now that we know if
// we overflow or not.
- updateScrollInfoAfterLayout();
+ if (hasOverflowClip())
+ layer()->updateScrollInfoAfterLayout();
// Repaint with our new bounds if they are different from our old bounds.
repainter.repaintAfterLayout();
- if (needAnotherLayoutPass && layoutPass == NormalLayoutPass) {
- setChildNeedsLayout(true, false);
- layoutBlock(false, pageLogicalHeight);
- } else
- setNeedsLayout(false);
+ setNeedsLayout(false);
}
// The first walk over our kids is to find out if we have any flexible children.
@@ -327,7 +324,7 @@ static void gatherFlexChildrenInfo(FlexBoxIterator& iterator, bool relayoutChild
// may have changed, and we need to reallocate space.
child->clearOverrideSize();
if (!relayoutChildren)
- child->setChildNeedsLayout(true, false);
+ child->setChildNeedsLayout(true, MarkOnlyThis);
haveFlex = true;
unsigned int flexGroup = child->style()->boxFlexGroup();
if (lowestFlexGroup == 0)
@@ -374,7 +371,7 @@ void RenderDeprecatedFlexibleBox::layoutHorizontalBox(bool relayoutChildren)
for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
// make sure we relayout children if we need it.
if (relayoutChildren || (child->isReplaced() && (child->style()->width().isPercent() || child->style()->height().isPercent())))
- child->setChildNeedsLayout(true, false);
+ child->setChildNeedsLayout(true, MarkOnlyThis);
if (child->isPositioned())
continue;
@@ -431,7 +428,7 @@ void RenderDeprecatedFlexibleBox::layoutHorizontalBox(bool relayoutChildren)
if (childLayer->staticBlockPosition() != yPos) {
childLayer->setStaticBlockPosition(yPos);
if (child->style()->hasStaticBlockPosition(style()->isHorizontalWritingMode()))
- child->setChildNeedsLayout(true, false);
+ child->setChildNeedsLayout(true, MarkOnlyThis);
}
continue;
} else if (child->style()->visibility() == COLLAPSE) {
@@ -448,7 +445,7 @@ void RenderDeprecatedFlexibleBox::layoutHorizontalBox(bool relayoutChildren)
LayoutUnit oldChildHeight = child->height();
child->computeLogicalHeight();
if (oldChildHeight != child->height())
- child->setChildNeedsLayout(true, false);
+ child->setChildNeedsLayout(true, MarkOnlyThis);
if (!child->needsLayout())
child->markForPaginationRelayoutIfNeeded();
@@ -517,7 +514,7 @@ void RenderDeprecatedFlexibleBox::layoutHorizontalBox(bool relayoutChildren)
for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
LayoutUnit allowedFlex = allowedChildFlex(child, expanding, i);
if (allowedFlex) {
- LayoutUnit projectedFlex = (allowedFlex == numeric_limits<LayoutUnit>::max()) ? allowedFlex : LayoutUnit(allowedFlex * (totalFlex / child->style()->boxFlex()));
+ LayoutUnit projectedFlex = (allowedFlex == MAX_LAYOUT_UNIT) ? allowedFlex : LayoutUnit(allowedFlex * (totalFlex / child->style()->boxFlex()));
spaceAvailableThisPass = expanding ? min(spaceAvailableThisPass, projectedFlex) : max(spaceAvailableThisPass, projectedFlex);
}
}
@@ -562,7 +559,7 @@ void RenderDeprecatedFlexibleBox::layoutHorizontalBox(bool relayoutChildren)
}
}
}
- } while (groupRemainingSpace);
+ } while (absoluteValue(groupRemainingSpace) >= 1);
}
// We didn't find any children that could grow.
@@ -663,7 +660,7 @@ void RenderDeprecatedFlexibleBox::layoutVerticalBox(bool relayoutChildren)
for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
// Make sure we relayout children if we need it.
if (!haveLineClamp && (relayoutChildren || (child->isReplaced() && (child->style()->width().isPercent() || child->style()->height().isPercent()))))
- child->setChildNeedsLayout(true, false);
+ child->setChildNeedsLayout(true, MarkOnlyThis);
if (child->isPositioned()) {
child->containingBlock()->insertPositionedObject(child);
@@ -672,7 +669,7 @@ void RenderDeprecatedFlexibleBox::layoutVerticalBox(bool relayoutChildren)
if (childLayer->staticBlockPosition() != height()) {
childLayer->setStaticBlockPosition(height());
if (child->style()->hasStaticBlockPosition(style()->isHorizontalWritingMode()))
- child->setChildNeedsLayout(true, false);
+ child->setChildNeedsLayout(true, MarkOnlyThis);
}
continue;
} else if (child->style()->visibility() == COLLAPSE) {
@@ -771,7 +768,7 @@ void RenderDeprecatedFlexibleBox::layoutVerticalBox(bool relayoutChildren)
for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
LayoutUnit allowedFlex = allowedChildFlex(child, expanding, i);
if (allowedFlex) {
- LayoutUnit projectedFlex = (allowedFlex == numeric_limits<LayoutUnit>::max()) ? allowedFlex : static_cast<LayoutUnit>(allowedFlex * (totalFlex / child->style()->boxFlex()));
+ LayoutUnit projectedFlex = (allowedFlex == MAX_LAYOUT_UNIT) ? allowedFlex : static_cast<LayoutUnit>(allowedFlex * (totalFlex / child->style()->boxFlex()));
spaceAvailableThisPass = expanding ? min(spaceAvailableThisPass, projectedFlex) : max(spaceAvailableThisPass, projectedFlex);
}
}
@@ -813,7 +810,7 @@ void RenderDeprecatedFlexibleBox::layoutVerticalBox(bool relayoutChildren)
}
}
}
- } while (groupRemainingSpace);
+ } while (absoluteValue(groupRemainingSpace) >= 1);
}
// We didn't find any children that could grow.
@@ -885,7 +882,7 @@ void RenderDeprecatedFlexibleBox::applyLineClamp(FlexBoxIterator& iterator, bool
if (relayoutChildren || (child->isReplaced() && (child->style()->width().isPercent() || child->style()->height().isPercent()))
|| (child->style()->height().isAuto() && child->isBlockFlow())) {
- child->setChildNeedsLayout(true, false);
+ child->setChildNeedsLayout(true, MarkOnlyThis);
// Dirty all the positioned objects.
if (child->isRenderBlock()) {
@@ -918,7 +915,7 @@ void RenderDeprecatedFlexibleBox::applyLineClamp(FlexBoxIterator& iterator, bool
if (newHeight == child->height())
continue;
- child->setChildNeedsLayout(true, false);
+ child->setChildNeedsLayout(true, MarkOnlyThis);
child->setOverrideHeight(newHeight);
m_flexingChildren = true;
child->layoutIfNeeded();
@@ -1000,7 +997,7 @@ LayoutUnit RenderDeprecatedFlexibleBox::allowedChildFlex(RenderBox* child, bool
if (expanding) {
if (isHorizontal()) {
// FIXME: For now just handle fixed values.
- LayoutUnit maxWidth = numeric_limits<LayoutUnit>::max();
+ LayoutUnit maxWidth = MAX_LAYOUT_UNIT;
LayoutUnit width = child->overrideWidth() - child->borderAndPaddingWidth();
if (!child->style()->maxWidth().isUndefined() && child->style()->maxWidth().isFixed())
maxWidth = child->style()->maxWidth().value();
@@ -1008,16 +1005,16 @@ LayoutUnit RenderDeprecatedFlexibleBox::allowedChildFlex(RenderBox* child, bool
maxWidth = child->maxPreferredLogicalWidth();
else if (child->style()->maxWidth().type() == MinIntrinsic)
maxWidth = child->minPreferredLogicalWidth();
- if (maxWidth == numeric_limits<LayoutUnit>::max())
+ if (maxWidth == MAX_LAYOUT_UNIT)
return maxWidth;
return max<LayoutUnit>(0, maxWidth - width);
} else {
// FIXME: For now just handle fixed values.
- LayoutUnit maxHeight = numeric_limits<LayoutUnit>::max();
+ LayoutUnit maxHeight = MAX_LAYOUT_UNIT;
LayoutUnit height = child->overrideHeight() - child->borderAndPaddingHeight();
if (!child->style()->maxHeight().isUndefined() && child->style()->maxHeight().isFixed())
maxHeight = child->style()->maxHeight().value();
- if (maxHeight == numeric_limits<LayoutUnit>::max())
+ if (maxHeight == MAX_LAYOUT_UNIT)
return maxHeight;
return max<LayoutUnit>(0, maxHeight - height);
}
diff --git a/Source/WebCore/rendering/RenderDeprecatedFlexibleBox.h b/Source/WebCore/rendering/RenderDeprecatedFlexibleBox.h
index 9a42bd401..4d912f430 100644
--- a/Source/WebCore/rendering/RenderDeprecatedFlexibleBox.h
+++ b/Source/WebCore/rendering/RenderDeprecatedFlexibleBox.h
@@ -40,7 +40,7 @@ public:
void calcHorizontalPrefWidths();
void calcVerticalPrefWidths();
- virtual void layoutBlock(bool relayoutChildren, LayoutUnit pageHeight = 0, BlockLayoutPass = NormalLayoutPass);
+ virtual void layoutBlock(bool relayoutChildren, LayoutUnit pageHeight = 0);
void layoutHorizontalBox(bool relayoutChildren);
void layoutVerticalBox(bool relayoutChildren);
diff --git a/Source/WebCore/rendering/RenderDetailsMarker.cpp b/Source/WebCore/rendering/RenderDetailsMarker.cpp
index bcffaac1c..c36cdd588 100644
--- a/Source/WebCore/rendering/RenderDetailsMarker.cpp
+++ b/Source/WebCore/rendering/RenderDetailsMarker.cpp
@@ -21,7 +21,7 @@
#include "config.h"
#include "RenderDetailsMarker.h"
-#if ENABLE(DETAILS)
+#if ENABLE(DETAILS) || ENABLE(CALENDAR_PICKER)
#include "Element.h"
#include "GraphicsContext.h"
@@ -105,10 +105,10 @@ Path RenderDetailsMarker::getCanonicalPath() const
return Path();
}
-Path RenderDetailsMarker::getPath(const IntPoint& origin) const
+Path RenderDetailsMarker::getPath(const LayoutPoint& origin) const
{
Path result = getCanonicalPath();
- result.transform(AffineTransform().scale(logicalHeight()));
+ result.transform(AffineTransform().scale(contentWidth(), contentHeight()));
result.translate(FloatSize(origin.x(), origin.y()));
return result;
}
@@ -134,14 +134,19 @@ void RenderDetailsMarker::paint(PaintInfo& paintInfo, const LayoutPoint& paintOf
paintInfo.context->setStrokeThickness(1.0f);
paintInfo.context->setFillColor(color, style()->colorSpace());
+ boxOrigin.move(borderLeft() + paddingLeft(), borderTop() + paddingTop());
paintInfo.context->fillPath(getPath(boxOrigin));
}
bool RenderDetailsMarker::isOpen() const
{
for (RenderObject* renderer = parent(); renderer; renderer = renderer->parent()) {
- if (renderer->node() && renderer->node()->hasTagName(detailsTag))
+ if (!renderer->node())
+ continue;
+ if (renderer->node()->hasTagName(detailsTag))
return !toElement(renderer->node())->getAttribute(openAttr).isNull();
+ if (renderer->node()->hasTagName(inputTag))
+ return true;
}
return false;
diff --git a/Source/WebCore/rendering/RenderDetailsMarker.h b/Source/WebCore/rendering/RenderDetailsMarker.h
index 3afac553b..76e2b28e4 100644
--- a/Source/WebCore/rendering/RenderDetailsMarker.h
+++ b/Source/WebCore/rendering/RenderDetailsMarker.h
@@ -21,7 +21,7 @@
#ifndef RenderDetailsMarker_h
#define RenderDetailsMarker_h
-#if ENABLE(DETAILS)
+#if ENABLE(DETAILS) || ENABLE(CALENDAR_PICKER)
#include "RenderBlock.h"
@@ -42,7 +42,7 @@ private:
bool isOpen() const;
Path getCanonicalPath() const;
- Path getPath(const IntPoint& origin) const;
+ Path getPath(const LayoutPoint& origin) const;
};
inline RenderDetailsMarker* toRenderDetailsMarker(RenderObject* object)
diff --git a/Source/WebCore/rendering/RenderEmbeddedObject.cpp b/Source/WebCore/rendering/RenderEmbeddedObject.cpp
index c239db277..2168a400a 100644
--- a/Source/WebCore/rendering/RenderEmbeddedObject.cpp
+++ b/Source/WebCore/rendering/RenderEmbeddedObject.cpp
@@ -53,10 +53,6 @@
#include "Text.h"
#include "TextRun.h"
-#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
-#include "HTMLVideoElement.h"
-#endif
-
namespace WebCore {
using namespace HTMLNames;
@@ -83,10 +79,6 @@ RenderEmbeddedObject::RenderEmbeddedObject(Element* element)
, m_mouseDownWasInMissingPluginIndicator(false)
{
view()->frameView()->setIsVisuallyNonEmpty();
-#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
- if (element->hasTagName(videoTag) || element->hasTagName(audioTag))
- setHasIntrinsicSize();
-#endif
}
RenderEmbeddedObject::~RenderEmbeddedObject()
@@ -269,16 +261,17 @@ bool RenderEmbeddedObject::nodeAtPoint(const HitTestRequest& request, HitTestRes
return true;
PluginViewBase* view = static_cast<PluginViewBase*>(widget());
+ IntPoint roundedPoint = roundedIntPoint(pointInContainer);
if (Scrollbar* horizontalScrollbar = view->horizontalScrollbar()) {
- if (horizontalScrollbar->shouldParticipateInHitTesting() && horizontalScrollbar->frameRect().contains(pointInContainer)) {
+ if (horizontalScrollbar->shouldParticipateInHitTesting() && horizontalScrollbar->frameRect().contains(roundedPoint)) {
result.setScrollbar(horizontalScrollbar);
return true;
}
}
if (Scrollbar* verticalScrollbar = view->verticalScrollbar()) {
- if (verticalScrollbar->shouldParticipateInHitTesting() && verticalScrollbar->frameRect().contains(pointInContainer)) {
+ if (verticalScrollbar->shouldParticipateInHitTesting() && verticalScrollbar->frameRect().contains(roundedPoint)) {
result.setScrollbar(verticalScrollbar);
return true;
}
diff --git a/Source/WebCore/rendering/RenderFieldset.cpp b/Source/WebCore/rendering/RenderFieldset.cpp
index 3b70e6a11..8870a872f 100644
--- a/Source/WebCore/rendering/RenderFieldset.cpp
+++ b/Source/WebCore/rendering/RenderFieldset.cpp
@@ -132,11 +132,11 @@ void RenderFieldset::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint
// cases the legend is embedded in the right and bottom borders respectively.
// https://bugs.webkit.org/show_bug.cgi?id=47236
if (style()->isHorizontalWritingMode()) {
- LayoutUnit yOff = (legend->y() > 0) ? zeroLayoutUnit : (legend->height() - borderTop()) / 2;
+ LayoutUnit yOff = (legend->y() > 0) ? ZERO_LAYOUT_UNIT : (legend->height() - borderTop()) / 2;
paintRect.setHeight(paintRect.height() - yOff);
paintRect.setY(paintRect.y() + yOff);
} else {
- LayoutUnit xOff = (legend->x() > 0) ? zeroLayoutUnit : (legend->width() - borderLeft()) / 2;
+ LayoutUnit xOff = (legend->x() > 0) ? ZERO_LAYOUT_UNIT : (legend->width() - borderLeft()) / 2;
paintRect.setWidth(paintRect.width() - xOff);
paintRect.setX(paintRect.x() + xOff);
}
@@ -159,11 +159,11 @@ void RenderFieldset::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint
if (style()->isHorizontalWritingMode()) {
LayoutUnit clipTop = paintRect.y();
LayoutUnit clipHeight = max(static_cast<LayoutUnit>(style()->borderTopWidth()), legend->height() - ((legend->height() - borderTop()) / 2));
- graphicsContext->clipOut(LayoutRect(paintRect.x() + legend->x(), clipTop, legend->width(), clipHeight));
+ graphicsContext->clipOut(pixelSnappedIntRect(paintRect.x() + legend->x(), clipTop, legend->width(), clipHeight));
} else {
LayoutUnit clipLeft = paintRect.x();
LayoutUnit clipWidth = max(static_cast<LayoutUnit>(style()->borderLeftWidth()), legend->width());
- graphicsContext->clipOut(LayoutRect(clipLeft, paintRect.y() + legend->y(), clipWidth, legend->height()));
+ graphicsContext->clipOut(pixelSnappedIntRect(clipLeft, paintRect.y() + legend->y(), clipWidth, legend->height()));
}
paintBorder(paintInfo, paintRect, style());
@@ -183,11 +183,11 @@ void RenderFieldset::paintMask(PaintInfo& paintInfo, const LayoutPoint& paintOff
// cases the legend is embedded in the right and bottom borders respectively.
// https://bugs.webkit.org/show_bug.cgi?id=47236
if (style()->isHorizontalWritingMode()) {
- LayoutUnit yOff = (legend->y() > 0) ? 0 : (legend->height() - borderTop()) / 2;
+ LayoutUnit yOff = (legend->y() > 0) ? ZERO_LAYOUT_UNIT : (legend->height() - borderTop()) / 2;
paintRect.expand(0, -yOff);
paintRect.move(0, yOff);
} else {
- LayoutUnit xOff = (legend->x() > 0) ? 0 : (legend->width() - borderLeft()) / 2;
+ LayoutUnit xOff = (legend->x() > 0) ? ZERO_LAYOUT_UNIT : (legend->width() - borderLeft()) / 2;
paintRect.expand(-xOff, 0);
paintRect.move(xOff, 0);
}
@@ -195,4 +195,13 @@ void RenderFieldset::paintMask(PaintInfo& paintInfo, const LayoutPoint& paintOff
paintMaskImages(paintInfo, paintRect);
}
+bool RenderFieldset::stretchesToMinIntrinsicLogicalWidth() const
+{
+ // If width is explicitly specified then Fieldsets should not stretch
+ if (style()->width().isPercent())
+ return false;
+
+ return true;
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/rendering/RenderFieldset.h b/Source/WebCore/rendering/RenderFieldset.h
index bd12c5553..12dbda502 100644
--- a/Source/WebCore/rendering/RenderFieldset.h
+++ b/Source/WebCore/rendering/RenderFieldset.h
@@ -42,7 +42,7 @@ private:
virtual void computePreferredLogicalWidths();
virtual bool avoidsFloats() const { return true; }
- virtual bool stretchesToMinIntrinsicLogicalWidth() const { return true; }
+ virtual bool stretchesToMinIntrinsicLogicalWidth() const OVERRIDE;
virtual void paintBoxDecorations(PaintInfo&, const LayoutPoint&);
virtual void paintMask(PaintInfo&, const LayoutPoint&);
diff --git a/Source/WebCore/rendering/RenderFileUploadControl.cpp b/Source/WebCore/rendering/RenderFileUploadControl.cpp
index 74e6f7de7..fd62630a8 100644
--- a/Source/WebCore/rendering/RenderFileUploadControl.cpp
+++ b/Source/WebCore/rendering/RenderFileUploadControl.cpp
@@ -21,6 +21,7 @@
#include "config.h"
#include "RenderFileUploadControl.h"
+#include "ElementShadow.h"
#include "FileList.h"
#include "GraphicsContext.h"
#include "HTMLInputElement.h"
@@ -32,7 +33,6 @@
#include "RenderText.h"
#include "RenderTheme.h"
#include "ShadowRoot.h"
-#include "ShadowTree.h"
#include "TextRun.h"
#include "VisiblePosition.h"
#include <math.h>
@@ -52,6 +52,7 @@ const int buttonShadowHeight = 2;
RenderFileUploadControl::RenderFileUploadControl(HTMLInputElement* input)
: RenderBlock(input)
+ , m_canReceiveDroppedFiles(input->canReceiveDroppedFiles())
{
}
@@ -72,8 +73,12 @@ void RenderFileUploadControl::updateFromElement()
// updateFromElement() eventually.
if (button->disabled() != newDisabled)
button->setDisabled(newDisabled);
-
- button->setActive(input->canReceiveDroppedFiles());
+
+ bool newCanReceiveDroppedFilesState = input->canReceiveDroppedFiles();
+ if (m_canReceiveDroppedFiles != newCanReceiveDroppedFilesState) {
+ m_canReceiveDroppedFiles = newCanReceiveDroppedFilesState;
+ button->setActive(newCanReceiveDroppedFilesState);
+ }
}
// This only supports clearing out the files, but that's OK because for
@@ -86,13 +91,13 @@ void RenderFileUploadControl::updateFromElement()
static int nodeWidth(Node* node)
{
- return node ? node->renderBox()->width() : zeroLayoutUnit;
+ return node ? node->renderBox()->pixelSnappedWidth() : 0;
}
int RenderFileUploadControl::maxFilenameWidth() const
{
HTMLInputElement* input = static_cast<HTMLInputElement*>(node());
- return max(0, contentWidth() - nodeWidth(uploadButton()) - afterButtonSpacing
+ return max(0, contentBoxRect().pixelSnappedWidth() - nodeWidth(uploadButton()) - afterButtonSpacing
- (input->icon() ? iconWidth + iconFilenameSpacing : 0));
}
@@ -104,7 +109,7 @@ void RenderFileUploadControl::paintObject(PaintInfo& paintInfo, const LayoutPoin
// Push a clip.
GraphicsContextStateSaver stateSaver(*paintInfo.context, false);
if (paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseChildBlockBackgrounds) {
- LayoutRect clipRect(paintOffset.x() + borderLeft(), paintOffset.y() + borderTop(),
+ IntRect clipRect = pixelSnappedIntRect(paintOffset.x() + borderLeft(), paintOffset.y() + borderTop(),
width() - borderLeft() - borderRight(), height() - borderBottom() - borderTop() + buttonShadowHeight);
if (clipRect.isEmpty())
return;
@@ -142,7 +147,7 @@ void RenderFileUploadControl::paintObject(PaintInfo& paintInfo, const LayoutPoin
paintInfo.context->setFillColor(style()->visitedDependentColor(CSSPropertyColor), style()->colorSpace());
// Draw the filename
- paintInfo.context->drawBidiText(font, textRun, LayoutPoint(textX, textY));
+ paintInfo.context->drawBidiText(font, textRun, IntPoint(roundToInt(textX), roundToInt(textY)));
if (input->icon()) {
// Determine where the icon should be placed
@@ -154,7 +159,7 @@ void RenderFileUploadControl::paintObject(PaintInfo& paintInfo, const LayoutPoin
iconX = contentLeft + contentWidth() - buttonWidth - afterButtonSpacing - iconWidth;
// Draw the file icon
- input->icon()->paint(paintInfo.context, LayoutRect(iconX, iconY, iconWidth, iconHeight));
+ input->icon()->paint(paintInfo.context, IntRect(roundToInt(iconX), roundToInt(iconY), iconWidth, iconHeight));
}
}
@@ -220,7 +225,7 @@ HTMLInputElement* RenderFileUploadControl::uploadButton() const
ASSERT(input->hasShadowRoot());
- Node* buttonNode = input->shadowTree()->oldestShadowRoot()->firstChild();
+ Node* buttonNode = input->shadow()->oldestShadowRoot()->firstChild();
return buttonNode && buttonNode->isHTMLElement() && buttonNode->hasTagName(inputTag) ? static_cast<HTMLInputElement*>(buttonNode) : 0;
}
@@ -236,7 +241,7 @@ String RenderFileUploadControl::fileTextValue() const
{
HTMLInputElement* input = static_cast<HTMLInputElement*>(node());
ASSERT(input->files());
- return theme()->fileListNameForWidth(input->files()->paths(), style()->font(), maxFilenameWidth(), input->multiple());
+ return theme()->fileListNameForWidth(input->files(), style()->font(), maxFilenameWidth(), input->multiple());
}
} // namespace WebCore
diff --git a/Source/WebCore/rendering/RenderFileUploadControl.h b/Source/WebCore/rendering/RenderFileUploadControl.h
index 11d959dac..11015eb90 100644
--- a/Source/WebCore/rendering/RenderFileUploadControl.h
+++ b/Source/WebCore/rendering/RenderFileUploadControl.h
@@ -55,6 +55,8 @@ private:
virtual VisiblePosition positionForPoint(const LayoutPoint&);
HTMLInputElement* uploadButton() const;
+
+ bool m_canReceiveDroppedFiles;
};
inline RenderFileUploadControl* toRenderFileUploadControl(RenderObject* object)
diff --git a/Source/WebCore/rendering/RenderFlexibleBox.cpp b/Source/WebCore/rendering/RenderFlexibleBox.cpp
index e9dd8381d..efa2eb71d 100644
--- a/Source/WebCore/rendering/RenderFlexibleBox.cpp
+++ b/Source/WebCore/rendering/RenderFlexibleBox.cpp
@@ -102,38 +102,30 @@ private:
Vector<int>::const_iterator m_orderValuesIterator;
};
-struct RenderFlexibleBox::WrapReverseContext {
- explicit WrapReverseContext(EFlexWrap flexWrap)
- : isWrapReverse(flexWrap == FlexWrapReverse)
+struct RenderFlexibleBox::LineContext {
+ LineContext(LayoutUnit crossAxisOffset, LayoutUnit crossAxisExtent, size_t numberOfChildren, LayoutUnit maxAscent)
+ : crossAxisOffset(crossAxisOffset)
+ , crossAxisExtent(crossAxisExtent)
+ , numberOfChildren(numberOfChildren)
+ , maxAscent(maxAscent)
{
}
- void addCrossAxisOffset(LayoutUnit offset)
- {
- if (!isWrapReverse)
- return;
- crossAxisOffsets.append(offset);
- }
-
- void addNumberOfChildrenOnLine(size_t numberOfChildren)
- {
- if (!isWrapReverse)
- return;
- childrenPerLine.append(numberOfChildren);
- }
+ LayoutUnit crossAxisOffset;
+ LayoutUnit crossAxisExtent;
+ size_t numberOfChildren;
+ LayoutUnit maxAscent;
+};
- LayoutUnit lineCrossAxisDelta(size_t line, LayoutUnit crossAxisContentExtent) const
+struct RenderFlexibleBox::Violation {
+ Violation(RenderBox* child, LayoutUnit childSize)
+ : child(child)
+ , childSize(childSize)
{
- ASSERT(line + 1 < crossAxisOffsets.size());
- LayoutUnit lineHeight = crossAxisOffsets[line + 1] - crossAxisOffsets[line];
- LayoutUnit originalOffset = crossAxisOffsets[line] - crossAxisOffsets[0];
- LayoutUnit newOffset = crossAxisContentExtent - originalOffset - lineHeight;
- return newOffset - originalOffset;
}
- WTF::Vector<LayoutUnit> crossAxisOffsets;
- WTF::Vector<size_t> childrenPerLine;
- bool isWrapReverse;
+ RenderBox* child;
+ LayoutUnit childSize;
};
@@ -188,11 +180,19 @@ void RenderFlexibleBox::computePreferredLogicalWidths()
minPreferredLogicalWidth += margin;
maxPreferredLogicalWidth += margin;
if (!isColumnFlow()) {
- m_minPreferredLogicalWidth += minPreferredLogicalWidth;
m_maxPreferredLogicalWidth += maxPreferredLogicalWidth;
+ if (isMultiline()) {
+ // For multiline, the min preferred width is if you put a break between each item.
+ m_minPreferredLogicalWidth = std::max(m_minPreferredLogicalWidth, minPreferredLogicalWidth);
+ } else
+ m_minPreferredLogicalWidth += minPreferredLogicalWidth;
} else {
m_minPreferredLogicalWidth = std::max(minPreferredLogicalWidth, m_minPreferredLogicalWidth);
- m_maxPreferredLogicalWidth = std::max(maxPreferredLogicalWidth, m_maxPreferredLogicalWidth);
+ if (isMultiline()) {
+ // For multiline, the max preferred width is if you put a break between each item.
+ m_maxPreferredLogicalWidth += maxPreferredLogicalWidth;
+ } else
+ m_maxPreferredLogicalWidth = std::max(maxPreferredLogicalWidth, m_maxPreferredLogicalWidth);
}
}
@@ -230,7 +230,7 @@ void RenderFlexibleBox::computePreferredLogicalWidths()
setPreferredLogicalWidthsDirty(false);
}
-void RenderFlexibleBox::layoutBlock(bool relayoutChildren, int, BlockLayoutPass)
+void RenderFlexibleBox::layoutBlock(bool relayoutChildren, LayoutUnit)
{
ASSERT(needsLayout());
@@ -247,12 +247,10 @@ void RenderFlexibleBox::layoutBlock(bool relayoutChildren, int, BlockLayoutPass)
}
computeInitialRegionRangeForBlock();
- IntSize previousSize = size();
+ LayoutSize previousSize = size();
setLogicalHeight(0);
- // We need to call both of these because we grab both crossAxisExtent and mainAxisExtent in layoutFlexItems.
computeLogicalWidth();
- computeLogicalHeight();
m_overflow.clear();
@@ -264,10 +262,15 @@ void RenderFlexibleBox::layoutBlock(bool relayoutChildren, int, BlockLayoutPass)
layer()->setHasVerticalScrollbar(true);
}
- layoutFlexItems(relayoutChildren);
+ WTF::Vector<LineContext> lineContexts;
+ FlexOrderHashSet flexOrderValues;
+ computeMainAxisPreferredSizes(relayoutChildren, flexOrderValues);
+ FlexOrderIterator flexIterator(this, flexOrderValues);
+ layoutFlexItems(flexIterator, lineContexts);
LayoutUnit oldClientAfterEdge = clientLogicalBottom();
computeLogicalHeight();
+ repositionLogicalHeightDependentFlexItems(flexIterator, lineContexts, oldClientAfterEdge);
if (size() != previousSize)
relayoutChildren = true;
@@ -284,13 +287,35 @@ void RenderFlexibleBox::layoutBlock(bool relayoutChildren, int, BlockLayoutPass)
// Update our scroll information if we're overflow:auto/scroll/hidden now that we know if
// we overflow or not.
- updateScrollInfoAfterLayout();
+ if (hasOverflowClip())
+ layer()->updateScrollInfoAfterLayout();
repainter.repaintAfterLayout();
setNeedsLayout(false);
}
+void RenderFlexibleBox::repositionLogicalHeightDependentFlexItems(FlexOrderIterator& iterator, WTF::Vector<LineContext>& lineContexts, LayoutUnit& oldClientAfterEdge)
+{
+ LayoutUnit crossAxisStartEdge = lineContexts.isEmpty() ? ZERO_LAYOUT_UNIT : lineContexts[0].crossAxisOffset;
+ packFlexLines(iterator, lineContexts);
+
+ // If we have a single line flexbox, the line height is all the available space.
+ // For flex-direction: row, this means we need to use the height, so we do this after calling computeLogicalHeight.
+ if (!isMultiline() && lineContexts.size() == 1)
+ lineContexts[0].crossAxisExtent = crossAxisContentExtent();
+ alignChildren(iterator, lineContexts);
+
+ if (style()->flexWrap() == FlexWrapReverse) {
+ if (isHorizontalFlow())
+ oldClientAfterEdge = clientLogicalBottom();
+ flipForWrapReverse(iterator, lineContexts, crossAxisStartEdge);
+ }
+
+ // direction:rtl + flex-direction:column means the cross-axis direction is flipped.
+ flipForRightToLeftColumn(iterator);
+}
+
bool RenderFlexibleBox::hasOrthogonalFlow(RenderBox* child) const
{
// FIXME: If the child is a flexbox, then we need to check isHorizontalFlow.
@@ -321,9 +346,12 @@ bool RenderFlexibleBox::isMultiline() const
return style()->flexWrap() != FlexWrapNone;
}
-Length RenderFlexibleBox::mainAxisLengthForChild(RenderBox* child) const
+Length RenderFlexibleBox::preferredLengthForChild(RenderBox* child) const
{
- return isHorizontalFlow() ? child->style()->width() : child->style()->height();
+ Length flexLength = child->style()->flexPreferredSize();
+ if (flexLength.isAuto())
+ flexLength = isHorizontalFlow() ? child->style()->width() : child->style()->height();
+ return flexLength;
}
Length RenderFlexibleBox::crossAxisLength() const
@@ -560,62 +588,58 @@ LayoutUnit RenderFlexibleBox::mainAxisScrollbarExtentForChild(RenderBox* child)
LayoutUnit RenderFlexibleBox::preferredMainAxisContentExtentForChild(RenderBox* child) const
{
- Length mainAxisLength = mainAxisLengthForChild(child);
+ Length mainAxisLength = preferredLengthForChild(child);
if (mainAxisLength.isAuto()) {
LayoutUnit mainAxisExtent = hasOrthogonalFlow(child) ? child->logicalHeight() : child->maxPreferredLogicalWidth();
- return mainAxisExtent - mainAxisBorderAndPaddingExtentForChild(child) - mainAxisScrollbarExtentForChild(child);
+ return mainAxisExtent - mainAxisBorderAndPaddingExtentForChild(child);
}
- return mainAxisLength.calcMinValue(mainAxisContentExtent());
+ return minimumValueForLength(mainAxisLength, mainAxisContentExtent(), view());
}
-void RenderFlexibleBox::layoutFlexItems(bool relayoutChildren)
+LayoutUnit RenderFlexibleBox::computeAvailableFreeSpace(LayoutUnit preferredMainAxisExtent)
{
- FlexOrderHashSet flexOrderValues;
- computeMainAxisPreferredSizes(relayoutChildren, flexOrderValues);
+ LayoutUnit contentExtent = 0;
+ if (!isColumnFlow())
+ contentExtent = mainAxisContentExtent();
+ else if (hasOverrideHeight())
+ contentExtent = overrideHeight() - (logicalHeight() - contentLogicalHeight());
+ else {
+ LayoutUnit heightResult = computeContentLogicalHeightUsing(style()->logicalHeight());
+ if (heightResult == -1)
+ heightResult = preferredMainAxisExtent;
+ LayoutUnit minHeight = computeContentLogicalHeightUsing(style()->logicalMinHeight()); // Leave as -1 if unset.
+ LayoutUnit maxHeight = style()->logicalMaxHeight().isUndefined() ? heightResult : computeContentLogicalHeightUsing(style()->logicalMaxHeight());
+ if (maxHeight == -1)
+ maxHeight = heightResult;
+ heightResult = std::min(maxHeight, heightResult);
+ heightResult = std::max(minHeight, heightResult);
+ contentExtent = heightResult;
+ }
+ return contentExtent - preferredMainAxisExtent;
+}
+
+void RenderFlexibleBox::layoutFlexItems(FlexOrderIterator& iterator, WTF::Vector<LineContext>& lineContexts)
+{
OrderedFlexItemList orderedChildren;
LayoutUnit preferredMainAxisExtent;
float totalPositiveFlexibility;
float totalNegativeFlexibility;
- FlexOrderIterator flexIterator(this, flexOrderValues);
-
- // For wrap-reverse, we need to layout as wrap, then reverse the lines. The next two arrays
- // are some extra information so it's possible to reverse the lines.
- WrapReverseContext wrapReverseContext(style()->flexWrap());
+ LayoutUnit minMaxAppliedMainAxisExtent;
LayoutUnit crossAxisOffset = flowAwareBorderBefore() + flowAwarePaddingBefore();
- LayoutUnit mainAxisFlexibleSpace = mainAxisContentExtent();
- while (computeNextFlexLine(flexIterator, orderedChildren, preferredMainAxisExtent, totalPositiveFlexibility, totalNegativeFlexibility)) {
- LayoutUnit availableFreeSpace = mainAxisFlexibleSpace - preferredMainAxisExtent;
+ while (computeNextFlexLine(iterator, orderedChildren, preferredMainAxisExtent, totalPositiveFlexibility, totalNegativeFlexibility, minMaxAppliedMainAxisExtent)) {
+ LayoutUnit availableFreeSpace = computeAvailableFreeSpace(preferredMainAxisExtent);
+ FlexSign flexSign = (minMaxAppliedMainAxisExtent < preferredMainAxisExtent + availableFreeSpace) ? PositiveFlexibility : NegativeFlexibility;
InflexibleFlexItemSize inflexibleItems;
WTF::Vector<LayoutUnit> childSizes;
- while (!runFreeSpaceAllocationAlgorithm(orderedChildren, availableFreeSpace, totalPositiveFlexibility, totalNegativeFlexibility, inflexibleItems, childSizes)) {
+ while (!resolveFlexibleLengths(flexSign, orderedChildren, availableFreeSpace, totalPositiveFlexibility, totalNegativeFlexibility, inflexibleItems, childSizes)) {
ASSERT(totalPositiveFlexibility >= 0 && totalNegativeFlexibility >= 0);
ASSERT(inflexibleItems.size() > 0);
}
- wrapReverseContext.addNumberOfChildrenOnLine(orderedChildren.size());
- wrapReverseContext.addCrossAxisOffset(crossAxisOffset);
- layoutAndPlaceChildren(crossAxisOffset, orderedChildren, childSizes, availableFreeSpace);
- }
-
- if (wrapReverseContext.isWrapReverse) {
- wrapReverseContext.addCrossAxisOffset(crossAxisOffset);
- flipForWrapReverse(flexIterator, wrapReverseContext);
+ layoutAndPlaceChildren(crossAxisOffset, orderedChildren, childSizes, availableFreeSpace, lineContexts);
}
-
- // direction:rtl + flex-direction:column means the cross-axis direction is flipped.
- flipForRightToLeftColumn(flexIterator);
-}
-
-float RenderFlexibleBox::positiveFlexForChild(RenderBox* child) const
-{
- return isHorizontalFlow() ? child->style()->flexboxWidthPositiveFlex() : child->style()->flexboxHeightPositiveFlex();
-}
-
-float RenderFlexibleBox::negativeFlexForChild(RenderBox* child) const
-{
- return isHorizontalFlow() ? child->style()->flexboxWidthNegativeFlex() : child->style()->flexboxHeightNegativeFlex();
}
LayoutUnit RenderFlexibleBox::availableAlignmentSpaceForChild(LayoutUnit lineCrossAxisExtent, RenderBox* child)
@@ -635,6 +659,7 @@ LayoutUnit RenderFlexibleBox::marginBoxAscentForChild(RenderBox* child)
void RenderFlexibleBox::computeMainAxisPreferredSizes(bool relayoutChildren, FlexOrderHashSet& flexOrderValues)
{
LayoutUnit flexboxAvailableContentExtent = mainAxisContentExtent();
+ RenderView* renderView = view();
for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
flexOrderValues.add(child->style()->flexOrder());
@@ -642,7 +667,7 @@ void RenderFlexibleBox::computeMainAxisPreferredSizes(bool relayoutChildren, Fle
continue;
child->clearOverrideSize();
- if (mainAxisLengthForChild(child).isAuto()) {
+ if (preferredLengthForChild(child).isAuto()) {
if (!relayoutChildren)
child->setChildNeedsLayout(true);
child->layoutIfNeeded();
@@ -652,52 +677,100 @@ void RenderFlexibleBox::computeMainAxisPreferredSizes(bool relayoutChildren, Fle
// of 0 and because if we're not auto sizing, we don't do a layout that
// computes the start/end margins.
if (isHorizontalFlow()) {
- child->setMarginLeft(child->style()->marginLeft().calcMinValue(flexboxAvailableContentExtent));
- child->setMarginRight(child->style()->marginRight().calcMinValue(flexboxAvailableContentExtent));
+ child->setMarginLeft(minimumValueForLength(child->style()->marginLeft(), flexboxAvailableContentExtent, renderView));
+ child->setMarginRight(minimumValueForLength(child->style()->marginRight(), flexboxAvailableContentExtent, renderView));
} else {
- child->setMarginTop(child->style()->marginTop().calcMinValue(flexboxAvailableContentExtent));
- child->setMarginBottom(child->style()->marginBottom().calcMinValue(flexboxAvailableContentExtent));
+ child->setMarginTop(minimumValueForLength(child->style()->marginTop(), flexboxAvailableContentExtent, renderView));
+ child->setMarginBottom(minimumValueForLength(child->style()->marginBottom(), flexboxAvailableContentExtent, renderView));
}
}
}
-bool RenderFlexibleBox::computeNextFlexLine(FlexOrderIterator& iterator, OrderedFlexItemList& orderedChildren, LayoutUnit& preferredMainAxisExtent, float& totalPositiveFlexibility, float& totalNegativeFlexibility)
+LayoutUnit RenderFlexibleBox::lineBreakLength()
+{
+ if (!isColumnFlow())
+ return mainAxisContentExtent();
+
+ LayoutUnit height = computeContentLogicalHeightUsing(style()->logicalHeight());
+ if (height == -1)
+ height = MAX_LAYOUT_UNIT;
+ LayoutUnit maxHeight = computeContentLogicalHeightUsing(style()->logicalMaxHeight());
+ if (maxHeight != -1)
+ height = std::min(height, maxHeight);
+ return height;
+}
+
+LayoutUnit RenderFlexibleBox::adjustChildSizeForMinAndMax(RenderBox* child, LayoutUnit childSize, LayoutUnit flexboxAvailableContentExtent)
+{
+ Length max = isHorizontalFlow() ? child->style()->maxWidth() : child->style()->maxHeight();
+ Length min = isHorizontalFlow() ? child->style()->minWidth() : child->style()->minHeight();
+ RenderView* renderView = view();
+ // FIXME: valueForLength isn't quite right in quirks mode: percentage heights should check parents until a value is found.
+ // https://bugs.webkit.org/show_bug.cgi?id=81809
+ if (max.isSpecified() && childSize > valueForLength(max, flexboxAvailableContentExtent, renderView))
+ childSize = valueForLength(max, flexboxAvailableContentExtent, renderView);
+ if (min.isSpecified() && childSize < valueForLength(min, flexboxAvailableContentExtent, renderView))
+ childSize = valueForLength(min, flexboxAvailableContentExtent, renderView);
+ return childSize;
+}
+
+bool RenderFlexibleBox::computeNextFlexLine(FlexOrderIterator& iterator, OrderedFlexItemList& orderedChildren, LayoutUnit& preferredMainAxisExtent, float& totalPositiveFlexibility, float& totalNegativeFlexibility, LayoutUnit& minMaxAppliedMainAxisExtent)
{
orderedChildren.clear();
preferredMainAxisExtent = 0;
totalPositiveFlexibility = totalNegativeFlexibility = 0;
+ minMaxAppliedMainAxisExtent = 0;
if (!iterator.currentChild())
return false;
+ LayoutUnit flexboxAvailableContentExtent = mainAxisContentExtent();
+ LayoutUnit lineBreak = lineBreakLength();
+
for (RenderBox* child = iterator.currentChild(); child; child = iterator.next()) {
if (child->isPositioned()) {
orderedChildren.append(child);
continue;
}
- LayoutUnit childMainAxisExtent = mainAxisBorderAndPaddingExtentForChild(child) + preferredMainAxisContentExtentForChild(child);
- if (isHorizontalFlow())
- childMainAxisExtent += child->marginWidth();
- else
- childMainAxisExtent += child->marginHeight();
+ LayoutUnit childMainAxisExtent = preferredMainAxisContentExtentForChild(child);
+ LayoutUnit childMainAxisMarginBoxExtent = mainAxisBorderAndPaddingExtentForChild(child) + childMainAxisExtent;
+ childMainAxisMarginBoxExtent += isHorizontalFlow() ? child->marginWidth() : child->marginHeight();
- if (isMultiline() && preferredMainAxisExtent + childMainAxisExtent > mainAxisContentExtent() && orderedChildren.size() > 0)
+ if (isMultiline() && preferredMainAxisExtent + childMainAxisMarginBoxExtent > lineBreak && orderedChildren.size() > 0)
break;
orderedChildren.append(child);
- preferredMainAxisExtent += childMainAxisExtent;
- totalPositiveFlexibility += positiveFlexForChild(child);
- totalNegativeFlexibility += negativeFlexForChild(child);
+ preferredMainAxisExtent += childMainAxisMarginBoxExtent;
+ totalPositiveFlexibility += child->style()->positiveFlex();
+ totalNegativeFlexibility += child->style()->negativeFlex();
+
+ LayoutUnit childMinMaxAppliedMainAxisExtent = adjustChildSizeForMinAndMax(child, childMainAxisExtent, flexboxAvailableContentExtent);
+ minMaxAppliedMainAxisExtent += childMinMaxAppliedMainAxisExtent - childMainAxisExtent + childMainAxisMarginBoxExtent;
}
return true;
}
+void RenderFlexibleBox::freezeViolations(const WTF::Vector<Violation>& violations, LayoutUnit& availableFreeSpace, float& totalPositiveFlexibility, float& totalNegativeFlexibility, InflexibleFlexItemSize& inflexibleItems)
+{
+ for (size_t i = 0; i < violations.size(); ++i) {
+ RenderBox* child = violations[i].child;
+ LayoutUnit childSize = violations[i].childSize;
+ availableFreeSpace -= childSize - preferredMainAxisContentExtentForChild(child);
+ totalPositiveFlexibility -= child->style()->positiveFlex();
+ totalNegativeFlexibility -= child->style()->negativeFlex();
+ inflexibleItems.set(child, childSize);
+ }
+}
+
// Returns true if we successfully ran the algorithm and sized the flex items.
-bool RenderFlexibleBox::runFreeSpaceAllocationAlgorithm(const OrderedFlexItemList& children, LayoutUnit& availableFreeSpace, float& totalPositiveFlexibility, float& totalNegativeFlexibility, InflexibleFlexItemSize& inflexibleItems, WTF::Vector<LayoutUnit>& childSizes)
+bool RenderFlexibleBox::resolveFlexibleLengths(FlexSign flexSign, const OrderedFlexItemList& children, LayoutUnit& availableFreeSpace, float& totalPositiveFlexibility, float& totalNegativeFlexibility, InflexibleFlexItemSize& inflexibleItems, WTF::Vector<LayoutUnit>& childSizes)
{
childSizes.clear();
-
LayoutUnit flexboxAvailableContentExtent = mainAxisContentExtent();
+ LayoutUnit totalViolation = 0;
+ LayoutUnit usedFreeSpace = 0;
+ WTF::Vector<Violation> minViolations;
+ WTF::Vector<Violation> maxViolations;
for (size_t i = 0; i < children.size(); ++i) {
RenderBox* child = children[i];
if (child->isPositioned()) {
@@ -705,59 +778,53 @@ bool RenderFlexibleBox::runFreeSpaceAllocationAlgorithm(const OrderedFlexItemLis
continue;
}
- LayoutUnit childPreferredSize;
if (inflexibleItems.contains(child))
- childPreferredSize = inflexibleItems.get(child);
+ childSizes.append(inflexibleItems.get(child));
else {
- childPreferredSize = preferredMainAxisContentExtentForChild(child);
- if (availableFreeSpace > 0 && totalPositiveFlexibility > 0) {
- childPreferredSize += lroundf(availableFreeSpace * positiveFlexForChild(child) / totalPositiveFlexibility);
-
- Length childLogicalMaxWidth = isHorizontalFlow() ? child->style()->maxWidth() : child->style()->maxHeight();
- if (!childLogicalMaxWidth.isUndefined() && childLogicalMaxWidth.isSpecified() && childPreferredSize > childLogicalMaxWidth.calcValue(flexboxAvailableContentExtent)) {
- childPreferredSize = childLogicalMaxWidth.calcValue(flexboxAvailableContentExtent);
- availableFreeSpace -= childPreferredSize - preferredMainAxisContentExtentForChild(child);
- totalPositiveFlexibility -= positiveFlexForChild(child);
-
- inflexibleItems.set(child, childPreferredSize);
- return false;
- }
- } else if (availableFreeSpace < 0 && totalNegativeFlexibility > 0) {
- childPreferredSize += lroundf(availableFreeSpace * negativeFlexForChild(child) / totalNegativeFlexibility);
-
- Length childLogicalMinWidth = isHorizontalFlow() ? child->style()->minWidth() : child->style()->minHeight();
- if (!childLogicalMinWidth.isUndefined() && childLogicalMinWidth.isSpecified() && childPreferredSize < childLogicalMinWidth.calcValue(flexboxAvailableContentExtent)) {
- childPreferredSize = childLogicalMinWidth.calcValue(flexboxAvailableContentExtent);
- availableFreeSpace += preferredMainAxisContentExtentForChild(child) - childPreferredSize;
- totalNegativeFlexibility -= negativeFlexForChild(child);
-
- inflexibleItems.set(child, childPreferredSize);
- return false;
- }
- }
+ LayoutUnit preferredChildSize = preferredMainAxisContentExtentForChild(child);
+ LayoutUnit childSize = preferredChildSize;
+ if (availableFreeSpace > 0 && totalPositiveFlexibility > 0 && flexSign == PositiveFlexibility)
+ childSize += lroundf(availableFreeSpace * child->style()->positiveFlex() / totalPositiveFlexibility);
+ else if (availableFreeSpace < 0 && totalNegativeFlexibility > 0 && flexSign == NegativeFlexibility)
+ childSize += lroundf(availableFreeSpace * child->style()->negativeFlex() / totalNegativeFlexibility);
+
+ LayoutUnit adjustedChildSize = adjustChildSizeForMinAndMax(child, childSize, flexboxAvailableContentExtent);
+ childSizes.append(adjustedChildSize);
+ usedFreeSpace += adjustedChildSize - preferredChildSize;
+
+ LayoutUnit violation = adjustedChildSize - childSize;
+ if (violation > 0)
+ minViolations.append(Violation(child, adjustedChildSize));
+ else if (violation < 0)
+ maxViolations.append(Violation(child, adjustedChildSize));
+ totalViolation += violation;
}
- childSizes.append(childPreferredSize);
}
- return true;
+
+ if (totalViolation)
+ freezeViolations(totalViolation < 0 ? maxViolations : minViolations, availableFreeSpace, totalPositiveFlexibility, totalNegativeFlexibility, inflexibleItems);
+ else
+ availableFreeSpace -= usedFreeSpace;
+
+ return !totalViolation;
}
-static LayoutUnit initialPackingOffset(LayoutUnit availableFreeSpace, EFlexPack flexPack, size_t numberOfChildren)
+static LayoutUnit initialPackingOffset(LayoutUnit availableFreeSpace, EFlexPack flexPack, unsigned numberOfChildren)
{
- if (availableFreeSpace > 0) {
- if (flexPack == PackEnd)
- return availableFreeSpace;
- if (flexPack == PackCenter)
- return availableFreeSpace / 2;
- if (flexPack == PackDistribute && numberOfChildren)
+ if (flexPack == PackEnd)
+ return availableFreeSpace;
+ if (flexPack == PackCenter)
+ return availableFreeSpace / 2;
+ if (flexPack == PackDistribute) {
+ if (availableFreeSpace > 0 && numberOfChildren)
return availableFreeSpace / (2 * numberOfChildren);
- } else if (availableFreeSpace < 0) {
- if (flexPack == PackCenter || flexPack == PackDistribute)
+ if (availableFreeSpace < 0)
return availableFreeSpace / 2;
}
return 0;
}
-static LayoutUnit packingSpaceBetweenChildren(LayoutUnit availableFreeSpace, EFlexPack flexPack, size_t numberOfChildren)
+static LayoutUnit packingSpaceBetweenChildren(LayoutUnit availableFreeSpace, EFlexPack flexPack, unsigned numberOfChildren)
{
if (availableFreeSpace > 0 && numberOfChildren > 1) {
if (flexPack == PackJustify)
@@ -791,7 +858,7 @@ void RenderFlexibleBox::prepareChildForPositionedLayout(RenderBox* child, Layout
if (childLayer->staticBlockPosition() != staticBlockPosition) {
childLayer->setStaticBlockPosition(staticBlockPosition);
if (child->style()->hasStaticBlockPosition(style()->isHorizontalWritingMode()))
- child->setChildNeedsLayout(true, false);
+ child->setChildNeedsLayout(true, MarkOnlyThis);
}
}
@@ -811,8 +878,9 @@ static EFlexAlign flexAlignForChild(RenderBox* child)
return align;
}
-void RenderFlexibleBox::layoutAndPlaceChildren(LayoutUnit& crossAxisOffset, const OrderedFlexItemList& children, const WTF::Vector<LayoutUnit>& childSizes, LayoutUnit availableFreeSpace)
+void RenderFlexibleBox::layoutAndPlaceChildren(LayoutUnit& crossAxisOffset, const OrderedFlexItemList& children, const WTF::Vector<LayoutUnit>& childSizes, LayoutUnit availableFreeSpace, WTF::Vector<LineContext>& lineContexts)
{
+ ASSERT(childSizes.size() == children.size());
LayoutUnit mainAxisOffset = flowAwareBorderStart() + flowAwarePaddingStart();
mainAxisOffset += initialPackingOffset(availableFreeSpace, style()->flexPack(), childSizes.size());
if (style()->flexDirection() == FlowRowReverse)
@@ -845,8 +913,8 @@ void RenderFlexibleBox::layoutAndPlaceChildren(LayoutUnit& crossAxisOffset, cons
childCrossAxisMarginBoxExtent = maxAscent + maxDescent;
} else
childCrossAxisMarginBoxExtent = crossAxisExtentForChild(child) + crossAxisMarginExtentForChild(child);
- if (crossAxisLength().isAuto())
- setCrossAxisExtent(std::max(crossAxisExtent(), crossAxisOffset + flowAwareBorderAfter() + flowAwarePaddingAfter() + childCrossAxisMarginBoxExtent + crossAxisScrollbarExtent()));
+ if (!isColumnFlow() && style()->logicalHeight().isAuto())
+ setLogicalHeight(std::max(logicalHeight(), crossAxisOffset + flowAwareBorderAfter() + flowAwarePaddingAfter() + childCrossAxisMarginBoxExtent + crossAxisScrollbarExtent()));
maxChildCrossAxisExtent = std::max(maxChildCrossAxisExtent, childCrossAxisMarginBoxExtent);
mainAxisOffset += flowAwareMarginStartForChild(child);
@@ -872,10 +940,8 @@ void RenderFlexibleBox::layoutAndPlaceChildren(LayoutUnit& crossAxisOffset, cons
layoutColumnReverse(children, childSizes, crossAxisOffset, availableFreeSpace);
}
- LayoutUnit lineCrossAxisExtent = isMultiline() ? maxChildCrossAxisExtent : crossAxisContentExtent();
- alignChildren(children, lineCrossAxisExtent, maxAscent);
-
- crossAxisOffset += lineCrossAxisExtent;
+ lineContexts.append(LineContext(crossAxisOffset, maxChildCrossAxisExtent, children.size(), maxAscent));
+ crossAxisOffset += maxChildCrossAxisExtent;
}
void RenderFlexibleBox::layoutColumnReverse(const OrderedFlexItemList& children, const WTF::Vector<LayoutUnit>& childSizes, LayoutUnit crossAxisOffset, LayoutUnit availableFreeSpace)
@@ -906,6 +972,55 @@ void RenderFlexibleBox::layoutColumnReverse(const OrderedFlexItemList& children,
}
}
+static LayoutUnit initialLinePackingOffset(LayoutUnit availableFreeSpace, EFlexLinePack linePack, unsigned numberOfLines)
+{
+ if (linePack == LinePackEnd)
+ return availableFreeSpace;
+ if (linePack == LinePackCenter)
+ return availableFreeSpace / 2;
+ if (linePack == LinePackDistribute) {
+ if (availableFreeSpace > 0 && numberOfLines)
+ return availableFreeSpace / (2 * numberOfLines);
+ if (availableFreeSpace < 0)
+ return availableFreeSpace / 2;
+ }
+ return 0;
+}
+
+static LayoutUnit linePackingSpaceBetweenChildren(LayoutUnit availableFreeSpace, EFlexLinePack linePack, unsigned numberOfLines)
+{
+ if (availableFreeSpace > 0 && numberOfLines > 1) {
+ if (linePack == LinePackJustify)
+ return availableFreeSpace / (numberOfLines - 1);
+ if (linePack == LinePackDistribute || linePack == LinePackStretch)
+ return availableFreeSpace / numberOfLines;
+ }
+ return 0;
+}
+
+void RenderFlexibleBox::packFlexLines(FlexOrderIterator& iterator, WTF::Vector<LineContext>& lineContexts)
+{
+ if (!isMultiline() || style()->flexLinePack() == LinePackStart)
+ return;
+
+ LayoutUnit availableCrossAxisSpace = crossAxisContentExtent();
+ for (size_t i = 0; i < lineContexts.size(); ++i)
+ availableCrossAxisSpace -= lineContexts[i].crossAxisExtent;
+
+ RenderBox* child = iterator.first();
+ LayoutUnit lineOffset = initialLinePackingOffset(availableCrossAxisSpace, style()->flexLinePack(), lineContexts.size());
+ for (unsigned lineNumber = 0; lineNumber < lineContexts.size(); ++lineNumber) {
+ lineContexts[lineNumber].crossAxisOffset += lineOffset;
+ for (size_t childNumber = 0; childNumber < lineContexts[lineNumber].numberOfChildren; ++childNumber, child = iterator.next())
+ adjustAlignmentForChild(child, lineOffset);
+
+ if (style()->flexLinePack() == LinePackStretch && availableCrossAxisSpace > 0)
+ lineContexts[lineNumber].crossAxisExtent += availableCrossAxisSpace / static_cast<unsigned>(lineContexts.size());
+
+ lineOffset += linePackingSpaceBetweenChildren(availableCrossAxisSpace, style()->flexLinePack(), lineContexts.size());
+ }
+}
+
void RenderFlexibleBox::adjustAlignmentForChild(RenderBox* child, LayoutUnit delta)
{
LayoutRect oldRect = child->frameRect();
@@ -919,72 +1034,94 @@ void RenderFlexibleBox::adjustAlignmentForChild(RenderBox* child, LayoutUnit del
child->repaintDuringLayoutIfMoved(oldRect);
}
-void RenderFlexibleBox::alignChildren(const OrderedFlexItemList& children, LayoutUnit lineCrossAxisExtent, LayoutUnit maxAscent)
+void RenderFlexibleBox::alignChildren(FlexOrderIterator& iterator, const WTF::Vector<LineContext>& lineContexts)
{
- LayoutUnit minMarginAfterBaseline = std::numeric_limits<LayoutUnit>::max();
-
- for (size_t i = 0; i < children.size(); ++i) {
- RenderBox* child = children[i];
- switch (flexAlignForChild(child)) {
- case AlignAuto:
- ASSERT_NOT_REACHED();
- break;
- case AlignStretch: {
- if (!isColumnFlow() && child->style()->logicalHeight().isAuto()) {
- LayoutUnit logicalHeightBefore = child->logicalHeight();
- LayoutUnit stretchedLogicalHeight = child->logicalHeight() + availableAlignmentSpaceForChild(lineCrossAxisExtent, child);
- child->setLogicalHeight(stretchedLogicalHeight);
- child->computeLogicalHeight();
-
- if (child->logicalHeight() != logicalHeightBefore) {
- child->setOverrideHeight(child->logicalHeight());
- child->setLogicalHeight(0);
- child->setChildNeedsLayout(true);
- child->layoutIfNeeded();
- }
- } else if (isColumnFlow() && child->style()->logicalWidth().isAuto() && isMultiline()) {
- // FIXME: Handle min-width and max-width.
- LayoutUnit childWidth = lineCrossAxisExtent - crossAxisMarginExtentForChild(child);
- child->setOverrideWidth(std::max(0, childWidth));
- child->setChildNeedsLayout(true);
- child->layoutIfNeeded();
+ // Keep track of the space between the baseline edge and the after edge of the box for each line.
+ WTF::Vector<LayoutUnit> minMarginAfterBaselines;
+
+ RenderBox* child = iterator.first();
+ for (size_t lineNumber = 0; lineNumber < lineContexts.size(); ++lineNumber) {
+ LayoutUnit minMarginAfterBaseline = MAX_LAYOUT_UNIT;
+ LayoutUnit lineCrossAxisExtent = lineContexts[lineNumber].crossAxisExtent;
+ LayoutUnit maxAscent = lineContexts[lineNumber].maxAscent;
+
+ for (size_t childNumber = 0; childNumber < lineContexts[lineNumber].numberOfChildren; ++childNumber, child = iterator.next()) {
+ ASSERT(child);
+ switch (flexAlignForChild(child)) {
+ case AlignAuto:
+ ASSERT_NOT_REACHED();
+ break;
+ case AlignStretch: {
+ applyStretchAlignmentToChild(child, lineCrossAxisExtent);
+ // Since wrap-reverse flips cross start and cross end, strech children should be aligned with the cross end.
+ if (style()->flexWrap() == FlexWrapReverse)
+ adjustAlignmentForChild(child, availableAlignmentSpaceForChild(lineCrossAxisExtent, child));
+ break;
}
- // Since wrap-reverse flips cross start and cross end, strech children should be aligned with the cross end.
- if (style()->flexWrap() == FlexWrapReverse)
+ case AlignStart:
+ break;
+ case AlignEnd:
adjustAlignmentForChild(child, availableAlignmentSpaceForChild(lineCrossAxisExtent, child));
- break;
- }
- case AlignStart:
- break;
- case AlignEnd:
- adjustAlignmentForChild(child, availableAlignmentSpaceForChild(lineCrossAxisExtent, child));
- break;
- case AlignCenter:
- adjustAlignmentForChild(child, availableAlignmentSpaceForChild(lineCrossAxisExtent, child) / 2);
- break;
- case AlignBaseline: {
- LayoutUnit ascent = marginBoxAscentForChild(child);
- LayoutUnit startOffset = maxAscent - ascent;
- adjustAlignmentForChild(child, startOffset);
-
- if (style()->flexWrap() == FlexWrapReverse)
- minMarginAfterBaseline = std::min(minMarginAfterBaseline, availableAlignmentSpaceForChild(lineCrossAxisExtent, child) - startOffset);
- break;
- }
+ break;
+ case AlignCenter:
+ adjustAlignmentForChild(child, availableAlignmentSpaceForChild(lineCrossAxisExtent, child) / 2);
+ break;
+ case AlignBaseline: {
+ LayoutUnit ascent = marginBoxAscentForChild(child);
+ LayoutUnit startOffset = maxAscent - ascent;
+ adjustAlignmentForChild(child, startOffset);
+
+ if (style()->flexWrap() == FlexWrapReverse)
+ minMarginAfterBaseline = std::min(minMarginAfterBaseline, availableAlignmentSpaceForChild(lineCrossAxisExtent, child) - startOffset);
+ break;
+ }
+ }
}
+ minMarginAfterBaselines.append(minMarginAfterBaseline);
}
+ if (style()->flexWrap() != FlexWrapReverse)
+ return;
+
// wrap-reverse flips the cross axis start and end. For baseline alignment, this means we
// need to align the after edge of baseline elements with the after edge of the flex line.
- if (style()->flexWrap() == FlexWrapReverse && minMarginAfterBaseline) {
- for (size_t i = 0; i < children.size(); ++i) {
- RenderBox* child = children[i];
- if (flexAlignForChild(child) == AlignBaseline)
+ child = iterator.first();
+ for (size_t lineNumber = 0; lineNumber < lineContexts.size(); ++lineNumber) {
+ LayoutUnit minMarginAfterBaseline = minMarginAfterBaselines[lineNumber];
+ for (size_t childNumber = 0; childNumber < lineContexts[lineNumber].numberOfChildren; ++childNumber, child = iterator.next()) {
+ ASSERT(child);
+ if (flexAlignForChild(child) == AlignBaseline && minMarginAfterBaseline)
adjustAlignmentForChild(child, minMarginAfterBaseline);
}
}
}
+void RenderFlexibleBox::applyStretchAlignmentToChild(RenderBox* child, LayoutUnit lineCrossAxisExtent)
+{
+ if (!isColumnFlow() && child->style()->logicalHeight().isAuto()) {
+ LayoutUnit logicalHeightBefore = child->logicalHeight();
+ LayoutUnit stretchedLogicalHeight = child->logicalHeight() + availableAlignmentSpaceForChild(lineCrossAxisExtent, child);
+ if (stretchedLogicalHeight < logicalHeightBefore)
+ return;
+
+ child->setLogicalHeight(stretchedLogicalHeight);
+ child->computeLogicalHeight();
+
+ if (child->logicalHeight() != logicalHeightBefore) {
+ child->setOverrideHeight(child->logicalHeight());
+ child->setLogicalHeight(0);
+ child->setChildNeedsLayout(true);
+ child->layoutIfNeeded();
+ }
+ } else if (isColumnFlow() && child->style()->logicalWidth().isAuto() && isMultiline()) {
+ // FIXME: Handle min-width and max-width.
+ LayoutUnit childWidth = lineCrossAxisExtent - crossAxisMarginExtentForChild(child);
+ child->setOverrideWidth(std::max(ZERO_LAYOUT_UNIT, childWidth));
+ child->setChildNeedsLayout(true);
+ child->layoutIfNeeded();
+ }
+}
+
void RenderFlexibleBox::flipForRightToLeftColumn(FlexOrderIterator& iterator)
{
if (style()->isLeftToRightDirection() || !isColumnFlow())
@@ -998,26 +1135,23 @@ void RenderFlexibleBox::flipForRightToLeftColumn(FlexOrderIterator& iterator)
}
}
-void RenderFlexibleBox::flipForWrapReverse(FlexOrderIterator& iterator, const WrapReverseContext& wrapReverseContext)
+void RenderFlexibleBox::flipForWrapReverse(FlexOrderIterator& iterator, const WTF::Vector<LineContext>& lineContexts, LayoutUnit crossAxisStartEdge)
{
- if (!isColumnFlow())
- computeLogicalHeight();
-
- size_t currentChild = 0;
- size_t lineNumber = 0;
LayoutUnit contentExtent = crossAxisContentExtent();
- for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
- LayoutPoint location = flowAwareLocationForChild(child);
- location.setY(location.y() + wrapReverseContext.lineCrossAxisDelta(lineNumber, contentExtent));
-
- LayoutRect oldRect = child->frameRect();
- setFlowAwareLocationForChild(child, location);
- if (!selfNeedsLayout() && child->checkForRepaintDuringLayout())
- child->repaintDuringLayoutIfMoved(oldRect);
-
- if (++currentChild == wrapReverseContext.childrenPerLine[lineNumber]) {
- ++lineNumber;
- currentChild = 0;
+ RenderBox* child = iterator.first();
+ for (size_t lineNumber = 0; lineNumber < lineContexts.size(); ++lineNumber) {
+ for (size_t childNumber = 0; childNumber < lineContexts[lineNumber].numberOfChildren; ++childNumber, child = iterator.next()) {
+ ASSERT(child);
+ LayoutPoint location = flowAwareLocationForChild(child);
+ LayoutUnit lineCrossAxisExtent = lineContexts[lineNumber].crossAxisExtent;
+ LayoutUnit originalOffset = lineContexts[lineNumber].crossAxisOffset - crossAxisStartEdge;
+ LayoutUnit newOffset = contentExtent - originalOffset - lineCrossAxisExtent;
+ location.setY(location.y() + newOffset - originalOffset);
+
+ LayoutRect oldRect = child->frameRect();
+ setFlowAwareLocationForChild(child, location);
+ if (!selfNeedsLayout() && child->checkForRepaintDuringLayout())
+ child->repaintDuringLayoutIfMoved(oldRect);
}
}
}
diff --git a/Source/WebCore/rendering/RenderFlexibleBox.h b/Source/WebCore/rendering/RenderFlexibleBox.h
index 3490bf1c6..6c21b0494 100644
--- a/Source/WebCore/rendering/RenderFlexibleBox.h
+++ b/Source/WebCore/rendering/RenderFlexibleBox.h
@@ -44,11 +44,16 @@ public:
virtual bool isFlexibleBox() const { return true; }
virtual void computePreferredLogicalWidths();
- virtual void layoutBlock(bool relayoutChildren, int pageLogicalHeight = 0, BlockLayoutPass = NormalLayoutPass);
+ virtual void layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeight = 0);
bool isHorizontalFlow() const;
private:
+ enum FlexSign {
+ PositiveFlexibility,
+ NegativeFlexibility,
+ };
+
struct FlexOrderHashTraits;
typedef HashSet<int, DefaultHash<int>::Hash, FlexOrderHashTraits> FlexOrderHashSet;
@@ -56,14 +61,15 @@ private:
typedef WTF::HashMap<const RenderBox*, LayoutUnit> InflexibleFlexItemSize;
typedef WTF::Vector<RenderBox*> OrderedFlexItemList;
- struct WrapReverseContext;
+ struct LineContext;
+ struct Violation;
bool hasOrthogonalFlow(RenderBox* child) const;
bool isColumnFlow() const;
bool isLeftToRightFlow() const;
bool isMultiline() const;
Length crossAxisLength() const;
- Length mainAxisLengthForChild(RenderBox* child) const;
+ Length preferredLengthForChild(RenderBox* child) const;
void setCrossAxisExtent(LayoutUnit);
LayoutUnit crossAxisExtentForChild(RenderBox* child);
LayoutUnit mainAxisExtentForChild(RenderBox* child);
@@ -94,24 +100,30 @@ private:
LayoutUnit mainAxisScrollbarExtentForChild(RenderBox* child) const;
LayoutUnit preferredMainAxisContentExtentForChild(RenderBox* child) const;
- void layoutFlexItems(bool relayoutChildren);
-
- float positiveFlexForChild(RenderBox* child) const;
- float negativeFlexForChild(RenderBox* child) const;
+ void layoutFlexItems(FlexOrderIterator&, WTF::Vector<LineContext>&);
+ void repositionLogicalHeightDependentFlexItems(FlexOrderIterator&, WTF::Vector<LineContext>&, LayoutUnit& oldClientAfterEdge);
LayoutUnit availableAlignmentSpaceForChild(LayoutUnit lineCrossAxisExtent, RenderBox*);
LayoutUnit marginBoxAscentForChild(RenderBox*);
void computeMainAxisPreferredSizes(bool relayoutChildren, FlexOrderHashSet&);
- bool computeNextFlexLine(FlexOrderIterator&, OrderedFlexItemList& orderedChildren, LayoutUnit& preferredMainAxisExtent, float& totalPositiveFlexibility, float& totalNegativeFlexibility);
- bool runFreeSpaceAllocationAlgorithm(const OrderedFlexItemList&, LayoutUnit& availableFreeSpace, float& totalPositiveFlexibility, float& totalNegativeFlexibility, InflexibleFlexItemSize&, WTF::Vector<LayoutUnit>& childSizes);
+ LayoutUnit lineBreakLength();
+ LayoutUnit adjustChildSizeForMinAndMax(RenderBox*, LayoutUnit childSize, LayoutUnit flexboxAvailableContentExtent);
+ bool computeNextFlexLine(FlexOrderIterator&, OrderedFlexItemList& orderedChildren, LayoutUnit& preferredMainAxisExtent, float& totalPositiveFlexibility, float& totalNegativeFlexibility, LayoutUnit& minMaxAppliedMainAxisExtent);
+ LayoutUnit computeAvailableFreeSpace(LayoutUnit preferredMainAxisExtent);
+
+ bool resolveFlexibleLengths(FlexSign, const OrderedFlexItemList&, LayoutUnit& availableFreeSpace, float& totalPositiveFlexibility, float& totalNegativeFlexibility, InflexibleFlexItemSize&, WTF::Vector<LayoutUnit>& childSizes);
+ void freezeViolations(const WTF::Vector<Violation>&, LayoutUnit& availableFreeSpace, float& totalPositiveFlexibility, float& totalNegativeFlexibility, InflexibleFlexItemSize&);
+
void setLogicalOverrideSize(RenderBox* child, LayoutUnit childPreferredSize);
void prepareChildForPositionedLayout(RenderBox* child, LayoutUnit mainAxisOffset, LayoutUnit crossAxisOffset);
- void layoutAndPlaceChildren(LayoutUnit& crossAxisOffset, const OrderedFlexItemList&, const WTF::Vector<LayoutUnit>& childSizes, LayoutUnit availableFreeSpace);
+ void layoutAndPlaceChildren(LayoutUnit& crossAxisOffset, const OrderedFlexItemList&, const WTF::Vector<LayoutUnit>& childSizes, LayoutUnit availableFreeSpace, WTF::Vector<LineContext>&);
void layoutColumnReverse(const OrderedFlexItemList&, const WTF::Vector<LayoutUnit>& childSizes, LayoutUnit crossAxisOffset, LayoutUnit availableFreeSpace);
- void alignChildren(const OrderedFlexItemList&, LayoutUnit lineCrossAxisExtent, LayoutUnit maxAscent);
+ void packFlexLines(FlexOrderIterator&, WTF::Vector<LineContext>&);
+ void alignChildren(FlexOrderIterator&, const WTF::Vector<LineContext>&);
+ void applyStretchAlignmentToChild(RenderBox*, LayoutUnit lineCrossAxisExtent);
void flipForRightToLeftColumn(FlexOrderIterator&);
- void flipForWrapReverse(FlexOrderIterator&, const WrapReverseContext&);
+ void flipForWrapReverse(FlexOrderIterator&, const WTF::Vector<LineContext>&, LayoutUnit crossAxisStartEdge);
};
} // namespace WebCore
diff --git a/Source/WebCore/rendering/RenderFlowThread.cpp b/Source/WebCore/rendering/RenderFlowThread.cpp
index e241d9670..393964ade 100644
--- a/Source/WebCore/rendering/RenderFlowThread.cpp
+++ b/Source/WebCore/rendering/RenderFlowThread.cpp
@@ -31,6 +31,7 @@
#include "RenderFlowThread.h"
+#include "FlowThreadController.h"
#include "HitTestRequest.h"
#include "HitTestResult.h"
#include "Node.h"
@@ -44,14 +45,14 @@
namespace WebCore {
-RenderFlowThread::RenderFlowThread(Node* node, const AtomicString& flowThread)
+RenderFlowThread::RenderFlowThread(Node* node)
: RenderBlock(node)
- , m_flowThread(flowThread)
, m_hasValidRegions(false)
, m_regionsInvalidated(false)
, m_regionsHaveUniformLogicalWidth(true)
, m_regionsHaveUniformLogicalHeight(true)
, m_overflow(false)
+ , m_regionLayoutUpdateEventTimer(this, &RenderFlowThread::regionLayoutUpdateEventTimerFired)
{
ASSERT(node->document()->cssRegionsEnabled());
setIsAnonymous(false);
@@ -82,63 +83,6 @@ void RenderFlowThread::styleDidChange(StyleDifference diff, const RenderStyle* o
m_regionsInvalidated = true;
}
-RenderObject* RenderFlowThread::nextRendererForNode(Node* node) const
-{
- FlowThreadChildList::const_iterator it = m_flowThreadChildList.begin();
- FlowThreadChildList::const_iterator end = m_flowThreadChildList.end();
-
- for (; it != end; ++it) {
- RenderObject* child = *it;
- ASSERT(child->node());
- unsigned short position = node->compareDocumentPosition(child->node());
- if (position & Node::DOCUMENT_POSITION_FOLLOWING)
- return child;
- }
-
- return 0;
-}
-
-RenderObject* RenderFlowThread::previousRendererForNode(Node* node) const
-{
- if (m_flowThreadChildList.isEmpty())
- return 0;
-
- FlowThreadChildList::const_iterator begin = m_flowThreadChildList.begin();
- FlowThreadChildList::const_iterator end = m_flowThreadChildList.end();
- FlowThreadChildList::const_iterator it = end;
-
- do {
- --it;
- RenderObject* child = *it;
- ASSERT(child->node());
- unsigned short position = node->compareDocumentPosition(child->node());
- if (position & Node::DOCUMENT_POSITION_PRECEDING)
- return child;
- } while (it != begin);
-
- return 0;
-}
-
-void RenderFlowThread::addFlowChild(RenderObject* newChild, RenderObject* beforeChild)
-{
- // The child list is used to sort the flow thread's children render objects
- // based on their corresponding nodes DOM order. The list is needed to avoid searching the whole DOM.
-
- // Do not add anonymous objects.
- if (!newChild->node())
- return;
-
- if (beforeChild)
- m_flowThreadChildList.insertBefore(beforeChild, newChild);
- else
- m_flowThreadChildList.add(newChild);
-}
-
-void RenderFlowThread::removeFlowChild(RenderObject* child)
-{
- m_flowThreadChildList.remove(child);
-}
-
void RenderFlowThread::removeFlowChildInfo(RenderObject* child)
{
if (child->isBox()) {
@@ -148,149 +92,22 @@ void RenderFlowThread::removeFlowChildInfo(RenderObject* child)
}
}
-// Compare two regions to determine in which one the content should flow first.
-// The function returns true if the first passed region is "less" than the second passed region.
-// If the first region appears before second region in DOM,
-// the first region is "less" than the second region.
-// If the first region is "less" than the second region, the first region receives content before second region.
-static bool compareRenderRegions(const RenderRegion* firstRegion, const RenderRegion* secondRegion)
-{
- ASSERT(firstRegion);
- ASSERT(secondRegion);
-
- // If the regions have the same region-index, compare their position in dom.
- ASSERT(firstRegion->node());
- ASSERT(secondRegion->node());
-
- unsigned short position = firstRegion->node()->compareDocumentPosition(secondRegion->node());
- return (position & Node::DOCUMENT_POSITION_FOLLOWING);
-}
-
-bool RenderFlowThread::dependsOn(RenderFlowThread* otherRenderFlowThread) const
-{
- if (m_layoutBeforeThreadsSet.contains(otherRenderFlowThread))
- return true;
-
- // Recursively traverse the m_layoutBeforeThreadsSet.
- RenderFlowThreadCountedSet::const_iterator iterator = m_layoutBeforeThreadsSet.begin();
- RenderFlowThreadCountedSet::const_iterator end = m_layoutBeforeThreadsSet.end();
- for (; iterator != end; ++iterator) {
- const RenderFlowThread* beforeFlowThread = (*iterator).first;
- if (beforeFlowThread->dependsOn(otherRenderFlowThread))
- return true;
- }
-
- return false;
-}
-
void RenderFlowThread::addRegionToThread(RenderRegion* renderRegion)
{
ASSERT(renderRegion);
- if (m_regionList.isEmpty())
- m_regionList.add(renderRegion);
- else {
- // Find the first region "greater" than renderRegion.
- RenderRegionList::iterator it = m_regionList.begin();
- while (it != m_regionList.end() && !compareRenderRegions(renderRegion, *it))
- ++it;
- m_regionList.insertBefore(it, renderRegion);
- }
-
- ASSERT(!renderRegion->isValid());
- if (renderRegion->parentFlowThread()) {
- if (renderRegion->parentFlowThread()->dependsOn(this)) {
- // Register ourself to get a notification when the state changes.
- renderRegion->parentFlowThread()->m_observerThreadsSet.add(this);
- return;
- }
-
- addDependencyOnFlowThread(renderRegion->parentFlowThread());
- }
-
+ m_regionList.add(renderRegion);
renderRegion->setIsValid(true);
-
invalidateRegions();
}
void RenderFlowThread::removeRegionFromThread(RenderRegion* renderRegion)
{
ASSERT(renderRegion);
-
m_regionRangeMap.clear();
m_regionList.remove(renderRegion);
-
- if (renderRegion->parentFlowThread()) {
- if (!renderRegion->isValid()) {
- renderRegion->parentFlowThread()->m_observerThreadsSet.remove(this);
- // No need to invalidate the regions rectangles. The removed region
- // was not taken into account. Just return here.
- return;
- }
- removeDependencyOnFlowThread(renderRegion->parentFlowThread());
- }
-
invalidateRegions();
}
-void RenderFlowThread::checkInvalidRegions()
-{
- for (RenderRegionList::iterator iter = m_regionList.begin(); iter != m_regionList.end(); ++iter) {
- RenderRegion* region = *iter;
- // The only reason a region would be invalid is because it has a parent flow thread.
- ASSERT(region->isValid() || region->parentFlowThread());
- if (region->isValid() || region->parentFlowThread()->dependsOn(this))
- continue;
-
- region->parentFlowThread()->m_observerThreadsSet.remove(this);
- addDependencyOnFlowThread(region->parentFlowThread());
- region->setIsValid(true);
- invalidateRegions();
- }
-
- if (m_observerThreadsSet.isEmpty())
- return;
-
- // Notify all the flow threads that were dependent on this flow.
-
- // Create a copy of the list first. That's because observers might change the list when calling checkInvalidRegions.
- Vector<RenderFlowThread*> observers;
- copyToVector(m_observerThreadsSet, observers);
-
- for (size_t i = 0; i < observers.size(); ++i) {
- RenderFlowThread* flowThread = observers.at(i);
- flowThread->checkInvalidRegions();
- }
-}
-
-void RenderFlowThread::addDependencyOnFlowThread(RenderFlowThread* otherFlowThread)
-{
- std::pair<RenderFlowThreadCountedSet::iterator, bool> result = m_layoutBeforeThreadsSet.add(otherFlowThread);
- if (result.second) {
- // This is the first time we see this dependency. Make sure we recalculate all the dependencies.
- view()->setIsRenderFlowThreadOrderDirty(true);
- }
-}
-
-void RenderFlowThread::removeDependencyOnFlowThread(RenderFlowThread* otherFlowThread)
-{
- bool removed = m_layoutBeforeThreadsSet.remove(otherFlowThread);
- if (removed) {
- checkInvalidRegions();
- view()->setIsRenderFlowThreadOrderDirty(true);
- }
-}
-
-void RenderFlowThread::pushDependencies(RenderFlowThreadList& list)
-{
- for (RenderFlowThreadCountedSet::iterator iter = m_layoutBeforeThreadsSet.begin(); iter != m_layoutBeforeThreadsSet.end(); ++iter) {
- RenderFlowThread* flowThread = (*iter).first;
- if (list.contains(flowThread))
- continue;
- flowThread->pushDependencies(list);
- list.add(flowThread);
- }
-}
-
class CurrentRenderFlowThreadMaintainer {
WTF_MAKE_NONCOPYABLE(CurrentRenderFlowThreadMaintainer);
public:
@@ -298,14 +115,14 @@ public:
: m_renderFlowThread(renderFlowThread)
{
RenderView* view = m_renderFlowThread->view();
- ASSERT(!view->currentRenderFlowThread());
- view->setCurrentRenderFlowThread(m_renderFlowThread);
+ ASSERT(!view->flowThreadController()->currentRenderFlowThread());
+ view->flowThreadController()->setCurrentRenderFlowThread(m_renderFlowThread);
}
~CurrentRenderFlowThreadMaintainer()
{
RenderView* view = m_renderFlowThread->view();
- ASSERT(view->currentRenderFlowThread() == m_renderFlowThread);
- view->setCurrentRenderFlowThread(0);
+ ASSERT(view->flowThreadController()->currentRenderFlowThread() == m_renderFlowThread);
+ view->flowThreadController()->setCurrentRenderFlowThread(0);
}
private:
RenderFlowThread* m_renderFlowThread;
@@ -318,14 +135,14 @@ public:
: m_view(view)
, m_renderFlowThread(0)
{
- m_renderFlowThread = m_view->currentRenderFlowThread();
+ m_renderFlowThread = m_view->flowThreadController()->currentRenderFlowThread();
if (m_renderFlowThread)
- view->setCurrentRenderFlowThread(0);
+ view->flowThreadController()->setCurrentRenderFlowThread(0);
}
~CurrentRenderFlowThreadDisabler()
{
if (m_renderFlowThread)
- m_view->setCurrentRenderFlowThread(m_renderFlowThread);
+ m_view->flowThreadController()->setCurrentRenderFlowThread(m_renderFlowThread);
}
private:
RenderView* m_view;
@@ -384,10 +201,10 @@ void RenderFlowThread::layout()
continue;
LayoutRect regionRect;
if (isHorizontalWritingMode()) {
- regionRect = LayoutRect(style()->direction() == LTR ? zeroLayoutUnit : logicalWidth() - region->contentWidth(), logicalHeight, region->contentWidth(), region->contentHeight());
+ regionRect = LayoutRect(style()->direction() == LTR ? ZERO_LAYOUT_UNIT : logicalWidth() - region->contentWidth(), logicalHeight, region->contentWidth(), region->contentHeight());
logicalHeight += regionRect.height();
} else {
- regionRect = LayoutRect(logicalHeight, style()->direction() == LTR ? zeroLayoutUnit : logicalWidth() - region->contentHeight(), region->contentWidth(), region->contentHeight());
+ regionRect = LayoutRect(logicalHeight, style()->direction() == LTR ? ZERO_LAYOUT_UNIT : logicalWidth() - region->contentHeight(), region->contentWidth(), region->contentHeight());
logicalHeight += regionRect.width();
}
region->setRegionRect(regionRect);
@@ -399,6 +216,15 @@ void RenderFlowThread::layout()
LayoutStateMaintainer statePusher(view(), this, regionsChanged);
RenderBlock::layout();
statePusher.pop();
+ if (document()->hasListenerType(Document::REGIONLAYOUTUPDATE_LISTENER) && !m_regionLayoutUpdateEventTimer.isActive())
+ for (RenderRegionList::iterator iter = m_regionList.begin(); iter != m_regionList.end(); ++iter) {
+ RenderRegion* region = *iter;
+ if (region->shouldDispatchRegionLayoutUpdateEvent()) {
+ // at least one region needs to dispatch the event
+ m_regionLayoutUpdateEventTimer.startOneShot(0);
+ break;
+ }
+ }
}
void RenderFlowThread::computeLogicalWidth()
@@ -421,7 +247,7 @@ void RenderFlowThread::computeLogicalWidth()
LayoutUnit regionLogicalWidth = isHorizontalWritingMode() ? region->contentWidth() : region->contentHeight();
if (regionLogicalWidth != logicalWidth) {
- LayoutUnit logicalLeft = style()->direction() == LTR ? zeroLayoutUnit : logicalWidth - regionLogicalWidth;
+ LayoutUnit logicalLeft = style()->direction() == LTR ? ZERO_LAYOUT_UNIT : logicalWidth - regionLogicalWidth;
region->setRenderBoxRegionInfo(this, logicalLeft, regionLogicalWidth, false);
}
}
@@ -429,7 +255,7 @@ void RenderFlowThread::computeLogicalWidth()
void RenderFlowThread::computeLogicalHeight()
{
- int logicalHeight = 0;
+ LayoutUnit logicalHeight = 0;
for (RenderRegionList::iterator iter = m_regionList.begin(); iter != m_regionList.end(); ++iter) {
RenderRegion* region = *iter;
@@ -676,7 +502,7 @@ void RenderFlowThread::removeRenderBoxRegionInfo(RenderBox* box)
}
#ifndef NDEBUG
- // We have to make sure we did not left any boxes with region info attached in regions.
+ // We have to make sure we did not leave any RenderBoxRegionInfo attached.
for (RenderRegionList::iterator iter = m_regionList.begin(); iter != m_regionList.end(); ++iter) {
RenderRegion* region = *iter;
if (!region->isValid())
@@ -866,14 +692,6 @@ void RenderFlowThread::getRegionRangeForBox(const RenderBox* box, RenderRegion*&
ASSERT(m_regionList.contains(startRegion) && m_regionList.contains(endRegion));
}
-WebKitNamedFlow* RenderFlowThread::ensureNamedFlow()
-{
- if (!m_namedFlow)
- m_namedFlow = WebKitNamedFlow::create(this);
-
- return m_namedFlow.get();
-}
-
void RenderFlowThread::computeOverflowStateForRegions(LayoutUnit oldClientAfterEdge)
{
LayoutUnit height = oldClientAfterEdge;
@@ -892,12 +710,20 @@ void RenderFlowThread::computeOverflowStateForRegions(LayoutUnit oldClientAfterE
}
LayoutUnit flowMin = height - (isHorizontalWritingMode() ? region->regionRect().y() : region->regionRect().x());
LayoutUnit flowMax = height - (isHorizontalWritingMode() ? region->regionRect().maxY() : region->regionRect().maxX());
+ RenderRegion::RegionState previousState = region->regionState();
RenderRegion::RegionState state = RenderRegion::RegionFit;
if (flowMin <= 0)
state = RenderRegion::RegionEmpty;
if (flowMax > 0)
state = RenderRegion::RegionOverflow;
region->setRegionState(state);
+ // determine whether this region should dispatch a regionLayoutUpdate event
+ // FIXME: currently it cannot determine whether a region whose regionOverflow state remained either "fit" or "overflow" has actually
+ // changed, so it just assumes that those region should dispatch the event
+ if (previousState != state
+ || state == RenderRegion::RegionFit
+ || state == RenderRegion::RegionOverflow)
+ region->setDispatchRegionLayoutUpdateEvent(true);
}
// With the regions overflow state computed we can also set the overflow for the named flow.
@@ -905,6 +731,35 @@ void RenderFlowThread::computeOverflowStateForRegions(LayoutUnit oldClientAfterE
m_overflow = lastReg && (lastReg->regionState() == RenderRegion::RegionOverflow);
}
+void RenderFlowThread::regionLayoutUpdateEventTimerFired(Timer<RenderFlowThread>*)
+{
+ // Create a copy of region nodes, to protect them for being destroyed in the event listener
+ Vector<RefPtr<Node> > regionNodes;
+ regionNodes.reserveCapacity(m_regionList.size());
+ for (RenderRegionList::iterator iter = m_regionList.begin(); iter != m_regionList.end(); ++iter) {
+ RenderRegion* region = *iter;
+ ASSERT(region->node() && region->node()->isElementNode());
+ // dispatch the event only for marked regions and only for those who have a listener
+ if (region->shouldDispatchRegionLayoutUpdateEvent()) {
+ regionNodes.append(region->node());
+ // clear the dispatch flag here, as it is possible to be set again due to event listeners
+ region->setDispatchRegionLayoutUpdateEvent(false);
+ }
+ }
+ for (Vector<RefPtr<Node> >::const_iterator it = regionNodes.begin(); it != regionNodes.end(); ++it) {
+ RefPtr<Node> node = *it;
+ RefPtr<Document> document = node->document();
+ if (!document)
+ continue;
+ RenderObject* renderer = node->renderer();
+ if (renderer && renderer->isRenderRegion()) {
+ node->dispatchRegionLayoutUpdateEvent();
+ // Layout needs to be uptodate after each event listener
+ document->updateLayoutIgnorePendingStylesheets();
+ }
+ }
+}
+
bool RenderFlowThread::regionInRange(const RenderRegion* targetRegion, const RenderRegion* startRegion, const RenderRegion* endRegion) const
{
ASSERT(targetRegion);
@@ -939,7 +794,7 @@ bool RenderFlowThread::objectInFlowRegion(const RenderObject* object, const Rend
RenderRegion* enclosingBoxEndRegion = 0;
getRegionRangeForBox(enclosingBox, enclosingBoxStartRegion, enclosingBoxEndRegion);
if (!regionInRange(region, enclosingBoxStartRegion, enclosingBoxEndRegion))
- return false;
+ return false;
if (object->isBox())
return true;
@@ -971,4 +826,3 @@ bool RenderFlowThread::objectInFlowRegion(const RenderObject* object, const Rend
}
} // namespace WebCore
-
diff --git a/Source/WebCore/rendering/RenderFlowThread.h b/Source/WebCore/rendering/RenderFlowThread.h
index b958eb164..953939cd6 100644
--- a/Source/WebCore/rendering/RenderFlowThread.h
+++ b/Source/WebCore/rendering/RenderFlowThread.h
@@ -36,17 +36,13 @@
#include <wtf/ListHashSet.h>
#include <wtf/PassRefPtr.h>
#include <wtf/UnusedParam.h>
-#include <wtf/text/AtomicString.h>
namespace WebCore {
class RenderFlowThread;
class RenderStyle;
class RenderRegion;
-class WebKitNamedFlow;
-typedef ListHashSet<RenderFlowThread*> RenderFlowThreadList;
-typedef HashCountedSet<RenderFlowThread*> RenderFlowThreadCountedSet;
typedef ListHashSet<RenderRegion*> RenderRegionList;
// RenderFlowThread is used to collect all the render objects that participate in a
@@ -57,32 +53,24 @@ typedef ListHashSet<RenderRegion*> RenderRegionList;
class RenderFlowThread: public RenderBlock {
public:
- RenderFlowThread(Node*, const AtomicString& flowThread);
-
+ RenderFlowThread(Node*);
+ virtual ~RenderFlowThread() { };
+
virtual bool isRenderFlowThread() const { return true; }
virtual void layout();
- AtomicString flowThread() const { return m_flowThread; }
-
- // Always create a RenderLayer for the RenderFlowThread, so that we
- // can easily avoid to draw it's children directly.
+ // Always create a RenderLayer for the RenderFlowThread so that we
+ // can easily avoid drawing the children directly.
virtual bool requiresLayer() const { return true; }
-
- RenderObject* nextRendererForNode(Node*) const;
- RenderObject* previousRendererForNode(Node*) const;
- void addFlowChild(RenderObject* newChild, RenderObject* beforeChild = 0);
- void removeFlowChild(RenderObject*);
void removeFlowChildInfo(RenderObject*);
- bool hasChildren() const { return !m_flowThreadChildList.isEmpty(); }
#ifndef NDEBUG
- bool hasChild(RenderObject* child) const { return m_flowThreadChildList.contains(child); }
bool hasChildInfo(RenderObject* child) const { return child && child->isBox() && m_regionRangeMap.contains(toRenderBox(child)); }
#endif
- void addRegionToThread(RenderRegion*);
- void removeRegionFromThread(RenderRegion*);
+ virtual void addRegionToThread(RenderRegion*);
+ virtual void removeRegionFromThread(RenderRegion*);
const RenderRegionList& renderRegionList() const { return m_regionList; }
void computeLogicalWidth();
@@ -101,8 +89,6 @@ public:
void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
- void pushDependencies(RenderFlowThreadList&);
-
void repaintRectangleInRegions(const LayoutRect&, bool immediate);
LayoutUnit regionLogicalTopForLine(LayoutUnit position) const;
@@ -132,7 +118,7 @@ public:
void clearRenderBoxCustomStyle(const RenderBox*,
const RenderRegion* oldStartRegion = 0, const RenderRegion* oldEndRegion = 0,
const RenderRegion* newStartRegion = 0, const RenderRegion* newEndRegion = 0);
- WebKitNamedFlow* ensureNamedFlow();
+
void computeOverflowStateForRegions(LayoutUnit oldClientAfterEdge);
bool overflow() const { return m_overflow; }
@@ -140,22 +126,13 @@ public:
// Check if the object is in region and the region is part of this flow thread.
bool objectInFlowRegion(const RenderObject*, const RenderRegion*) const;
-private:
- virtual const char* renderName() const { return "RenderFlowThread"; }
-
- bool dependsOn(RenderFlowThread* otherRenderFlowThread) const;
- void addDependencyOnFlowThread(RenderFlowThread*);
- void removeDependencyOnFlowThread(RenderFlowThread*);
- void checkInvalidRegions();
+protected:
+ virtual const char* renderName() const = 0;
bool shouldRepaint(const LayoutRect&) const;
-
+ void regionLayoutUpdateEventTimerFired(Timer<RenderFlowThread>*);
bool regionInRange(const RenderRegion* targetRegion, const RenderRegion* startRegion, const RenderRegion* endRegion) const;
- typedef ListHashSet<RenderObject*> FlowThreadChildList;
- FlowThreadChildList m_flowThreadChildList;
-
- AtomicString m_flowThread;
RenderRegionList m_regionList;
class RenderRegionRange {
@@ -184,16 +161,6 @@ private:
RenderRegion* m_endRegion;
};
- // Observer flow threads have invalid regions that depend on the state of this thread
- // to re-validate their regions. Keeping a set of observer threads make it easy
- // to notify them when a region was removed from this flow.
- RenderFlowThreadCountedSet m_observerThreadsSet;
-
- // Some threads need to have a complete layout before we layout this flow.
- // That's because they contain a RenderRegion that should display this thread. The set makes it
- // easy to sort the order of threads layout.
- RenderFlowThreadCountedSet m_layoutBeforeThreadsSet;
-
// A maps from RenderBox
typedef HashMap<const RenderBox*, RenderRegionRange> RenderRegionRangeMap;
RenderRegionRangeMap m_regionRangeMap;
@@ -203,7 +170,7 @@ private:
bool m_regionsHaveUniformLogicalWidth;
bool m_regionsHaveUniformLogicalHeight;
bool m_overflow;
- RefPtr<WebKitNamedFlow> m_namedFlow;
+ Timer<RenderFlowThread> m_regionLayoutUpdateEventTimer;
};
inline RenderFlowThread* toRenderFlowThread(RenderObject* object)
diff --git a/Source/WebCore/rendering/RenderFrameBase.cpp b/Source/WebCore/rendering/RenderFrameBase.cpp
index b95e44755..046288bff 100644
--- a/Source/WebCore/rendering/RenderFrameBase.cpp
+++ b/Source/WebCore/rendering/RenderFrameBase.cpp
@@ -78,9 +78,9 @@ void RenderFrameBase::layoutWithFlattening(bool fixedWidth, bool fixedHeight)
// expand the frame by setting frame height = content height
if (isScrollable || !fixedHeight || childRoot->isFrameSet())
- setHeight(max(height(), childFrameView->contentsHeight() + vBorder));
+ setHeight(max<LayoutUnit>(height(), childFrameView->contentsHeight() + vBorder));
if (isScrollable || !fixedWidth || childRoot->isFrameSet())
- setWidth(max(width(), childFrameView->contentsWidth() + hBorder));
+ setWidth(max<LayoutUnit>(width(), childFrameView->contentsWidth() + hBorder));
updateWidgetPosition();
diff --git a/Source/WebCore/rendering/RenderFrameSet.cpp b/Source/WebCore/rendering/RenderFrameSet.cpp
index bcce93ef8..e02c06689 100644
--- a/Source/WebCore/rendering/RenderFrameSet.cpp
+++ b/Source/WebCore/rendering/RenderFrameSet.cpp
@@ -215,7 +215,7 @@ void RenderFrameSet::layOutAxis(GridAxis& axis, const Length* grid, int availabl
// Count the total length of all of the fixed columns/rows -> totalFixed
// Count the number of columns/rows which are fixed -> countFixed
if (grid[i].isFixed()) {
- gridLayout[i] = max(grid[i].value(), 0);
+ gridLayout[i] = max(grid[i].intValue(), 0);
totalFixed += gridLayout[i];
countFixed++;
}
@@ -223,7 +223,7 @@ void RenderFrameSet::layOutAxis(GridAxis& axis, const Length* grid, int availabl
// Count the total percentage of all of the percentage columns/rows -> totalPercent
// Count the number of columns/rows which are percentages -> countPercent
if (grid[i].isPercent()) {
- gridLayout[i] = max(grid[i].calcValue(availableLen), 0);
+ gridLayout[i] = max(intValueForLength(grid[i], availableLen), 0);
totalPercent += gridLayout[i];
countPercent++;
}
@@ -231,7 +231,7 @@ void RenderFrameSet::layOutAxis(GridAxis& axis, const Length* grid, int availabl
// Count the total relative of all the relative columns/rows -> totalRelative
// Count the number of columns/rows which are relative -> countRelative
if (grid[i].isRelative()) {
- totalRelative += max(grid[i].value(), 1);
+ totalRelative += max(grid[i].intValue(), 1);
countRelative++;
}
}
@@ -276,7 +276,7 @@ void RenderFrameSet::layOutAxis(GridAxis& axis, const Length* grid, int availabl
for (int i = 0; i < gridLen; ++i) {
if (grid[i].isRelative()) {
- gridLayout[i] = (max(grid[i].value(), 1) * remainingRelative) / totalRelative;
+ gridLayout[i] = (max(grid[i].intValue(), 1) * remainingRelative) / totalRelative;
remainingLen -= gridLayout[i];
lastRelative = i;
}
@@ -472,8 +472,8 @@ void RenderFrameSet::layout()
setHeight(view()->viewHeight());
}
- size_t cols = frameSet()->totalCols();
- size_t rows = frameSet()->totalRows();
+ unsigned cols = frameSet()->totalCols();
+ unsigned rows = frameSet()->totalRows();
if (m_rows.m_sizes.size() != rows || m_cols.m_sizes.size() != cols) {
m_rows.resize(rows);
diff --git a/Source/WebCore/rendering/RenderFullScreen.cpp b/Source/WebCore/rendering/RenderFullScreen.cpp
index 1d689f5c9..e0507388d 100644
--- a/Source/WebCore/rendering/RenderFullScreen.cpp
+++ b/Source/WebCore/rendering/RenderFullScreen.cpp
@@ -113,8 +113,10 @@ RenderObject* RenderFullScreen::wrapRenderer(RenderObject* object, Document* doc
if (RenderObject* parent = object->parent()) {
parent->addChild(fullscreenRenderer, object);
object->remove();
+ parent->setNeedsLayoutAndPrefWidthsRecalc();
}
fullscreenRenderer->addChild(object);
+ fullscreenRenderer->setNeedsLayoutAndPrefWidthsRecalc();
}
document->setFullScreenRenderer(fullscreenRenderer);
return fullscreenRenderer;
@@ -127,6 +129,7 @@ void RenderFullScreen::unwrapRenderer()
while ((child = firstChild())) {
child->remove();
parent()->addChild(child, this);
+ parent()->setNeedsLayoutAndPrefWidthsRecalc();
}
}
if (placeholder())
@@ -140,7 +143,7 @@ void RenderFullScreen::setPlaceholder(RenderBlock* placeholder)
m_placeholder = placeholder;
}
-void RenderFullScreen::createPlaceholder(PassRefPtr<RenderStyle> style, const IntRect& frameRect)
+void RenderFullScreen::createPlaceholder(PassRefPtr<RenderStyle> style, const LayoutRect& frameRect)
{
if (style->width().isAuto())
style->setWidth(Length(frameRect.width(), Fixed));
@@ -150,8 +153,10 @@ void RenderFullScreen::createPlaceholder(PassRefPtr<RenderStyle> style, const In
if (!m_placeholder) {
m_placeholder = new (document()->renderArena()) RenderFullScreenPlaceholder(this);
m_placeholder->setStyle(style);
- if (parent())
+ if (parent()) {
parent()->addChild(m_placeholder, this);
+ parent()->setNeedsLayoutAndPrefWidthsRecalc();
+ }
} else
m_placeholder->setStyle(style);
}
diff --git a/Source/WebCore/rendering/RenderFullScreen.h b/Source/WebCore/rendering/RenderFullScreen.h
index 7968792b2..d0aac50ac 100644
--- a/Source/WebCore/rendering/RenderFullScreen.h
+++ b/Source/WebCore/rendering/RenderFullScreen.h
@@ -39,7 +39,7 @@ public:
void setPlaceholder(RenderBlock*);
RenderBlock* placeholder() { return m_placeholder; }
- void createPlaceholder(PassRefPtr<RenderStyle>, const IntRect& frameRect);
+ void createPlaceholder(PassRefPtr<RenderStyle>, const LayoutRect& frameRect);
static RenderObject* wrapRenderer(RenderObject* renderer, Document*);
diff --git a/Source/WebCore/rendering/RenderHTMLCanvas.cpp b/Source/WebCore/rendering/RenderHTMLCanvas.cpp
index 0df9fe998..33116989e 100644
--- a/Source/WebCore/rendering/RenderHTMLCanvas.cpp
+++ b/Source/WebCore/rendering/RenderHTMLCanvas.cpp
@@ -88,7 +88,7 @@ void RenderHTMLCanvas::canvasSizeChanged()
if (!preferredLogicalWidthsDirty())
setPreferredLogicalWidthsDirty(true);
- IntSize oldSize = size();
+ LayoutSize oldSize = size();
computeLogicalWidth();
computeLogicalHeight();
if (oldSize == size())
diff --git a/Source/WebCore/rendering/RenderIFrame.cpp b/Source/WebCore/rendering/RenderIFrame.cpp
index 743e3f4c2..ffd50aeb8 100644
--- a/Source/WebCore/rendering/RenderIFrame.cpp
+++ b/Source/WebCore/rendering/RenderIFrame.cpp
@@ -57,7 +57,7 @@ void RenderIFrame::computeLogicalHeight()
if (!view)
return;
int border = borderTop() + borderBottom();
- setHeight(max(height(), view->contentsHeight() + border));
+ setHeight(max<LayoutUnit>(height(), view->contentsHeight() + border));
}
}
@@ -75,7 +75,7 @@ void RenderIFrame::computeLogicalWidth()
if (!view)
return;
LayoutUnit border = borderLeft() + borderRight();
- setWidth(max(width(), view->contentsWidth() + border));
+ setWidth(max<LayoutUnit>(width(), view->contentsWidth() + border));
}
}
@@ -85,24 +85,20 @@ bool RenderIFrame::flattenFrame()
return false;
HTMLIFrameElement* element = static_cast<HTMLIFrameElement*>(node());
- bool isScrollable = element->scrollingMode() != ScrollbarAlwaysOff;
-
- if (style()->width().isFixed() && style()->height().isFixed()) {
- if (!isScrollable)
- return false;
- if (style()->width().value() <= 0 || style()->height().value() <= 0)
- return false;
- }
-
Frame* frame = element->document()->frame();
+
bool enabled = frame && frame->settings() && frame->settings()->frameFlatteningEnabled();
if (!enabled || !frame->page())
return false;
- FrameView* view = frame->page()->mainFrame()->view();
- if (!view)
- return false;
+ if (style()->width().isFixed() && style()->height().isFixed()) {
+ // Do not flatten iframes with scrolling="no".
+ if (element->scrollingMode() == ScrollbarAlwaysOff)
+ return false;
+ if (style()->width().value() <= 0 || style()->height().value() <= 0)
+ return false;
+ }
// Do not flatten offscreen inner frames during frame flattening, as flattening might make them visible.
IntRect boundingRect = absoluteBoundingBoxRectIgnoringTransforms();
diff --git a/Source/WebCore/rendering/RenderIFrame.h b/Source/WebCore/rendering/RenderIFrame.h
index b6b30c9ea..fe6631e36 100644
--- a/Source/WebCore/rendering/RenderIFrame.h
+++ b/Source/WebCore/rendering/RenderIFrame.h
@@ -34,6 +34,8 @@ class RenderIFrame : public RenderFrameBase {
public:
explicit RenderIFrame(Element*);
+ bool flattenFrame();
+
private:
virtual void computeLogicalHeight();
virtual void computeLogicalWidth();
@@ -44,8 +46,6 @@ private:
virtual const char* renderName() const { return "RenderPartObject"; } // Lying for now to avoid breaking tests
- bool flattenFrame();
-
};
inline RenderIFrame* toRenderIFrame(RenderObject* object)
diff --git a/Source/WebCore/rendering/RenderImage.cpp b/Source/WebCore/rendering/RenderImage.cpp
index 6406f6f66..35caaff29 100644
--- a/Source/WebCore/rendering/RenderImage.cpp
+++ b/Source/WebCore/rendering/RenderImage.cpp
@@ -6,6 +6,7 @@
* (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
* Copyright (C) 2010 Google Inc. All rights reserved.
+ * Copyright (C) Research In Motion Limited 2011-2012. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -39,7 +40,7 @@
#include "HTMLNames.h"
#include "HitTestResult.h"
#include "Page.h"
-#include "RenderLayer.h"
+#include "PaintInfo.h"
#include "RenderView.h"
#include "SVGImage.h"
#include <wtf/UnusedParam.h>
@@ -175,7 +176,7 @@ void RenderImage::imageChanged(WrappedImagePtr newImage, const IntRect* rect)
imageDimensionsChanged(imageSizeChanged, rect);
}
-bool RenderImage::updateIntrinsicSizeIfNeeded(const LayoutSize& newSize, bool imageSizeChanged)
+bool RenderImage::updateIntrinsicSizeIfNeeded(const IntSize& newSize, bool imageSizeChanged)
{
if (newSize == intrinsicSize() && !imageSizeChanged)
return false;
@@ -226,10 +227,8 @@ void RenderImage::imageDimensionsChanged(bool imageSizeChanged, const IntRect* r
repaintRectangle(repaintRect);
#if USE(ACCELERATED_COMPOSITING)
- if (hasLayer()) {
- // Tell any potential compositing layers that the image needs updating.
- layer()->contentChanged(RenderLayer::ImageChanged);
- }
+ // Tell any potential compositing layers that the image needs updating.
+ contentChanged(ImageChanged);
#endif
}
}
@@ -243,10 +242,10 @@ void RenderImage::notifyFinished(CachedResource* newImage)
return;
#if USE(ACCELERATED_COMPOSITING)
- if (newImage == m_imageResource->cachedImage() && hasLayer()) {
+ if (newImage == m_imageResource->cachedImage()) {
// tell any potential compositing layers
// that the image is done and they can reference it directly.
- layer()->contentChanged(RenderLayer::ImageChanged);
+ contentChanged(ImageChanged);
}
#else
UNUSED_PARAM(newImage);
@@ -306,7 +305,7 @@ void RenderImage::paintReplaced(PaintInfo& paintInfo, const LayoutPoint& paintOf
if (centerY < 0)
centerY = 0;
imageOffset = LayoutSize(leftBorder + leftPad + centerX + 1, topBorder + topPad + centerY + 1);
- context->drawImage(image.get(), style()->colorSpace(), IntRect(roundedIntPoint(paintOffset + imageOffset), imageSize));
+ context->drawImage(image.get(), style()->colorSpace(), IntRect(roundedIntPoint(paintOffset + imageOffset), imageSize), CompositeSourceOver, shouldRespectImageOrientation());
errorPictureDrawn = true;
}
@@ -416,18 +415,19 @@ void RenderImage::areaElementFocusChanged(HTMLAreaElement* element)
void RenderImage::paintIntoRect(GraphicsContext* context, const LayoutRect& rect)
{
- if (!m_imageResource->hasImage() || m_imageResource->errorOccurred() || rect.width() <= 0 || rect.height() <= 0)
+ IntRect alignedRect = pixelSnappedIntRect(rect);
+ if (!m_imageResource->hasImage() || m_imageResource->errorOccurred() || alignedRect.width() <= 0 || alignedRect.height() <= 0)
return;
- RefPtr<Image> img = m_imageResource->image(rect.width(), rect.height());
+ RefPtr<Image> img = m_imageResource->image(alignedRect.width(), alignedRect.height());
if (!img || img->isNull())
return;
HTMLImageElement* imageElt = (node() && node()->hasTagName(imgTag)) ? static_cast<HTMLImageElement*>(node()) : 0;
CompositeOperator compositeOperator = imageElt ? imageElt->compositeOperator() : CompositeSourceOver;
Image* image = m_imageResource->image().get();
- bool useLowQualityScaling = shouldPaintAtLowQuality(context, image, image, rect.size());
- context->drawImage(m_imageResource->image(rect.width(), rect.height()).get(), style()->colorSpace(), rect, compositeOperator, useLowQualityScaling);
+ bool useLowQualityScaling = shouldPaintAtLowQuality(context, image, image, alignedRect.size());
+ context->drawImage(m_imageResource->image(alignedRect.width(), alignedRect.height()).get(), style()->colorSpace(), alignedRect, compositeOperator, shouldRespectImageOrientation(), useLowQualityScaling);
}
bool RenderImage::backgroundIsObscured() const
@@ -469,7 +469,7 @@ HTMLMapElement* RenderImage::imageMap() const
bool RenderImage::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const LayoutPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
{
- HitTestResult tempResult(result.point(), result.topPadding(), result.rightPadding(), result.bottomPadding(), result.leftPadding());
+ HitTestResult tempResult(result.point(), result.topPadding(), result.rightPadding(), result.bottomPadding(), result.leftPadding(), result.shadowContentFilterPolicy());
bool inside = RenderReplaced::nodeAtPoint(request, tempResult, pointInContainer, accumulatedOffset, hitTestAction);
if (tempResult.innerNode() && node()) {
@@ -502,52 +502,34 @@ void RenderImage::updateAltText()
m_altText = static_cast<HTMLImageElement*>(node())->altText();
}
-LayoutUnit RenderImage::computeReplacedLogicalWidth(bool includeMaxWidth) const
+void RenderImage::layout()
{
- // If we've got an explicit width/height assigned, propagate it to the image resource.
- if (style()->logicalWidth().isSpecified() && style()->logicalHeight().isSpecified()) {
- LayoutUnit width = RenderReplaced::computeReplacedLogicalWidth(includeMaxWidth);
- m_imageResource->setContainerSizeForRenderer(IntSize(width, computeReplacedLogicalHeight()));
- return width;
- }
-
- IntSize containerSize;
- if (m_imageResource->imageHasRelativeWidth() || m_imageResource->imageHasRelativeHeight()) {
- // Propagate the containing block size to the image resource, otherwhise we can't compute our own intrinsic size, if it's relative.
- RenderObject* containingBlock = isPositioned() ? container() : this->containingBlock();
- if (containingBlock->isBox()) {
- RenderBox* box = toRenderBox(containingBlock);
- containerSize = IntSize(box->availableWidth(), box->availableHeight()); // Already contains zooming information.
- }
- } else {
- // Propagate the current zoomed image size to the image resource, otherwhise the image size will remain the same on-screen.
- CachedImage* cachedImage = m_imageResource->cachedImage();
- if (cachedImage && cachedImage->image()) {
- containerSize = cachedImage->image()->size();
- // FIXME: Remove unnecessary rounding when layout is off ints: webkit.org/b/63656
- containerSize.setWidth(static_cast<LayoutUnit>(containerSize.width() * style()->effectiveZoom()));
- containerSize.setHeight(static_cast<LayoutUnit>(containerSize.height() * style()->effectiveZoom()));
- }
- }
+ RenderReplaced::layout();
- if (!containerSize.isEmpty()) {
+ // Propagate container size to image resource.
+ IntSize containerSize(contentWidth(), contentHeight());
+ if (!containerSize.isEmpty())
m_imageResource->setContainerSizeForRenderer(containerSize);
- const_cast<RenderImage*>(this)->updateIntrinsicSizeIfNeeded(containerSize, false);
- }
-
- return RenderReplaced::computeReplacedLogicalWidth(includeMaxWidth);
}
void RenderImage::computeIntrinsicRatioInformation(FloatSize& intrinsicSize, double& intrinsicRatio, bool& isPercentageIntrinsicSize) const
{
- // Assure this method is never used for SVGImages.
- ASSERT(!embeddedContentBox());
- isPercentageIntrinsicSize = false;
- CachedImage* cachedImage = m_imageResource ? m_imageResource->cachedImage() : 0;
- if (!cachedImage || !cachedImage->image())
+ RenderReplaced::computeIntrinsicRatioInformation(intrinsicSize, intrinsicRatio, isPercentageIntrinsicSize);
+
+ // Our intrinsicSize is empty if we're rendering generated images with relative width/height. Figure out the right intrinsic size to use.
+ if (intrinsicSize.isEmpty() && (m_imageResource->imageHasRelativeWidth() || m_imageResource->imageHasRelativeHeight())) {
+ RenderObject* containingBlock = isPositioned() ? container() : this->containingBlock();
+ if (containingBlock->isBox()) {
+ RenderBox* box = toRenderBox(containingBlock);
+ intrinsicSize.setWidth(box->availableLogicalWidth());
+ intrinsicSize.setHeight(box->availableLogicalHeight());
+ }
+ }
+ // Don't compute an intrinsic ratio to preserve historical WebKit behavior if we're painting alt text and/or a broken image.
+ if (m_imageResource && m_imageResource->errorOccurred()) {
+ intrinsicRatio = 1;
return;
- intrinsicSize = cachedImage->image()->size();
- intrinsicRatio = intrinsicSize.width() / static_cast<double>(intrinsicSize.height());
+ }
}
bool RenderImage::needsPreferredWidthsRecalculation() const
diff --git a/Source/WebCore/rendering/RenderImage.h b/Source/WebCore/rendering/RenderImage.h
index 489ceb13a..11197cce1 100644
--- a/Source/WebCore/rendering/RenderImage.h
+++ b/Source/WebCore/rendering/RenderImage.h
@@ -68,6 +68,7 @@ protected:
virtual void paintIntoRect(GraphicsContext*, const LayoutRect&);
virtual void paint(PaintInfo&, const LayoutPoint&);
+ virtual void layout();
virtual void intrinsicSizeChanged()
{
@@ -90,11 +91,9 @@ private:
virtual void notifyFinished(CachedResource*);
virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const LayoutPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction);
- virtual LayoutUnit computeReplacedLogicalWidth(bool includeMaxWidth = true) const;
-
IntSize imageSizeForError(CachedImage*) const;
void imageDimensionsChanged(bool imageSizeChanged, const IntRect* = 0);
- bool updateIntrinsicSizeIfNeeded(const LayoutSize&, bool imageSizeChanged);
+ bool updateIntrinsicSizeIfNeeded(const IntSize&, bool imageSizeChanged);
void paintAreaElementFocusRing(PaintInfo&);
diff --git a/Source/WebCore/rendering/RenderInline.cpp b/Source/WebCore/rendering/RenderInline.cpp
index 0a5a65ee9..4449d72e3 100644
--- a/Source/WebCore/rendering/RenderInline.cpp
+++ b/Source/WebCore/rendering/RenderInline.cpp
@@ -146,9 +146,8 @@ static void updateStyleOfAnonymousBlockContinuations(RenderObject* block, const
RenderInline* cont = toRenderBlock(block)->inlineElementContinuation();
if (oldStyle->position() == RelativePosition && hasRelPositionedInlineAncestor(cont))
continue;
- RefPtr<RenderStyle> blockStyle = RenderStyle::createAnonymousStyle(block->style());
+ RefPtr<RenderStyle> blockStyle = RenderStyle::createAnonymousStyleWithDisplay(block->style(), BLOCK);
blockStyle->setPosition(newStyle->position());
- blockStyle->setDisplay(BLOCK);
block->setStyle(blockStyle);
}
}
@@ -281,8 +280,7 @@ void RenderInline::addChildIgnoringContinuation(RenderObject* newChild, RenderOb
// inline into continuations. This involves creating an anonymous block box to hold
// |newChild|. We then make that block box a continuation of this inline. We take all of
// the children after |beforeChild| and put them in a clone of this object.
- RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyle(style());
- newStyle->setDisplay(BLOCK);
+ RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(style(), BLOCK);
// If inside an inline affected by relative positioning the block needs to be affected by it too.
// Giving the block a layer like this allows it to collect the x/y offsets from inline parents later.
@@ -426,7 +424,7 @@ void RenderInline::splitFlow(RenderObject* beforeChild, RenderBlock* newBlockBox
madeNewBeforeBlock = true;
}
- RenderBlock* post = block->createAnonymousBlockWithSameTypeAs(pre);
+ RenderBlock* post = toRenderBlock(pre->createAnonymousBoxWithSameTypeAs(block));
RenderObject* boxFirst = madeNewBeforeBlock ? block->firstChild() : pre->nextSibling();
if (madeNewBeforeBlock)
@@ -701,7 +699,9 @@ static LayoutUnit computeMargin(const RenderInline* renderer, const Length& marg
if (margin.isFixed())
return margin.value();
if (margin.isPercent())
- return margin.calcMinValue(max<LayoutUnit>(0, renderer->containingBlock()->availableLogicalWidth()));
+ return minimumValueForLength(margin, max<LayoutUnit>(0, renderer->containingBlock()->availableLogicalWidth()));
+ if (margin.isViewportPercentage())
+ return valueForLength(margin, 0, renderer->view());
return 0;
}
@@ -785,14 +785,14 @@ VisiblePosition RenderInline::positionForPoint(const LayoutPoint& point)
return RenderBoxModelObject::positionForPoint(point);
}
-LayoutRect RenderInline::linesBoundingBox() const
+IntRect RenderInline::linesBoundingBox() const
{
if (!alwaysCreateLineBoxes()) {
ASSERT(!firstLineBox());
- return enclosingLayoutRect(culledInlineBoundingBox(this));
+ return enclosingIntRect(culledInlineBoundingBox(this));
}
- LayoutRect result;
+ IntRect result;
// See <rdar://problem/5289721>, for an unknown reason the linked list here is sometimes inconsistent, first is non-zero and last is zero. We have been
// unable to reproduce this at all (and consequently unable to figure ot why this is happening). The assert will hopefully catch the problem in debug
@@ -815,7 +815,7 @@ LayoutRect RenderInline::linesBoundingBox() const
float y = isHorizontal ? firstLineBox()->y() : logicalLeftSide;
float width = isHorizontal ? logicalRightSide - logicalLeftSide : lastLineBox()->logicalBottom() - x;
float height = isHorizontal ? lastLineBox()->logicalBottom() - y : logicalRightSide - logicalLeftSide;
- result = enclosingLayoutRect(FloatRect(x, y, width, height));
+ result = enclosingIntRect(FloatRect(x, y, width, height));
}
return result;
@@ -976,8 +976,8 @@ LayoutRect RenderInline::linesVisualOverflowBoundingBox() const
return LayoutRect();
// Return the width of the minimal left side and the maximal right side.
- LayoutUnit logicalLeftSide = numeric_limits<LayoutUnit>::max();
- LayoutUnit logicalRightSide = numeric_limits<LayoutUnit>::min();
+ LayoutUnit logicalLeftSide = MAX_LAYOUT_UNIT;
+ LayoutUnit logicalRightSide = MIN_LAYOUT_UNIT;
for (InlineFlowBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) {
logicalLeftSide = min(logicalLeftSide, curr->logicalLeftVisualOverflow());
logicalRightSide = max(logicalRightSide, curr->logicalRightVisualOverflow());
@@ -1011,18 +1011,27 @@ LayoutRect RenderInline::clippedOverflowRectForRepaint(RenderBoxModelObject* rep
// Now invalidate a rectangle.
LayoutUnit ow = style() ? style()->outlineSize() : 0;
-
+
+ bool hitRepaintContainer = false;
+
// We need to add in the relative position offsets of any inlines (including us) up to our
// containing block.
RenderBlock* cb = containingBlock();
for (const RenderObject* inlineFlow = this; inlineFlow && inlineFlow->isRenderInline() && inlineFlow != cb;
inlineFlow = inlineFlow->parent()) {
- if (inlineFlow->style()->position() == RelativePosition && inlineFlow->hasLayer())
+ if (inlineFlow == repaintContainer) {
+ hitRepaintContainer = true;
+ break;
+ }
+ if (inlineFlow->style()->position() == RelativePosition && inlineFlow->hasLayer())
toRenderInline(inlineFlow)->layer()->relativePositionOffset(left, top);
}
LayoutRect r(-ow + left, -ow + top, boundingBox.width() + ow * 2, boundingBox.height() + ow * 2);
+ if (hitRepaintContainer || !cb)
+ return r;
+
if (cb->hasColumns())
cb->adjustRectForColumns(r);
@@ -1036,11 +1045,8 @@ LayoutRect RenderInline::clippedOverflowRectForRepaint(RenderBoxModelObject* rep
LayoutRect boxRect(LayoutPoint(), cb->cachedSizeForOverflowClip());
r = intersection(repaintRect, boxRect);
}
-
- // FIXME: need to ensure that we compute the correct repaint rect when the repaint container
- // is an inline.
- if (repaintContainer != this)
- cb->computeRectForRepaint(repaintContainer, r);
+
+ cb->computeRectForRepaint(repaintContainer, r);
if (ow) {
for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
@@ -1050,7 +1056,7 @@ LayoutRect RenderInline::clippedOverflowRectForRepaint(RenderBoxModelObject* rep
}
}
- if (continuation() && !continuation()->isInline()) {
+ if (continuation() && !continuation()->isInline() && continuation()->parent()) {
LayoutRect contRect = continuation()->rectWithOutlineForRepaint(repaintContainer, ow);
r.unite(contRect);
}
@@ -1104,18 +1110,6 @@ void RenderInline::computeRectForRepaint(RenderBoxModelObject* repaintContainer,
}
}
-#if ENABLE(CSS_FILTERS)
- if (style()->hasFilterOutsets()) {
- LayoutUnit topOutset;
- LayoutUnit rightOutset;
- LayoutUnit bottomOutset;
- LayoutUnit leftOutset;
- style()->filter().getOutsets(topOutset, rightOutset, bottomOutset, leftOutset);
- rect.move(-leftOutset, -topOutset);
- rect.expand(leftOutset + rightOutset, topOutset + bottomOutset);
- }
-#endif
-
if (style()->position() == RelativePosition && layer()) {
// Apply the relative position offset when invalidating a rectangle. The layer
// is translated, but the render box isn't, so we need to do this to get the
@@ -1168,7 +1162,7 @@ LayoutSize RenderInline::offsetFromContainer(RenderObject* container, const Layo
return offset;
}
-void RenderInline::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed, bool useTransforms, TransformState& transformState, bool* wasFixed) const
+void RenderInline::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed, bool useTransforms, TransformState& transformState, ApplyContainerFlipOrNot applyContainerFlip, bool* wasFixed) const
{
if (repaintContainer == this)
return;
@@ -1189,9 +1183,11 @@ void RenderInline::mapLocalToContainer(RenderBoxModelObject* repaintContainer, b
if (!o)
return;
- IntPoint centerPoint = roundedIntPoint(transformState.mappedPoint());
- if (o->isBox() && o->style()->isFlippedBlocksWritingMode())
- transformState.move(toRenderBox(o)->flipForWritingModeIncludingColumns(roundedIntPoint(transformState.mappedPoint())) - centerPoint);
+ if (applyContainerFlip && o->isBox() && o->style()->isFlippedBlocksWritingMode()) {
+ IntPoint centerPoint = roundedIntPoint(transformState.mappedPoint());
+ transformState.move(toRenderBox(o)->flipForWritingModeIncludingColumns(centerPoint) - centerPoint);
+ applyContainerFlip = DoNotApplyContainerFlip;
+ }
LayoutSize containerOffset = offsetFromContainer(o, roundedLayoutPoint(transformState.mappedPoint()));
@@ -1211,7 +1207,7 @@ void RenderInline::mapLocalToContainer(RenderBoxModelObject* repaintContainer, b
return;
}
- o->mapLocalToContainer(repaintContainer, fixed, useTransforms, transformState, wasFixed);
+ o->mapLocalToContainer(repaintContainer, fixed, useTransforms, transformState, applyContainerFlip, wasFixed);
}
void RenderInline::updateDragState(bool dragOn)
@@ -1307,10 +1303,10 @@ LayoutUnit RenderInline::lineHeight(bool firstLine, LineDirectionMode /*directio
if (firstLine && document()->usesFirstLineRules()) {
RenderStyle* s = style(firstLine);
if (s != style())
- return s->computedLineHeight();
+ return s->computedLineHeight(view());
}
- return style()->computedLineHeight();
+ return style()->computedLineHeight(view());
}
LayoutUnit RenderInline::baselinePosition(FontBaseline baselineType, bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) const
@@ -1457,6 +1453,8 @@ void RenderInline::paintOutlineForLine(GraphicsContext* graphicsContext, const L
LayoutSize(thisline.width() + offset, thisline.height() + offset));
IntRect pixelSnappedBox = pixelSnappedIntRect(box);
+ IntRect pixelSnappedLastLine = pixelSnappedIntRect(paintOffset.x() + lastline.x(), 0, lastline.width(), 0);
+ IntRect pixelSnappedNextLine = pixelSnappedIntRect(paintOffset.x() + nextline.x(), 0, nextline.width(), 0);
// left edge
drawLineForBoxSide(graphicsContext,
@@ -1486,7 +1484,7 @@ void RenderInline::paintOutlineForLine(GraphicsContext* graphicsContext, const L
drawLineForBoxSide(graphicsContext,
pixelSnappedBox.x() - outlineWidth,
pixelSnappedBox.y() - outlineWidth,
- min(pixelSnappedBox.maxX() + outlineWidth, (lastline.isEmpty() ? 1000000 : paintOffset.x() + lastline.x())),
+ min(pixelSnappedBox.maxX() + outlineWidth, (lastline.isEmpty() ? 1000000 : pixelSnappedLastLine.x())),
pixelSnappedBox.y(),
BSTop, outlineColor, outlineStyle,
outlineWidth,
@@ -1495,7 +1493,7 @@ void RenderInline::paintOutlineForLine(GraphicsContext* graphicsContext, const L
if (lastline.maxX() < thisline.maxX())
drawLineForBoxSide(graphicsContext,
- max(lastline.isEmpty() ? -1000000 : paintOffset.x() + lastline.maxX(), pixelSnappedBox.x() - outlineWidth),
+ max(lastline.isEmpty() ? -1000000 : pixelSnappedLastLine.maxX(), pixelSnappedBox.x() - outlineWidth),
pixelSnappedBox.y() - outlineWidth,
pixelSnappedBox.maxX() + outlineWidth,
pixelSnappedBox.y(),
@@ -1519,7 +1517,7 @@ void RenderInline::paintOutlineForLine(GraphicsContext* graphicsContext, const L
drawLineForBoxSide(graphicsContext,
pixelSnappedBox.x() - outlineWidth,
pixelSnappedBox.maxY(),
- min(pixelSnappedBox.maxX() + outlineWidth, !nextline.isEmpty() ? paintOffset.x() + nextline.x() + 1 : 1000000),
+ min(pixelSnappedBox.maxX() + outlineWidth, !nextline.isEmpty() ? pixelSnappedNextLine.x() + 1 : 1000000),
pixelSnappedBox.maxY() + outlineWidth,
BSBottom, outlineColor, outlineStyle,
outlineWidth,
@@ -1528,7 +1526,7 @@ void RenderInline::paintOutlineForLine(GraphicsContext* graphicsContext, const L
if (nextline.maxX() < thisline.maxX())
drawLineForBoxSide(graphicsContext,
- max(!nextline.isEmpty() ? paintOffset.x() + nextline.maxX() : -1000000, pixelSnappedBox.x() - outlineWidth),
+ max(!nextline.isEmpty() ? pixelSnappedNextLine.maxX() : -1000000, pixelSnappedBox.x() - outlineWidth),
pixelSnappedBox.maxY(),
pixelSnappedBox.maxX() + outlineWidth,
pixelSnappedBox.maxY() + outlineWidth,
diff --git a/Source/WebCore/rendering/RenderInline.h b/Source/WebCore/rendering/RenderInline.h
index 0cb026448..190cbec41 100644
--- a/Source/WebCore/rendering/RenderInline.h
+++ b/Source/WebCore/rendering/RenderInline.h
@@ -51,7 +51,7 @@ public:
virtual LayoutSize offsetFromContainer(RenderObject*, const LayoutPoint&) const;
- LayoutRect linesBoundingBox() const;
+ IntRect linesBoundingBox() const;
LayoutRect linesVisualOverflowBoundingBox() const;
InlineFlowBox* createAndAppendInlineFlowBox();
@@ -130,14 +130,14 @@ private:
virtual LayoutRect rectWithOutlineForRepaint(RenderBoxModelObject* repaintContainer, LayoutUnit outlineWidth) const;
virtual void computeRectForRepaint(RenderBoxModelObject* repaintContainer, LayoutRect&, bool fixed) const;
- virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed, bool useTransforms, TransformState&, bool* wasFixed = 0) const;
+ virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed, bool useTransforms, TransformState&, ApplyContainerFlipOrNot = ApplyContainerFlip, bool* wasFixed = 0) const;
virtual VisiblePosition positionForPoint(const LayoutPoint&);
- virtual LayoutRect borderBoundingBox() const
+ virtual IntRect borderBoundingBox() const
{
- LayoutRect boundingBox = linesBoundingBox();
- return LayoutRect(0, 0, boundingBox.width(), boundingBox.height());
+ IntRect boundingBox = linesBoundingBox();
+ return IntRect(0, 0, boundingBox.width(), boundingBox.height());
}
virtual InlineFlowBox* createInlineFlowBox(); // Subclassed by SVG and Ruby
diff --git a/Source/WebCore/rendering/RenderInputSpeech.cpp b/Source/WebCore/rendering/RenderInputSpeech.cpp
index 0f14925bb..370ae0aec 100644
--- a/Source/WebCore/rendering/RenderInputSpeech.cpp
+++ b/Source/WebCore/rendering/RenderInputSpeech.cpp
@@ -46,7 +46,7 @@ static const float defaultSpeechButtonSize = 16;
static const float minSpeechButtonSize = 8;
static const float maxSpeechButtonSize = 40;
-void RenderInputSpeech::adjustInputFieldSpeechButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*)
+void RenderInputSpeech::adjustInputFieldSpeechButtonStyle(StyleResolver*, RenderStyle* style, Element*)
{
// Scale the button size based on the font size.
float fontScale = style->fontSize() / defaultControlFontPixelSize;
@@ -66,19 +66,19 @@ bool RenderInputSpeech::paintInputFieldSpeechButton(RenderObject* object, const
if (!input->renderer()->isBox())
return false;
RenderBox* inputRenderBox = toRenderBox(input->renderer());
- IntRect inputContentBox = inputRenderBox->contentBoxRect();
+ LayoutRect inputContentBox = inputRenderBox->contentBoxRect();
// Make sure the scaled button stays square and will fit in its parent's box.
- int buttonSize = std::min(inputContentBox.width(), std::min(inputContentBox.height(), rect.height()));
+ LayoutUnit buttonSize = std::min(inputContentBox.width(), std::min<LayoutUnit>(inputContentBox.height(), rect.height()));
// Calculate button's coordinates relative to the input element.
// Center the button vertically. Round up though, so if it has to be one pixel off-center, it will
// be one pixel closer to the bottom of the field. This tends to look better with the text.
- IntRect buttonRect(object->offsetFromAncestorContainer(inputRenderBox).width(),
- inputContentBox.y() + (inputContentBox.height() - buttonSize + 1) / 2,
- buttonSize, buttonSize);
+ LayoutRect buttonRect(object->offsetFromAncestorContainer(inputRenderBox).width(),
+ inputContentBox.y() + (inputContentBox.height() - buttonSize + 1) / 2,
+ buttonSize, buttonSize);
// Compute an offset between the part renderer and the input renderer.
- IntSize offsetFromInputRenderer = -(object->offsetFromAncestorContainer(inputRenderBox));
+ LayoutSize offsetFromInputRenderer = -(object->offsetFromAncestorContainer(inputRenderBox));
// Move the rect into partRenderer's coords.
buttonRect.move(offsetFromInputRenderer);
// Account for the local drawing offset.
@@ -94,7 +94,7 @@ bool RenderInputSpeech::paintInputFieldSpeechButton(RenderObject* object, const
image = imageStateRecording.get();
else if (speechButton->state() == InputFieldSpeechButtonElement::Recognizing)
image = imageStateWaiting.get();
- paintInfo.context->drawImage(image, object->style()->colorSpace(), buttonRect);
+ paintInfo.context->drawImage(image, object->style()->colorSpace(), pixelSnappedIntRect(buttonRect));
return false;
}
diff --git a/Source/WebCore/rendering/RenderInputSpeech.h b/Source/WebCore/rendering/RenderInputSpeech.h
index 63ef8ae65..f37b836f4 100644
--- a/Source/WebCore/rendering/RenderInputSpeech.h
+++ b/Source/WebCore/rendering/RenderInputSpeech.h
@@ -39,7 +39,7 @@ namespace WebCore {
class RenderInputSpeech {
public:
- static void adjustInputFieldSpeechButtonStyle(CSSStyleSelector*, RenderStyle*, Element*);
+ static void adjustInputFieldSpeechButtonStyle(StyleResolver*, RenderStyle*, Element*);
static bool paintInputFieldSpeechButton(RenderObject*, const PaintInfo&, const IntRect&);
};
diff --git a/Source/WebCore/rendering/RenderLayer.cpp b/Source/WebCore/rendering/RenderLayer.cpp
index 9cf767ee8..33379cf24 100644
--- a/Source/WebCore/rendering/RenderLayer.cpp
+++ b/Source/WebCore/rendering/RenderLayer.cpp
@@ -46,7 +46,6 @@
#include "ColumnInfo.h"
#include "CSSPropertyNames.h"
-#include "CSSStyleSelector.h"
#include "Chrome.h"
#include "Document.h"
#include "DocumentEventQueue.h"
@@ -92,6 +91,7 @@
#include "Settings.h"
#include "SourceGraphic.h"
#include "StylePropertySet.h"
+#include "StyleResolver.h"
#include "TextStream.h"
#include "TransformationMatrix.h"
#include "TranslateTransformOperation.h"
@@ -165,7 +165,13 @@ RenderLayer::RenderLayer(RenderBoxModelObject* renderer)
, m_mustOverlapCompositedLayers(false)
#endif
, m_containsDirtyOverlayScrollbars(false)
+#if !ASSERT_DISABLED
+ , m_layerListMutationAllowed(true)
+#endif
, m_canSkipRepaintRectsUpdateOnScroll(renderer->isTableCell())
+#if ENABLE(CSS_FILTERS)
+ , m_hasFilterInfo(false)
+#endif
, m_renderer(renderer)
, m_parent(0)
, m_previous(0)
@@ -194,6 +200,14 @@ RenderLayer::RenderLayer(RenderBoxModelObject* renderer)
m_visibleContentStatusDirty = false;
m_hasVisibleContent = renderer->style()->visibility() == VISIBLE;
}
+
+ Node* node = renderer->node();
+ if (node && node->isElementNode()) {
+ // We save and restore only the scrollOffset as the other scroll values are recalculated.
+ Element* element = toElement(node);
+ m_scrollOffset = element->savedLayerScrollOffset();
+ element->setSavedLayerScrollOffset(IntSize());
+ }
}
RenderLayer::~RenderLayer()
@@ -208,11 +222,21 @@ RenderLayer::~RenderLayer()
frameView->removeScrollableArea(this);
}
+ if (!m_renderer->documentBeingDestroyed()) {
+ Node* node = m_renderer->node();
+ if (node && node->isElementNode())
+ toElement(node)->setSavedLayerScrollOffset(m_scrollOffset);
+ }
+
destroyScrollbar(HorizontalScrollbar);
destroyScrollbar(VerticalScrollbar);
if (m_reflection)
removeReflection();
+
+#if ENABLE(CSS_FILTERS)
+ removeFilterInfoIfNeeded();
+#endif
// Child layers will be deleted by their corresponding render objects, so
// we don't need to delete them ourselves.
@@ -223,7 +247,7 @@ RenderLayer::~RenderLayer()
delete m_marquee;
#if USE(ACCELERATED_COMPOSITING)
- clearBacking();
+ clearBacking(true);
#endif
// Make sure we have no lingering clip rects.
@@ -253,15 +277,6 @@ void RenderLayer::contentChanged(ContentChangeType changeType)
}
#endif // USE(ACCELERATED_COMPOSITING)
-bool RenderLayer::hasAcceleratedCompositing() const
-{
-#if USE(ACCELERATED_COMPOSITING)
- return compositor()->hasAcceleratedCompositing();
-#else
- return false;
-#endif
-}
-
bool RenderLayer::canRender3DTransforms() const
{
#if USE(ACCELERATED_COMPOSITING)
@@ -278,14 +293,24 @@ bool RenderLayer::paintsWithFilters() const
if (!renderer()->hasFilter())
return false;
+#if USE(ACCELERATED_COMPOSITING)
if (!isComposited())
return true;
if (!m_backing || !m_backing->canCompositeFilters())
return true;
+#endif
return false;
}
+
+bool RenderLayer::requiresFullLayerImageForFilters() const
+{
+ if (!paintsWithFilters())
+ return false;
+ FilterEffectRenderer* filter = filterRenderer();
+ return filter ? filter->hasFilterThatMovesPixels() : false;
+}
#endif
LayoutPoint RenderLayer::computeOffsetFromRoot(bool& hasLayerOffset) const
@@ -739,12 +764,13 @@ void RenderLayer::updateLayerPosition()
LayoutSize inlineBoundingBoxOffset; // We don't put this into the RenderLayer x/y for inlines, so we need to subtract it out when done.
if (renderer()->isRenderInline()) {
RenderInline* inlineFlow = toRenderInline(renderer());
- LayoutRect lineBox = inlineFlow->linesBoundingBox();
+ IntRect lineBox = inlineFlow->linesBoundingBox();
setSize(lineBox.size());
inlineBoundingBoxOffset = toSize(lineBox.location());
localPoint += inlineBoundingBoxOffset;
} else if (RenderBox* box = renderBox()) {
- setSize(box->size());
+ // FIXME: Is snapping the size really needed here for the RenderBox case?
+ setSize(pixelSnappedIntSize(box->size(), box->location()));
localPoint += box->topLeftLocationOffset();
}
@@ -820,8 +846,8 @@ TransformationMatrix RenderLayer::perspectiveTransform() const
const float boxWidth = borderBox.width();
const float boxHeight = borderBox.height();
- float perspectiveOriginX = style->perspectiveOriginX().calcFloatValue(boxWidth);
- float perspectiveOriginY = style->perspectiveOriginY().calcFloatValue(boxHeight);
+ float perspectiveOriginX = floatValueForLength(style->perspectiveOriginX(), boxWidth);
+ float perspectiveOriginY = floatValueForLength(style->perspectiveOriginY(), boxHeight);
// A perspective origin of 0,0 makes the vanishing point in the center of the element.
// We want it to be in the top-left, so subtract half the height and width.
@@ -844,8 +870,8 @@ FloatPoint RenderLayer::perspectiveOrigin() const
const LayoutRect borderBox = toRenderBox(renderer())->borderBoxRect();
RenderStyle* style = renderer()->style();
- return FloatPoint(style->perspectiveOriginX().calcFloatValue(borderBox.width()),
- style->perspectiveOriginY().calcFloatValue(borderBox.height()));
+ return FloatPoint(floatValueForLength(style->perspectiveOriginX(), borderBox.width()),
+ floatValueForLength(style->perspectiveOriginY(), borderBox.height()));
}
RenderLayer* RenderLayer::stackingContext() const
@@ -934,8 +960,107 @@ RenderLayer* RenderLayer::enclosingCompositingLayer(bool includeSelf) const
return 0;
}
+
+RenderLayer* RenderLayer::enclosingCompositingLayerForRepaint(bool includeSelf) const
+{
+ if (includeSelf && isComposited() && !backing()->paintsIntoCompositedAncestor())
+ return const_cast<RenderLayer*>(this);
+
+ for (const RenderLayer* curr = compositingContainer(this); curr; curr = compositingContainer(curr)) {
+ if (curr->isComposited() && !curr->backing()->paintsIntoCompositedAncestor())
+ return const_cast<RenderLayer*>(curr);
+ }
+
+ return 0;
+}
+#endif
+
+#if ENABLE(CSS_FILTERS)
+RenderLayer* RenderLayer::enclosingFilterLayer(bool includeSelf) const
+{
+ const RenderLayer* curr = includeSelf ? this : parent();
+ for (; curr; curr = curr->parent()) {
+ if (curr->requiresFullLayerImageForFilters())
+ return const_cast<RenderLayer*>(curr);
+ }
+
+ return 0;
+}
+
+RenderLayer* RenderLayer::enclosingFilterRepaintLayer() const
+{
+ for (const RenderLayer* curr = this; curr; curr = curr->parent()) {
+ if ((curr != this && curr->requiresFullLayerImageForFilters()) || curr->isComposited() || curr->isRootLayer())
+ return const_cast<RenderLayer*>(curr);
+ }
+ return 0;
+}
+
+void RenderLayer::setFilterBackendNeedsRepaintingInRect(const LayoutRect& rect, bool immediate)
+{
+ if (rect.isEmpty())
+ return;
+
+ LayoutRect rectForRepaint = rect;
+
+#if ENABLE(CSS_FILTERS)
+ if (renderer()->style()->hasFilterOutsets()) {
+ int topOutset;
+ int rightOutset;
+ int bottomOutset;
+ int leftOutset;
+ renderer()->style()->getFilterOutsets(topOutset, rightOutset, bottomOutset, leftOutset);
+ rectForRepaint.move(-leftOutset, -topOutset);
+ rectForRepaint.expand(leftOutset + rightOutset, topOutset + bottomOutset);
+ }
+#endif
+
+ RenderLayerFilterInfo* filterInfo = this->filterInfo();
+ ASSERT(filterInfo);
+ filterInfo->expandDirtySourceRect(rectForRepaint);
+
+#if ENABLE(CSS_SHADERS)
+ ASSERT(filterInfo->renderer());
+ if (filterInfo->renderer()->hasCustomShaderFilter()) {
+ // If we have at least one custom shader, we need to update the whole bounding box of the layer, because the
+ // shader can address any ouput pixel.
+ // Note: This is only for output rect, so there's no need to expand the dirty source rect.
+ rectForRepaint.unite(calculateLayerBounds(this, this));
+ }
+#endif
+
+ RenderLayer* parentLayer = enclosingFilterRepaintLayer();
+ ASSERT(parentLayer);
+ FloatQuad repaintQuad(rectForRepaint);
+ LayoutRect parentLayerRect = renderer()->localToContainerQuad(repaintQuad, parentLayer->renderer()).enclosingBoundingBox();
+
+#if USE(ACCELERATED_COMPOSITING)
+ if (parentLayer->isComposited()) {
+ if (!parentLayer->backing()->paintsIntoWindow()) {
+ parentLayer->setBackingNeedsRepaintInRect(parentLayerRect);
+ return;
+ }
+ // If the painting goes to window, redirect the painting to the parent RenderView.
+ parentLayer = renderer()->view()->layer();
+ parentLayerRect = renderer()->localToContainerQuad(repaintQuad, parentLayer->renderer()).enclosingBoundingBox();
+ }
#endif
+ if (parentLayer->paintsWithFilters()) {
+ parentLayer->setFilterBackendNeedsRepaintingInRect(parentLayerRect, immediate);
+ return;
+ }
+
+ if (parentLayer->isRootLayer()) {
+ RenderView* view = toRenderView(parentLayer->renderer());
+ view->repaintViewRectangle(parentLayerRect, immediate);
+ return;
+ }
+
+ ASSERT_NOT_REACHED();
+}
+#endif
+
RenderLayer* RenderLayer::clippingRoot() const
{
#if USE(ACCELERATED_COMPOSITING)
@@ -952,7 +1077,7 @@ RenderLayer* RenderLayer::clippingRoot() const
ASSERT(current);
if (current->transform()
#if USE(ACCELERATED_COMPOSITING)
- || current->isComposited()
+ || (current->isComposited() && !current->backing()->paintsIntoCompositedAncestor())
#endif
)
return const_cast<RenderLayer*>(current);
@@ -1480,23 +1605,9 @@ void RenderLayer::scrollTo(int x, int y)
view->updateWidgetPositions();
}
-#if USE(ACCELERATED_COMPOSITING)
- if (compositor()->inCompositingMode()) {
- // Our stacking context is guaranteed to contain all of our descendants that may need
- // repositioning, so update compositing layers from there.
- if (RenderLayer* compositingAncestor = stackingContext()->enclosingCompositingLayer()) {
- if (compositor()->compositingConsultsOverlap())
- compositor()->updateCompositingLayers(CompositingUpdateOnScroll, compositingAncestor);
- else {
- bool isUpdateRoot = true;
- compositingAncestor->backing()->updateAfterLayout(RenderLayerBacking::AllDescendants, isUpdateRoot);
- }
- }
- }
-#endif
+ updateCompositingLayersAfterScroll();
RenderBoxModelObject* repaintContainer = renderer()->containerForRepaint();
-
Frame* frame = renderer()->frame();
if (frame) {
// The caret rect needs to be invalidated after scrolling
@@ -1587,9 +1698,12 @@ void RenderLayer::scrollRectToVisible(const LayoutRect& rect, const ScrollAlignm
yOffset = max(0, min(frameView->contentsHeight(), yOffset));
frameView->setScrollPosition(IntPoint(xOffset, yOffset));
- parentLayer = ownerElement->renderer()->enclosingLayer();
- newRect.setX(rect.x() - frameView->scrollX() + frameView->x());
- newRect.setY(rect.y() - frameView->scrollY() + frameView->y());
+ if (frameView->safeToPropagateScrollToParent()) {
+ parentLayer = ownerElement->renderer()->enclosingLayer();
+ newRect.setX(rect.x() - frameView->scrollX() + frameView->x());
+ newRect.setY(rect.y() - frameView->scrollY() + frameView->y());
+ } else
+ parentLayer = 0;
}
} else {
LayoutRect viewRect = frameView->visibleContentRect();
@@ -1617,6 +1731,24 @@ void RenderLayer::scrollRectToVisible(const LayoutRect& rect, const ScrollAlignm
frameView->resumeScheduledEvents();
}
+void RenderLayer::updateCompositingLayersAfterScroll()
+{
+#if USE(ACCELERATED_COMPOSITING)
+ if (compositor()->inCompositingMode()) {
+ // Our stacking context is guaranteed to contain all of our descendants that may need
+ // repositioning, so update compositing layers from there.
+ if (RenderLayer* compositingAncestor = stackingContext()->enclosingCompositingLayer()) {
+ if (compositor()->compositingConsultsOverlap())
+ compositor()->updateCompositingLayers(CompositingUpdateOnScroll, compositingAncestor);
+ else {
+ bool isUpdateRoot = true;
+ compositingAncestor->backing()->updateAfterLayout(RenderLayerBacking::AllDescendants, isUpdateRoot);
+ }
+ }
+ }
+#endif
+}
+
LayoutRect RenderLayer::getRectToExpose(const LayoutRect &visibleRect, const LayoutRect &exposeRect, const ScrollAlignment& alignX, const ScrollAlignment& alignY)
{
// Determine the appropriate X behavior.
@@ -1755,9 +1887,9 @@ void RenderLayer::resize(const PlatformMouseEvent& evt, const LayoutSize& oldOff
styledElement->setInlineStyleProperty(CSSPropertyMarginLeft, String::number(renderer->marginLeft() / zoomFactor) + "px", false);
styledElement->setInlineStyleProperty(CSSPropertyMarginRight, String::number(renderer->marginRight() / zoomFactor) + "px", false);
}
- LayoutUnit baseWidth = renderer->width() - (isBoxSizingBorder ? zeroLayoutUnit : renderer->borderAndPaddingWidth());
+ LayoutUnit baseWidth = renderer->width() - (isBoxSizingBorder ? ZERO_LAYOUT_UNIT : renderer->borderAndPaddingWidth());
baseWidth = baseWidth / zoomFactor;
- styledElement->setInlineStyleProperty(CSSPropertyWidth, String::number(baseWidth + difference.width()) + "px", false);
+ styledElement->setInlineStyleProperty(CSSPropertyWidth, String::number(roundToInt(baseWidth + difference.width())) + "px", false);
}
if (resize != RESIZE_HORIZONTAL && difference.height()) {
@@ -1766,9 +1898,9 @@ void RenderLayer::resize(const PlatformMouseEvent& evt, const LayoutSize& oldOff
styledElement->setInlineStyleProperty(CSSPropertyMarginTop, String::number(renderer->marginTop() / zoomFactor) + "px", false);
styledElement->setInlineStyleProperty(CSSPropertyMarginBottom, String::number(renderer->marginBottom() / zoomFactor) + "px", false);
}
- LayoutUnit baseHeight = renderer->height() - (isBoxSizingBorder ? zeroLayoutUnit : renderer->borderAndPaddingHeight());
+ LayoutUnit baseHeight = renderer->height() - (isBoxSizingBorder ? ZERO_LAYOUT_UNIT : renderer->borderAndPaddingHeight());
baseHeight = baseHeight / zoomFactor;
- styledElement->setInlineStyleProperty(CSSPropertyHeight, String::number(baseHeight + difference.height()) + "px", false);
+ styledElement->setInlineStyleProperty(CSSPropertyHeight, String::number(roundToInt(baseHeight + difference.height())) + "px", false);
}
document->updateLayout();
@@ -1878,7 +2010,7 @@ IntRect RenderLayer::scrollCornerRect() const
bool hasVerticalBar = verticalScrollbar();
bool hasResizer = renderer()->style()->resize() != RESIZE_NONE;
if ((hasHorizontalBar && hasVerticalBar) || (hasResizer && (hasHorizontalBar || hasVerticalBar)))
- return cornerRect(this, pixelSnappedIntRect(renderBox()->borderBoxRect()));
+ return cornerRect(this, renderBox()->pixelSnappedBorderBoxRect());
return IntRect();
}
@@ -1897,7 +2029,7 @@ IntRect RenderLayer::scrollCornerAndResizerRect() const
return IntRect();
IntRect scrollCornerAndResizer = scrollCornerRect();
if (scrollCornerAndResizer.isEmpty())
- scrollCornerAndResizer = resizerCornerRect(this, pixelSnappedIntRect(box->borderBoxRect()));
+ scrollCornerAndResizer = resizerCornerRect(this, box->pixelSnappedBorderBoxRect());
return scrollCornerAndResizer;
}
@@ -1955,7 +2087,7 @@ IntPoint RenderLayer::convertFromContainingViewToScrollbar(const Scrollbar* scro
IntSize RenderLayer::contentsSize() const
{
- return IntSize(const_cast<RenderLayer*>(this)->scrollWidth(), const_cast<RenderLayer*>(this)->scrollHeight());
+ return IntSize(scrollWidth(), scrollHeight());
}
int RenderLayer::visibleHeight() const
@@ -1999,7 +2131,7 @@ LayoutUnit RenderLayer::horizontalScrollbarStart(int minX) const
const RenderBox* box = renderBox();
int x = minX + box->borderLeft();
if (renderer()->style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft())
- x += m_vBar ? m_vBar->width() : resizerCornerRect(this, box->borderBoxRect()).width();
+ x += m_vBar ? m_vBar->width() : resizerCornerRect(this, box->pixelSnappedBorderBoxRect()).width();
return x;
}
@@ -2097,7 +2229,7 @@ bool RenderLayer::scrollsOverflow() const
{
if (!renderer()->isBox())
return false;
-
+
return toRenderBox(renderer())->scrollsOverflow();
}
@@ -2108,7 +2240,7 @@ bool RenderLayer::allowsScrolling() const
void RenderLayer::setHasHorizontalScrollbar(bool hasScrollbar)
{
- if (hasScrollbar == (m_hBar != 0))
+ if (hasScrollbar == hasHorizontalScrollbar())
return;
if (hasScrollbar)
@@ -2131,7 +2263,7 @@ void RenderLayer::setHasHorizontalScrollbar(bool hasScrollbar)
void RenderLayer::setHasVerticalScrollbar(bool hasScrollbar)
{
- if (hasScrollbar == (m_vBar != 0))
+ if (hasScrollbar == hasVerticalScrollbar())
return;
if (hasScrollbar)
@@ -2202,7 +2334,7 @@ void RenderLayer::positionOverflowControls(const IntSize& offsetFromLayer)
if (!box)
return;
- const IntRect borderBox = pixelSnappedIntRect(box->borderBoxRect());
+ const IntRect borderBox = box->pixelSnappedBorderBoxRect();
const IntRect& scrollCorner = scrollCornerRect();
IntRect absBounds(borderBox.location() + offsetFromLayer, borderBox.size());
if (m_vBar)
@@ -2247,18 +2379,20 @@ void RenderLayer::positionOverflowControls(const IntSize& offsetFromLayer)
m_resizer->setFrameRect(resizerCornerRect(this, borderBox));
}
-int RenderLayer::scrollWidth()
+int RenderLayer::scrollWidth() const
{
+ ASSERT(renderBox());
if (m_scrollDimensionsDirty)
- computeScrollDimensions();
- return m_scrollSize.width();
+ const_cast<RenderLayer*>(this)->computeScrollDimensions();
+ return snapSizeToPixel(m_scrollSize.width(), renderBox()->clientLeft());
}
-int RenderLayer::scrollHeight()
+int RenderLayer::scrollHeight() const
{
+ ASSERT(renderBox());
if (m_scrollDimensionsDirty)
- computeScrollDimensions();
- return m_scrollSize.height();
+ const_cast<RenderLayer*>(this)->computeScrollDimensions();
+ return snapSizeToPixel(m_scrollSize.height(), renderBox()->clientTop());
}
LayoutUnit RenderLayer::overflowTop() const
@@ -2293,11 +2427,11 @@ LayoutUnit RenderLayer::overflowRight() const
return overflowRect.maxX();
}
-void RenderLayer::computeScrollDimensions(bool* needHBar, bool* needVBar)
+void RenderLayer::computeScrollDimensions()
{
RenderBox* box = renderBox();
ASSERT(box);
-
+
m_scrollDimensionsDirty = false;
m_scrollOverflow.setWidth(overflowLeft() - box->borderLeft());
@@ -2305,60 +2439,47 @@ void RenderLayer::computeScrollDimensions(bool* needHBar, bool* needVBar)
m_scrollSize.setWidth(overflowRight() - overflowLeft());
m_scrollSize.setHeight(overflowBottom() - overflowTop());
-
+
setScrollOrigin(IntPoint(-m_scrollOverflow.width(), -m_scrollOverflow.height()));
+}
- if (needHBar)
- *needHBar = scrollWidth() > box->pixelSnappedClientWidth();
- if (needVBar)
- *needVBar = scrollHeight() > box->pixelSnappedClientHeight();
+bool RenderLayer::hasHorizontalOverflow() const
+{
+ ASSERT(!m_scrollDimensionsDirty);
+
+ return scrollWidth() > renderBox()->pixelSnappedClientWidth();
}
-void RenderLayer::updateScrollInfoAfterLayout()
+bool RenderLayer::hasVerticalOverflow() const
{
- RenderBox* box = renderBox();
- if (!box)
- return;
+ ASSERT(!m_scrollDimensionsDirty);
- m_scrollDimensionsDirty = true;
- IntSize scrollOffsetOriginal(scrollXOffset(), scrollYOffset());
+ return scrollHeight() > renderBox()->pixelSnappedClientHeight();
+}
- bool horizontalOverflow, verticalOverflow;
- computeScrollDimensions(&horizontalOverflow, &verticalOverflow);
+void RenderLayer::updateScrollbarsAfterLayout()
+{
+ RenderBox* box = renderBox();
+ ASSERT(box);
- if (box->style()->overflowX() != OMARQUEE) {
- // Layout may cause us to be in an invalid scroll position. In this case we need
- // to pull our scroll offsets back to the max (or push them up to the min).
- int newX = max(0, min<int>(scrollXOffset(), scrollWidth() - box->clientWidth()));
- int newY = max(0, min<int>(scrollYOffset(), scrollHeight() - box->clientHeight()));
- if (newX != scrollXOffset() || newY != scrollYOffset())
- scrollToOffset(newX, newY);
- }
+ bool hasHorizontalOverflow = this->hasHorizontalOverflow();
+ bool hasVerticalOverflow = this->hasVerticalOverflow();
- bool haveHorizontalBar = m_hBar;
- bool haveVerticalBar = m_vBar;
-
// overflow:scroll should just enable/disable.
if (m_hBar && renderer()->style()->overflowX() == OSCROLL)
- m_hBar->setEnabled(horizontalOverflow);
+ m_hBar->setEnabled(hasHorizontalOverflow);
if (m_vBar && renderer()->style()->overflowY() == OSCROLL)
- m_vBar->setEnabled(verticalOverflow);
+ m_vBar->setEnabled(hasVerticalOverflow);
- // A dynamic change from a scrolling overflow to overflow:hidden means we need to get rid of any
- // scrollbars that may be present.
- if (renderer()->style()->overflowX() == OHIDDEN && haveHorizontalBar)
- setHasHorizontalScrollbar(false);
- if (renderer()->style()->overflowY() == OHIDDEN && haveVerticalBar)
- setHasVerticalScrollbar(false);
-
// overflow:auto may need to lay out again if scrollbars got added/removed.
- bool scrollbarsChanged = (box->hasAutoHorizontalScrollbar() && haveHorizontalBar != horizontalOverflow) ||
- (box->hasAutoVerticalScrollbar() && haveVerticalBar != verticalOverflow);
- if (scrollbarsChanged) {
+ bool autoHorizontalScrollBarChanged = box->hasAutoHorizontalScrollbar() && (hasHorizontalScrollbar() != hasHorizontalOverflow);
+ bool autoVerticalScrollBarChanged = box->hasAutoVerticalScrollbar() && (hasVerticalScrollbar() != hasVerticalOverflow);
+
+ if (autoHorizontalScrollBarChanged || autoVerticalScrollBarChanged) {
if (box->hasAutoHorizontalScrollbar())
- setHasHorizontalScrollbar(horizontalOverflow);
+ setHasHorizontalScrollbar(hasHorizontalOverflow);
if (box->hasAutoVerticalScrollbar())
- setHasVerticalScrollbar(verticalOverflow);
+ setHasVerticalScrollbar(hasVerticalOverflow);
#if ENABLE(DASHBOARD_SUPPORT)
// Force an update since we know the scrollbars have changed things.
@@ -2372,24 +2493,17 @@ void RenderLayer::updateScrollInfoAfterLayout()
if (!m_inOverflowRelayout) {
// Our proprietary overflow: overlay value doesn't trigger a layout.
m_inOverflowRelayout = true;
- renderer()->setNeedsLayout(true, false);
+ renderer()->setNeedsLayout(true, MarkOnlyThis);
if (renderer()->isRenderBlock()) {
RenderBlock* block = toRenderBlock(renderer());
- block->scrollbarsChanged(box->hasAutoHorizontalScrollbar() && haveHorizontalBar != horizontalOverflow,
- box->hasAutoVerticalScrollbar() && haveVerticalBar != verticalOverflow);
- block->layoutBlock(true); // FIXME: Need to handle positioned floats triggering extra relayouts.
+ block->scrollbarsChanged(autoHorizontalScrollBarChanged, autoVerticalScrollBarChanged);
+ block->layoutBlock(true);
} else
renderer()->layout();
m_inOverflowRelayout = false;
}
}
}
-
- // If overflow:scroll is turned into overflow:auto a bar might still be disabled (Bug 11985).
- if (m_hBar && box->hasAutoHorizontalScrollbar())
- m_hBar->setEnabled(true);
- if (m_vBar && box->hasAutoVerticalScrollbar())
- m_vBar->setEnabled(true);
// Set up the range (and page step/line step).
if (m_hBar) {
@@ -2405,6 +2519,31 @@ void RenderLayer::updateScrollInfoAfterLayout()
m_vBar->setProportion(clientHeight, m_scrollSize.height());
}
+ updateScrollableAreaSet((hasHorizontalOverflow || hasVerticalOverflow) && scrollsOverflow());
+}
+
+void RenderLayer::updateScrollInfoAfterLayout()
+{
+ RenderBox* box = renderBox();
+ if (!box)
+ return;
+
+ m_scrollDimensionsDirty = true;
+ IntSize scrollOffsetOriginal(scrollXOffset(), scrollYOffset());
+
+ computeScrollDimensions();
+
+ if (box->style()->overflowX() != OMARQUEE) {
+ // Layout may cause us to be at an invalid scroll position. In this case we need
+ // to pull our scroll offsets back to the max (or push them up to the min).
+ int newX = max(0, min<int>(scrollXOffset(), scrollWidth() - box->clientWidth()));
+ int newY = max(0, min<int>(scrollYOffset(), scrollHeight() - box->clientHeight()));
+ if (newX != scrollXOffset() || newY != scrollYOffset())
+ scrollToOffset(newX, newY);
+ }
+
+ updateScrollbarsAfterLayout();
+
if (scrollOffsetOriginal != scrollOffset())
scrollToOffsetWithoutAnimation(IntPoint(scrollXOffset(), scrollYOffset()));
}
@@ -2534,7 +2673,7 @@ void RenderLayer::paintResizer(GraphicsContext* context, const IntPoint& paintOf
RenderBox* box = renderBox();
ASSERT(box);
- IntRect absRect = resizerCornerRect(this, pixelSnappedIntRect(box->borderBoxRect()));
+ IntRect absRect = resizerCornerRect(this, box->pixelSnappedBorderBoxRect());
absRect.moveBy(paintOffset);
if (!absRect.intersects(damageRect))
return;
@@ -2589,7 +2728,7 @@ bool RenderLayer::hitTestOverflowControls(HitTestResult& result, const IntPoint&
IntRect resizeControlRect;
if (renderer()->style()->resize() != RESIZE_NONE) {
- resizeControlRect = resizerCornerRect(this, pixelSnappedIntRect(box->borderBoxRect()));
+ resizeControlRect = resizerCornerRect(this, box->pixelSnappedBorderBoxRect());
if (resizeControlRect.contains(localPoint))
return true;
}
@@ -2747,7 +2886,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()->paintingGoesToWindow() && !shouldDoSoftwarePaint(this, paintFlags & PaintLayerPaintingReflection)) {
+ else if (!backing()->paintsIntoWindow() && !backing()->paintsIntoCompositedAncestor() && !shouldDoSoftwarePaint(this, paintFlags & PaintLayerPaintingReflection)) {
// If this RenderLayer should paint into its backing, that will be done via RenderLayerBacking::paintIntoLayer().
return;
}
@@ -2761,6 +2900,10 @@ void RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* context,
if (!renderer()->opacity())
return;
+ // Non self-painting leaf layers don't need to be painted as their renderer() should properly paint itself.
+ if (!isSelfPaintingLayer() && !firstChild())
+ return;
+
if (paintsWithTransparency(paintBehavior))
paintFlags |= PaintLayerHaveTransparency;
@@ -2836,7 +2979,7 @@ void RenderLayer::paintLayerContentsAndReflection(RenderLayer* rootLayer, Graphi
}
void RenderLayer::paintLayerContents(RenderLayer* rootLayer, GraphicsContext* context,
- const LayoutRect& paintDirtyRect, PaintBehavior paintBehavior,
+ const LayoutRect& parentPaintDirtyRect, PaintBehavior paintBehavior,
RenderObject* paintingRoot, RenderRegion* region, OverlapTestRequestMap* overlapTestRequests,
PaintLayerFlags paintFlags)
{
@@ -2852,14 +2995,50 @@ void RenderLayer::paintLayerContents(RenderLayer* rootLayer, GraphicsContext* co
LayoutRect layerBounds;
ClipRect damageRect, clipRectToApply, outlineRect;
LayoutPoint paintOffset;
+ LayoutRect paintDirtyRect = parentPaintDirtyRect;
+
+ bool useClipRect = true;
+ GraphicsContext* transparencyLayerContext = context;
+
+ // Ensure our lists are up-to-date.
+ updateLayerListsIfNeeded();
+
+#if ENABLE(CSS_FILTERS)
+ FilterEffectRendererHelper filterPainter(filterRenderer() && paintsWithFilters());
+ if (filterPainter.haveFilterEffect() && !context->paintingDisabled()) {
+ LayoutPoint rootLayerOffset;
+ convertToLayerCoords(rootLayer, rootLayerOffset);
+ RenderLayerFilterInfo* filterInfo = this->filterInfo();
+ ASSERT(filterInfo);
+ LayoutRect filterRepaintRect = filterInfo->dirtySourceRect();
+ filterRepaintRect.move(rootLayerOffset.x(), rootLayerOffset.y());
+ if (filterPainter.prepareFilterEffect(this, calculateLayerBounds(this, rootLayer, 0), parentPaintDirtyRect, filterRepaintRect)) {
+ // Now we know for sure, that the source image will be updated, so we can revert our tracking repaint rect back to zero.
+ filterInfo->resetDirtySourceRect();
+
+ // Rewire the old context to a memory buffer, so that we can capture the contents of the layer.
+ // NOTE: We saved the old context in the "transparencyLayerContext" local variable, to be able to start a transparency layer
+ // on the original context and avoid duplicating "beginFilterEffect" after each transpareny layer call. Also, note that
+ // beginTransparencyLayers will only create a single lazy transparency layer, even though it is called twice in this method.
+ context = filterPainter.beginFilterEffect(context);
+
+ // Check that we didn't fail to allocate the graphics context for the offscreen buffer.
+ if (filterPainter.hasStartedFilterEffect()) {
+ paintDirtyRect = filterPainter.repaintRect();
+ // If the filter needs the full source image, we need to avoid using the clip rectangles.
+ // Otherwise, if for example this layer has overflow:hidden, a drop shadow will not compute correctly.
+ // Note that we will still apply the clipping on the final rendering of the filter.
+ useClipRect = !filterRenderer()->hasFilterThatMovesPixels();
+ }
+ }
+ }
+#endif
+
if (shouldPaintContent || shouldPaintOutline || isPaintingOverlayScrollbars) {
calculateRects(rootLayer, region, paintDirtyRect, layerBounds, damageRect, clipRectToApply, outlineRect, localPaintFlags & PaintLayerTemporaryClipRects);
paintOffset = toPoint(layerBounds.location() - renderBoxLocation());
}
- // Ensure our lists are up-to-date.
- updateLayerListsIfNeeded();
-
bool forceBlackText = paintBehavior & PaintBehaviorForceBlackText;
bool selectionOnly = paintBehavior & PaintBehaviorSelectionOnly;
@@ -2874,10 +3053,6 @@ void RenderLayer::paintLayerContents(RenderLayer* rootLayer, GraphicsContext* co
if (overlapTestRequests && isSelfPaintingLayer)
performOverlapTests(*overlapTestRequests, rootLayer, this);
-#if ENABLE(CSS_FILTERS)
- FilterEffectRendererHelper filterPainter(paintsWithFilters());
-#endif
-
// We want to paint our layer, but only if we intersect the damage rect.
shouldPaintContent &= intersectsDamageRect(layerBounds, damageRect.rect(), rootLayer);
@@ -2885,23 +3060,22 @@ void RenderLayer::paintLayerContents(RenderLayer* rootLayer, GraphicsContext* co
if (shouldPaintContent && !selectionOnly) {
// Begin transparency layers lazily now that we know we have to paint something.
if (haveTransparency)
- beginTransparencyLayers(context, rootLayer, paintDirtyRect, paintBehavior);
+ beginTransparencyLayers(transparencyLayerContext, rootLayer, paintDirtyRect, paintBehavior);
-#if ENABLE(CSS_FILTERS)
- if (filterPainter.haveFilterEffect() && !context->paintingDisabled())
- context = filterPainter.beginFilterEffect(this, context, paintingExtent(rootLayer, paintDirtyRect, paintBehavior));
-#endif
-
- // Paint our background first, before painting any child layers.
- // Establish the clip used to paint our background.
- clipToRect(rootLayer, context, paintDirtyRect, damageRect, DoNotIncludeSelfForBorderRadius); // Background painting will handle clipping to self.
-
+ if (useClipRect) {
+ // Paint our background first, before painting any child layers.
+ // Establish the clip used to paint our background.
+ clipToRect(rootLayer, context, paintDirtyRect, damageRect, DoNotIncludeSelfForBorderRadius); // Background painting will handle clipping to self.
+ }
+
// Paint the background.
- PaintInfo paintInfo(context, damageRect.rect(), PaintPhaseBlockBackground, false, paintingRootForRenderer, region, 0);
+ PaintInfo paintInfo(context, pixelSnappedIntRect(damageRect.rect()), PaintPhaseBlockBackground, false, paintingRootForRenderer, region, 0);
renderer()->paint(paintInfo, paintOffset);
- // Restore the clip.
- restoreClip(context, paintDirtyRect, damageRect);
+ if (useClipRect) {
+ // Restore the clip.
+ restoreClip(context, paintDirtyRect, damageRect);
+ }
}
// Now walk the sorted list of children with negative z-indices.
@@ -2913,16 +3087,14 @@ void RenderLayer::paintLayerContents(RenderLayer* rootLayer, GraphicsContext* co
if (shouldPaintContent && !clipRectToApply.isEmpty()) {
// Begin transparency layers lazily now that we know we have to paint something.
if (haveTransparency)
- beginTransparencyLayers(context, rootLayer, paintDirtyRect, paintBehavior);
+ beginTransparencyLayers(transparencyLayerContext, rootLayer, paintDirtyRect, paintBehavior);
-#if ENABLE(CSS_FILTERS)
- // If the filter was not started yet, start it now, after the transparency layer was lazily created.
- if (filterPainter.haveFilterEffect() && !filterPainter.hasStartedFilterEffect() && !context->paintingDisabled())
- context = filterPainter.beginFilterEffect(this, context, paintingExtent(rootLayer, paintDirtyRect, paintBehavior));
-#endif
- // Set up the clip used when painting our children.
- clipToRect(rootLayer, context, paintDirtyRect, clipRectToApply);
- PaintInfo paintInfo(context, clipRectToApply.rect(),
+ if (useClipRect) {
+ // Set up the clip used when painting our children.
+ clipToRect(rootLayer, context, paintDirtyRect, clipRectToApply);
+ }
+
+ PaintInfo paintInfo(context, pixelSnappedIntRect(clipRectToApply.rect()),
selectionOnly ? PaintPhaseSelection : PaintPhaseChildBlockBackgrounds,
forceBlackText, paintingRootForRenderer, region, 0);
renderer()->paint(paintInfo, paintOffset);
@@ -2936,13 +3108,15 @@ void RenderLayer::paintLayerContents(RenderLayer* rootLayer, GraphicsContext* co
renderer()->paint(paintInfo, paintOffset);
}
- // Now restore our clip.
- restoreClip(context, paintDirtyRect, clipRectToApply);
+ if (useClipRect) {
+ // Now restore our clip.
+ restoreClip(context, paintDirtyRect, clipRectToApply);
+ }
}
if (shouldPaintOutline && !outlineRect.isEmpty()) {
// Paint our own outline
- PaintInfo paintInfo(context, outlineRect.rect(), PaintPhaseSelfOutline, false, paintingRootForRenderer, region, 0);
+ PaintInfo paintInfo(context, pixelSnappedIntRect(outlineRect.rect()), PaintPhaseSelfOutline, false, paintingRootForRenderer, region, 0);
clipToRect(rootLayer, context, paintDirtyRect, outlineRect, DoNotIncludeSelfForBorderRadius);
renderer()->paint(paintInfo, paintOffset);
restoreClip(context, paintDirtyRect, outlineRect);
@@ -2956,14 +3130,17 @@ void RenderLayer::paintLayerContents(RenderLayer* rootLayer, GraphicsContext* co
}
if ((localPaintFlags & PaintLayerPaintingCompositingMaskPhase) && shouldPaintContent && renderer()->hasMask() && !selectionOnly) {
- clipToRect(rootLayer, context, paintDirtyRect, damageRect, DoNotIncludeSelfForBorderRadius); // Mask painting will handle clipping to self.
+ if (useClipRect)
+ clipToRect(rootLayer, context, paintDirtyRect, damageRect, DoNotIncludeSelfForBorderRadius); // Mask painting will handle clipping to self.
// Paint the mask.
- PaintInfo paintInfo(context, damageRect.rect(), PaintPhaseMask, false, paintingRootForRenderer, region, 0);
+ PaintInfo paintInfo(context, pixelSnappedIntRect(damageRect.rect()), PaintPhaseMask, false, paintingRootForRenderer, region, 0);
renderer()->paint(paintInfo, paintOffset);
- // Restore the clip.
- restoreClip(context, paintDirtyRect, damageRect);
+ if (useClipRect) {
+ // Restore the clip.
+ restoreClip(context, paintDirtyRect, damageRect);
+ }
}
if (isPaintingOverlayScrollbars) {
@@ -2973,10 +3150,17 @@ void RenderLayer::paintLayerContents(RenderLayer* rootLayer, GraphicsContext* co
}
#if ENABLE(CSS_FILTERS)
- if (filterPainter.hasStartedFilterEffect())
+ if (filterPainter.hasStartedFilterEffect()) {
+ // Apply the correct clipping (ie. overflow: hidden).
+ clipToRect(rootLayer, transparencyLayerContext, paintDirtyRect, damageRect);
context = filterPainter.applyFilterEffect();
+ restoreClip(transparencyLayerContext, paintDirtyRect, damageRect);
+ }
#endif
+ // Make sure that we now use the original transparency context.
+ ASSERT(transparencyLayerContext == context);
+
// End our transparency layer
if (haveTransparency && m_usedTransparency && !m_paintingInsideReflection) {
context->endTransparencyLayer();
@@ -2992,7 +3176,11 @@ void RenderLayer::paintList(Vector<RenderLayer*>* list, RenderLayer* rootLayer,
{
if (!list)
return;
-
+
+#if !ASSERT_DISABLED
+ LayerListMutationDetector mutationChecker(this);
+#endif
+
for (size_t i = 0; i < list->size(); ++i) {
RenderLayer* childLayer = list->at(i);
if (!childLayer->isPaginated())
@@ -3132,9 +3320,9 @@ bool RenderLayer::hitTest(const HitTestRequest& request, HitTestResult& result)
{
renderer()->document()->updateLayout();
- IntRect hitTestArea = renderer()->isRenderFlowThread() ? toRenderFlowThread(renderer())->borderBoxRect() : renderer()->view()->documentRect();
+ LayoutRect hitTestArea = renderer()->isRenderFlowThread() ? toRenderFlowThread(renderer())->borderBoxRect() : renderer()->view()->documentRect();
if (!request.ignoreClipping())
- hitTestArea.intersect(pixelSnappedIntRect(frameVisibleRect(renderer())));
+ hitTestArea.intersect(frameVisibleRect(renderer()));
RenderLayer* insideLayer = hitTestLayer(this, 0, request, result, hitTestArea, result.point(), false);
if (!insideLayer) {
@@ -3377,7 +3565,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());
+ HitTestResult tempResult(result.point(), result.topPadding(), result.rightPadding(), result.bottomPadding(), result.leftPadding(), result.shadowContentFilterPolicy());
if (hitTestContents(request, tempResult, layerBounds, hitTestPoint, HitTestDescendants) &&
isHitCandidate(this, false, zOffsetForContentsPtr, unflattenedTransformState.get())) {
if (result.isRectBasedTest())
@@ -3406,7 +3594,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());
+ HitTestResult tempResult(result.point(), result.topPadding(), result.rightPadding(), result.bottomPadding(), result.leftPadding(), result.shadowContentFilterPolicy());
if (hitTestContents(request, tempResult, layerBounds, hitTestPoint, HitTestSelf) &&
isHitCandidate(this, false, zOffsetForContentsPtr, unflattenedTransformState.get())) {
if (result.isRectBasedTest())
@@ -3424,7 +3612,7 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* cont
bool RenderLayer::hitTestContents(const HitTestRequest& request, HitTestResult& result, const LayoutRect& layerBounds, const LayoutPoint& hitTestPoint, HitTestFilter hitTestFilter) const
{
if (!renderer()->hitTest(request, result, hitTestPoint,
- toPoint(layerBounds.location() - renderBoxLocation()),
+ toLayoutPoint(layerBounds.location() - renderBoxLocation()),
hitTestFilter)) {
// It's wrong to set innerNode, but then claim that you didn't hit anything, unless it is
// a rect-based test.
@@ -3462,7 +3650,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());
+ HitTestResult tempResult(result.point(), result.topPadding(), result.rightPadding(), result.bottomPadding(), result.leftPadding(), result.shadowContentFilterPolicy());
if (childLayer->isPaginated())
hitLayer = hitTestPaginatedChildLayer(childLayer, rootLayer, request, tempResult, hitTestRect, hitTestPoint, transformState, zOffsetForDescendants);
else
@@ -3722,8 +3910,11 @@ ClipRect RenderLayer::backgroundClipRect(const RenderLayer* rootLayer, RenderReg
ClipRect backgroundClipRect = backgroundClipRectForPosition(parentRects, renderer()->style()->position());
RenderView* view = renderer()->view();
ASSERT(view);
- if (parentRects.fixed() && rootLayer->renderer() == view)
+
+ // Note: infinite clipRects should not be scrolled here, otherwise they will accidentally no longer be considered infinite.
+ if (parentRects.fixed() && rootLayer->renderer() == view && backgroundClipRect != PaintInfo::infiniteRect())
backgroundClipRect.move(view->frameView()->scrollXForFixedPosition(), view->frameView()->scrollYForFixedPosition());
+
return backgroundClipRect;
}
@@ -3804,6 +3995,26 @@ LayoutRect RenderLayer::selfClipRect() const
return clippingRootLayer->renderer()->localToAbsoluteQuad(FloatQuad(backgroundRect.rect())).enclosingBoundingBox();
}
+LayoutRect RenderLayer::localClipRect() const
+{
+ // FIXME: border-radius not accounted for.
+ // FIXME: Regions not accounted for.
+ RenderLayer* clippingRootLayer = clippingRoot();
+ LayoutRect layerBounds;
+ ClipRect backgroundRect, foregroundRect, outlineRect;
+ calculateRects(clippingRootLayer, 0, PaintInfo::infiniteRect(), layerBounds, backgroundRect, foregroundRect, outlineRect);
+
+ LayoutRect clipRect = backgroundRect.rect();
+ if (clipRect == PaintInfo::infiniteRect())
+ return clipRect;
+
+ LayoutPoint clippingRootOffset;
+ convertToLayerCoords(clippingRootLayer, clippingRootOffset);
+ clipRect.moveBy(-clippingRootOffset);
+
+ return clipRect;
+}
+
void RenderLayer::addBlockSelectionGapsBounds(const LayoutRect& bounds)
{
m_blockSelectionGapsBounds.unite(bounds);
@@ -3919,9 +4130,116 @@ LayoutRect RenderLayer::boundingBox(const RenderLayer* ancestorLayer) const
return result;
}
-LayoutRect RenderLayer::absoluteBoundingBox() const
+IntRect RenderLayer::absoluteBoundingBox() const
{
- return boundingBox(root());
+ return pixelSnappedIntRect(boundingBox(root()));
+}
+
+IntRect RenderLayer::calculateLayerBounds(const RenderLayer* layer, const RenderLayer* ancestorLayer, CalculateLayerBoundsFlags flags)
+{
+ if (!layer->isSelfPaintingLayer())
+ return IntRect();
+
+ LayoutRect boundingBoxRect = layer->localBoundingBox();
+ 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
+ // to the code in RenderBox::paintRootBoxFillLayers().
+ if (FrameView* frameView = layer->renderer()->view()->frameView()) {
+ LayoutUnit contentsWidth = frameView->contentsWidth();
+ LayoutUnit contentsHeight = frameView->contentsHeight();
+
+ boundingBoxRect.setWidth(max(boundingBoxRect.width(), contentsWidth - boundingBoxRect.x()));
+ boundingBoxRect.setHeight(max(boundingBoxRect.height(), contentsHeight - boundingBoxRect.y()));
+ }
+ }
+
+ LayoutRect unionBounds = boundingBoxRect;
+
+ if (flags & UseLocalClipRectIfPossible) {
+ LayoutRect localClipRect = layer->localClipRect();
+ if (localClipRect != PaintInfo::infiniteRect()) {
+ LayoutPoint ancestorRelOffset;
+ layer->convertToLayerCoords(ancestorLayer, ancestorRelOffset);
+ localClipRect.moveBy(ancestorRelOffset);
+ return pixelSnappedIntRect(localClipRect);
+ }
+ }
+
+ const_cast<RenderLayer*>(layer)->updateLayerListsIfNeeded();
+
+ if (RenderLayer* reflection = layer->reflectionLayer()) {
+ if (!reflection->isComposited()) {
+ IntRect childUnionBounds = calculateLayerBounds(reflection, layer);
+ unionBounds.unite(childUnionBounds);
+ }
+ }
+
+ ASSERT(layer->isStackingContext() || (!layer->posZOrderList() || !layer->posZOrderList()->size()));
+
+#if !ASSERT_DISABLED
+ LayerListMutationDetector mutationChecker(const_cast<RenderLayer*>(layer));
+#endif
+
+ if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) {
+ size_t listSize = negZOrderList->size();
+ for (size_t i = 0; i < listSize; ++i) {
+ RenderLayer* curLayer = negZOrderList->at(i);
+ if (!curLayer->isComposited()) {
+ IntRect childUnionBounds = calculateLayerBounds(curLayer, layer);
+ unionBounds.unite(childUnionBounds);
+ }
+ }
+ }
+
+ if (Vector<RenderLayer*>* posZOrderList = layer->posZOrderList()) {
+ size_t listSize = posZOrderList->size();
+ for (size_t i = 0; i < listSize; ++i) {
+ RenderLayer* curLayer = posZOrderList->at(i);
+ if (!curLayer->isComposited()) {
+ IntRect childUnionBounds = calculateLayerBounds(curLayer, layer);
+ unionBounds.unite(childUnionBounds);
+ }
+ }
+ }
+
+ if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) {
+ size_t listSize = normalFlowList->size();
+ for (size_t i = 0; i < listSize; ++i) {
+ RenderLayer* curLayer = normalFlowList->at(i);
+ if (!curLayer->isComposited()) {
+ IntRect curAbsBounds = calculateLayerBounds(curLayer, layer);
+ unionBounds.unite(curAbsBounds);
+ }
+ }
+ }
+
+#if ENABLE(CSS_FILTERS)
+ // FIXME: We can optimize the size of the composited layers, by not enlarging
+ // filtered areas with the outsets if we know that the filter is going to render in hardware.
+ // https://bugs.webkit.org/show_bug.cgi?id=81239
+ if ((flags & IncludeLayerFilterOutsets) && layer->renderer()->style()->hasFilterOutsets()) {
+ int topOutset;
+ int rightOutset;
+ int bottomOutset;
+ int leftOutset;
+ layer->renderer()->style()->getFilterOutsets(topOutset, rightOutset, bottomOutset, leftOutset);
+ unionBounds.move(-leftOutset, -topOutset);
+ unionBounds.expand(leftOutset + rightOutset, topOutset + bottomOutset);
+ }
+#endif
+
+ if ((flags & IncludeSelfTransform) && layer->paintsWithTransform(PaintBehaviorNormal)) {
+ TransformationMatrix* affineTrans = layer->transform();
+ boundingBoxRect = affineTrans->mapRect(boundingBoxRect);
+ unionBounds = affineTrans->mapRect(unionBounds);
+ }
+
+ LayoutPoint ancestorRelOffset;
+ layer->convertToLayerCoords(ancestorLayer, ancestorRelOffset);
+ unionBounds.moveBy(ancestorRelOffset);
+
+ return pixelSnappedIntRect(unionBounds);
}
void RenderLayer::clearClipRectsIncludingDescendants()
@@ -3960,16 +4278,18 @@ RenderLayerBacking* RenderLayer::ensureBacking()
return m_backing.get();
}
-void RenderLayer::clearBacking()
+void RenderLayer::clearBacking(bool layerBeingDestroyed)
{
if (m_backing && !renderer()->documentBeingDestroyed())
compositor()->layerBecameNonComposited(this);
m_backing.clear();
#if ENABLE(CSS_FILTERS)
- updateOrRemoveFilterEffect();
+ if (!layerBeingDestroyed)
+ updateOrRemoveFilterEffect();
+#else
+ UNUSED_PARAM(layerBeingDestroyed);
#endif
-
}
bool RenderLayer::hasCompositedMask() const
@@ -3996,7 +4316,7 @@ GraphicsLayer* RenderLayer::layerForScrollCorner() const
bool RenderLayer::paintsWithTransform(PaintBehavior paintBehavior) const
{
#if USE(ACCELERATED_COMPOSITING)
- bool paintsToWindow = !isComposited() || backing()->paintingGoesToWindow();
+ bool paintsToWindow = !isComposited() || backing()->paintsIntoWindow();
#else
bool paintsToWindow = true;
#endif
@@ -4141,6 +4461,10 @@ static inline bool compareZIndex(RenderLayer* first, RenderLayer* second)
void RenderLayer::dirtyZOrderLists()
{
+ ASSERT(m_layerListMutationAllowed);
+ // We cannot assume that we are called on a stacking context as it
+ // is called when we just got demoted from being a stacking context.
+
if (m_posZOrderList)
m_posZOrderList->clear();
if (m_negZOrderList)
@@ -4162,6 +4486,8 @@ void RenderLayer::dirtyStackingContextZOrderLists()
void RenderLayer::dirtyNormalFlowList()
{
+ ASSERT(m_layerListMutationAllowed);
+
if (m_normalFlowList)
m_normalFlowList->clear();
m_normalFlowListDirty = true;
@@ -4172,8 +4498,11 @@ void RenderLayer::dirtyNormalFlowList()
#endif
}
-void RenderLayer::updateZOrderListsSlowCase()
+void RenderLayer::rebuildZOrderLists()
{
+ ASSERT(m_layerListMutationAllowed);
+ ASSERT(isDirtyStackingContext());
+
#if USE(ACCELERATED_COMPOSITING)
bool includeHiddenLayers = compositor()->inCompositingMode();
#else
@@ -4197,7 +4526,9 @@ void RenderLayer::updateNormalFlowList()
{
if (!m_normalFlowListDirty)
return;
-
+
+ ASSERT(m_layerListMutationAllowed);
+
for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
// Ignore non-overflow layers and reflections.
if (child->isNormalFlowOnly() && (!m_reflection || reflectionLayer() != child)) {
@@ -4243,13 +4574,18 @@ void RenderLayer::updateLayerListsIfNeeded()
{
updateZOrderLists();
updateNormalFlowList();
+
+ if (RenderLayer* reflectionLayer = this->reflectionLayer()) {
+ reflectionLayer->updateZOrderLists();
+ reflectionLayer->updateNormalFlowList();
+ }
}
void RenderLayer::updateCompositingAndLayerListsIfNeeded()
{
#if USE(ACCELERATED_COMPOSITING)
if (compositor()->inCompositingMode()) {
- if ((isStackingContext() && m_zOrderListsDirty) || m_normalFlowListDirty)
+ if (isDirtyStackingContext() || m_normalFlowListDirty)
compositor()->updateCompositingLayers(CompositingUpdateOnHitTest, this);
return;
}
@@ -4268,7 +4604,7 @@ void RenderLayer::repaintIncludingDescendants()
void RenderLayer::setBackingNeedsRepaint()
{
ASSERT(isComposited());
- if (backing()->paintingGoesToWindow()) {
+ if (backing()->paintsIntoWindow()) {
// If we're trying to repaint the placeholder document layer, propagate the
// repaint to the native view system.
RenderView* view = renderer()->view();
@@ -4283,7 +4619,7 @@ void RenderLayer::setBackingNeedsRepaintInRect(const LayoutRect& r)
// https://bugs.webkit.org/show_bug.cgi?id=61159 describes an unreproducible crash here,
// so assert but check that the layer is composited.
ASSERT(isComposited());
- if (!isComposited() || backing()->paintingGoesToWindow()) {
+ if (!isComposited() || backing()->paintsIntoWindow()) {
// If we're trying to repaint the placeholder document layer, propagate the
// repaint to the native view system.
LayoutRect absRect(r);
@@ -4343,6 +4679,40 @@ bool RenderLayer::isSelfPaintingLayer() const
|| renderer()->isRenderIFrame();
}
+static bool overflowCanHaveAScrollbar(EOverflow overflow)
+{
+ return overflow == OAUTO || overflow == OSCROLL || overflow == OOVERLAY;
+}
+
+void RenderLayer::updateScrollbarsAfterStyleChange(const RenderStyle* oldStyle)
+{
+ // Overflow are a box concept.
+ if (!renderBox())
+ return;
+
+ EOverflow overflowX = renderBox()->style()->overflowX();
+ EOverflow overflowY = renderBox()->style()->overflowY();
+ if (hasHorizontalScrollbar() && !overflowCanHaveAScrollbar(overflowX))
+ setHasHorizontalScrollbar(false);
+ if (hasVerticalScrollbar() && !overflowCanHaveAScrollbar(overflowY))
+ setHasVerticalScrollbar(false);
+
+ // With overflow: scroll, scrollbars are always visible but may be disabled.
+ // When switching to another value, we need to re-enable them (see bug 11985).
+ if (hasHorizontalScrollbar() && oldStyle->overflowX() == OSCROLL && overflowX != OSCROLL) {
+ ASSERT(overflowCanHaveAScrollbar(overflowX));
+ m_hBar->setEnabled(true);
+ }
+
+ if (hasVerticalScrollbar() && oldStyle->overflowY() == OSCROLL && overflowY != OSCROLL) {
+ ASSERT(overflowCanHaveAScrollbar(overflowY));
+ m_vBar->setEnabled(true);
+ }
+
+ if (!m_scrollDimensionsDirty)
+ updateScrollableAreaSet((hasHorizontalOverflow() || hasVerticalOverflow()) && scrollsOverflow());
+}
+
void RenderLayer::styleChanged(StyleDifference, const RenderStyle* oldStyle)
{
bool isNormalFlowOnly = shouldBeNormalFlowOnly();
@@ -4364,6 +4734,8 @@ void RenderLayer::styleChanged(StyleDifference, const RenderStyle* oldStyle)
m_marquee = 0;
}
+ updateScrollbarsAfterStyleChange(oldStyle);
+
if (!hasReflection() && m_reflection)
removeReflection();
else if (hasReflection()) {
@@ -4372,19 +4744,6 @@ void RenderLayer::styleChanged(StyleDifference, const RenderStyle* oldStyle)
updateReflectionStyle();
}
-#if ENABLE(CSS_FILTERS)
- updateOrRemoveFilterEffect();
-#endif
-
- if (Frame* frame = renderer()->frame()) {
- if (FrameView* frameView = frame->view()) {
- if (scrollsOverflow())
- frameView->addScrollableArea(this);
- else
- frameView->removeScrollableArea(this);
- }
- }
-
// FIXME: Need to detect a swap from custom to native scrollbars (and vice versa).
if (m_hBar)
m_hBar->styleChanged();
@@ -4394,11 +4753,18 @@ void RenderLayer::styleChanged(StyleDifference, const RenderStyle* oldStyle)
updateScrollCornerStyle();
updateResizerStyle();
+#if ENABLE(CSS_FILTERS)
+ bool backingDidCompositeLayers = isComposited() && backing()->canCompositeFilters();
+#endif
+
#if USE(ACCELERATED_COMPOSITING)
+ updateVisibilityStatus();
updateTransform();
if (compositor()->updateLayerCompositingState(this))
compositor()->setCompositingLayersNeedRebuild();
+ else if (oldStyle && (oldStyle->clip() != renderer()->style()->clip() || oldStyle->hasClip() != renderer()->style()->hasClip()))
+ compositor()->setCompositingLayersNeedRebuild();
else if (m_backing)
m_backing->updateGraphicsLayerGeometry();
else if (oldStyle && oldStyle->overflowX() != renderer()->style()->overflowX()) {
@@ -4406,6 +4772,35 @@ void RenderLayer::styleChanged(StyleDifference, const RenderStyle* oldStyle)
compositor()->setCompositingLayersNeedRebuild();
}
#endif
+
+#if ENABLE(CSS_FILTERS)
+ updateOrRemoveFilterEffect();
+ if (isComposited() && backingDidCompositeLayers && !backing()->canCompositeFilters()) {
+ // The filters used to be drawn by platform code, but now the platform cannot draw them anymore.
+ // Fallback to drawing them in software.
+ setBackingNeedsRepaint();
+ }
+#endif
+}
+
+void RenderLayer::updateScrollableAreaSet(bool hasOverflow)
+{
+ Frame* frame = renderer()->frame();
+ if (!frame)
+ return;
+
+ FrameView* frameView = frame->view();
+ if (!frameView)
+ return;
+
+ bool isVisibleToHitTest = renderer()->visibleToHitTesting();
+ if (HTMLFrameOwnerElement* owner = frame->ownerElement())
+ isVisibleToHitTest &= owner->renderer() && owner->renderer()->visibleToHitTesting();
+
+ if (hasOverflow && isVisibleToHitTest)
+ frameView->addScrollableArea(this);
+ else
+ frameView->removeScrollableArea(this);
}
void RenderLayer::updateScrollCornerStyle()
@@ -4502,17 +4897,38 @@ void RenderLayer::updateReflectionStyle()
#if ENABLE(CSS_FILTERS)
void RenderLayer::updateOrRemoveFilterEffect()
{
- if (paintsWithFilters()) {
- if (!m_filter) {
- m_filter = FilterEffectRenderer::create(this);
- RenderingMode renderingMode = renderer()->frame()->page()->settings()->acceleratedFiltersEnabled() ? Accelerated : Unaccelerated;
- m_filter->setRenderingMode(renderingMode);
- }
+ if (!hasFilter()) {
+ removeFilterInfoIfNeeded();
+ return;
+ }
- m_filter->build(renderer()->document(), renderer()->style()->filter());
- } else {
- m_filter = 0;
+#if ENABLE(CSS_SHADERS)
+ if (renderer()->style()->filter().hasCustomFilter())
+ ensureFilterInfo()->updateCustomFilterClients(renderer()->style()->filter());
+ else if (hasFilterInfo())
+ filterInfo()->removeCustomFilterClients();
+#endif
+
+ if (!paintsWithFilters()) {
+ // Don't delete the whole filter info here, because we might use it
+ // for loading CSS shader files.
+ if (RenderLayerFilterInfo* filterInfo = this->filterInfo())
+ filterInfo->setRenderer(0);
+ return;
}
+
+ RenderLayerFilterInfo* filterInfo = ensureFilterInfo();
+ if (!filterInfo->renderer()) {
+ RefPtr<FilterEffectRenderer> filterRenderer = FilterEffectRenderer::create();
+ RenderingMode renderingMode = renderer()->frame()->page()->settings()->acceleratedFiltersEnabled() ? Accelerated : Unaccelerated;
+ filterRenderer->setRenderingMode(renderingMode);
+ filterInfo->setRenderer(filterRenderer.release());
+ }
+
+ // If the filter fails to build, remove it from the layer. It will still attempt to
+ // go through regular processing (e.g. compositing), but never apply anything.
+ if (!filterInfo->renderer()->build(renderer()->document(), renderer()->style()->filter()))
+ filterInfo->setRenderer(0);
}
void RenderLayer::filterNeedsRepaint()
diff --git a/Source/WebCore/rendering/RenderLayer.h b/Source/WebCore/rendering/RenderLayer.h
index 4f5ec91f1..95c0f3933 100644
--- a/Source/WebCore/rendering/RenderLayer.h
+++ b/Source/WebCore/rendering/RenderLayer.h
@@ -44,15 +44,15 @@
#ifndef RenderLayer_h
#define RenderLayer_h
-#if ENABLE(CSS_FILTERS)
-#include "FilterEffectObserver.h"
-#endif
#include "PaintInfo.h"
#include "RenderBox.h"
-#include "ScrollBehavior.h"
#include "ScrollableArea.h"
#include <wtf/OwnPtr.h>
+#if ENABLE(CSS_FILTERS)
+#include "RenderLayerFilterInfo.h"
+#endif
+
namespace WebCore {
#if ENABLE(CSS_FILTERS)
@@ -100,6 +100,8 @@ public:
void setHasRadius(bool hasRadius) { m_hasRadius = hasRadius; }
bool operator==(const ClipRect& other) const { return rect() == other.rect() && hasRadius() == other.hasRadius(); }
+ bool operator!=(const ClipRect& other) const { return rect() != other.rect() || hasRadius() != other.hasRadius(); }
+ bool operator!=(const LayoutRect& otherRect) const { return rect() != otherRect; }
void intersect(const LayoutRect& other) { m_rect.intersect(other); }
void intersect(const ClipRect& other)
@@ -211,11 +213,7 @@ private:
bool m_fixed : 1;
};
-class RenderLayer : public ScrollableArea
-#if ENABLE(CSS_FILTERS)
- , public FilterEffectObserver
-#endif
-{
+class RenderLayer : public ScrollableArea {
public:
friend class RenderReplica;
@@ -280,8 +278,8 @@ public:
LayoutRect rect() const { return LayoutRect(location(), size()); }
- int scrollWidth();
- int scrollHeight();
+ int scrollWidth() const;
+ int scrollHeight() const;
void panScrollFromPoint(const LayoutPoint&);
@@ -301,7 +299,7 @@ public:
void scrollToXOffset(int x, ScrollOffsetClamping clamp = ScrollOffsetUnclamped) { scrollToOffset(x, scrollYOffset(), clamp); }
void scrollToYOffset(int y, ScrollOffsetClamping clamp = ScrollOffsetUnclamped) { scrollToOffset(scrollXOffset(), y, clamp); }
- void scrollRectToVisible(const LayoutRect&, const ScrollAlignment& alignX = ScrollAlignment::alignCenterIfNeeded, const ScrollAlignment& alignY = ScrollAlignment::alignCenterIfNeeded);
+ void scrollRectToVisible(const LayoutRect&, const ScrollAlignment& alignX, const ScrollAlignment& alignY);
LayoutRect getRectToExpose(const LayoutRect& visibleRect, const LayoutRect& exposeRect, const ScrollAlignment& alignX, const ScrollAlignment& alignY);
@@ -314,6 +312,9 @@ public:
PassRefPtr<Scrollbar> createScrollbar(ScrollbarOrientation);
void destroyScrollbar(ScrollbarOrientation);
+ bool hasHorizontalScrollbar() const { return horizontalScrollbar(); }
+ bool hasVerticalScrollbar() const { return verticalScrollbar(); }
+
// ScrollableArea overrides
virtual Scrollbar* horizontalScrollbar() const { return m_hBar.get(); }
virtual Scrollbar* verticalScrollbar() const { return m_vBar.get(); }
@@ -347,13 +348,9 @@ public:
// Notification from the renderer that its content changed (e.g. current frame of image changed).
// Allows updates of layer content without repainting.
- enum ContentChangeType { ImageChanged, MaskImageChanged, CanvasChanged, VideoChanged, FullScreenChanged };
void contentChanged(ContentChangeType);
#endif
- // Returns true if the accelerated compositing is enabled
- bool hasAcceleratedCompositing() const;
-
bool canRender3DTransforms() const;
void updateLayerPosition();
@@ -389,13 +386,26 @@ public:
void dirtyZOrderLists();
void dirtyStackingContextZOrderLists();
- void updateZOrderLists();
- Vector<RenderLayer*>* posZOrderList() const { return m_posZOrderList; }
- Vector<RenderLayer*>* negZOrderList() const { return m_negZOrderList; }
+
+ Vector<RenderLayer*>* posZOrderList() const
+ {
+ ASSERT(!m_zOrderListsDirty);
+ ASSERT(isStackingContext() || !m_posZOrderList);
+ return m_posZOrderList;
+ }
+
+ Vector<RenderLayer*>* negZOrderList() const
+ {
+ ASSERT(!m_zOrderListsDirty);
+ ASSERT(isStackingContext() || !m_negZOrderList);
+ return m_negZOrderList;
+ }
void dirtyNormalFlowList();
- void updateNormalFlowList();
- Vector<RenderLayer*>* normalFlowList() const { return m_normalFlowList; }
+ Vector<RenderLayer*>* normalFlowList() const { ASSERT(!m_normalFlowListDirty); return m_normalFlowList; }
+
+ // Update our normal and z-index lists.
+ void updateLayerListsIfNeeded();
// FIXME: We should ASSERT(!m_visibleContentStatusDirty) here, but see https://bugs.webkit.org/show_bug.cgi?id=71044
// ditto for hasVisibleDescendant(), see https://bugs.webkit.org/show_bug.cgi?id=71277
@@ -417,10 +427,17 @@ public:
#if USE(ACCELERATED_COMPOSITING)
// Enclosing compositing layer; if includeSelf is true, may return this.
RenderLayer* enclosingCompositingLayer(bool includeSelf = true) const;
+ RenderLayer* enclosingCompositingLayerForRepaint(bool includeSelf = true) const;
// Ancestor compositing layer, excluding this.
RenderLayer* ancestorCompositingLayer() const { return enclosingCompositingLayer(false); }
#endif
+#if ENABLE(CSS_FILTERS)
+ RenderLayer* enclosingFilterLayer(bool includeSelf = true) const;
+ RenderLayer* enclosingFilterRepaintLayer() const;
+ void setFilterBackendNeedsRepaintingInRect(const LayoutRect&, bool immediate);
+#endif
+
void convertToPixelSnappedLayerCoords(const RenderLayer* ancestorLayer, IntPoint& location) const;
void convertToPixelSnappedLayerCoords(const RenderLayer* ancestorLayer, IntRect&) const;
void convertToLayerCoords(const RenderLayer* ancestorLayer, LayoutPoint& location) const;
@@ -468,6 +485,7 @@ public:
LayoutRect childrenClipRect() const; // Returns the foreground clip rect of the layer in the document's coordinate space.
LayoutRect selfClipRect() const; // Returns the background clip rect of the layer in the document's coordinate space.
+ LayoutRect localClipRect() const; // Returns the background clip rect of the layer in the local coordinate space.
bool intersectsDamageRect(const LayoutRect& layerBounds, const LayoutRect& damageRect, const RenderLayer* rootLayer) const;
@@ -475,9 +493,18 @@ public:
LayoutRect boundingBox(const RenderLayer* rootLayer) const;
// Bounding box in the coordinates of this layer.
LayoutRect localBoundingBox() const;
- // Bounding box relative to the root.
- LayoutRect absoluteBoundingBox() const;
-
+ // Pixel snapped bounding box relative to the root.
+ IntRect absoluteBoundingBox() const;
+
+ enum CalculateLayerBoundsFlag {
+ IncludeSelfTransform = 1 << 0,
+ UseLocalClipRectIfPossible = 1 << 1,
+ IncludeLayerFilterOutsets = 1 << 2,
+ DefaultCalculateLayerBoundsFlags = IncludeSelfTransform | UseLocalClipRectIfPossible | IncludeLayerFilterOutsets
+ };
+ typedef unsigned CalculateLayerBoundsFlags;
+ static IntRect calculateLayerBounds(const RenderLayer*, const RenderLayer* ancestorLayer, CalculateLayerBoundsFlags = DefaultCalculateLayerBoundsFlags);
+
void updateHoverActiveState(const HitTestRequest&, HitTestResult&);
// WARNING: This method returns the offset for the parent as this is what updateLayerPositions expects.
@@ -539,7 +566,7 @@ public:
bool hasCompositedMask() const;
RenderLayerBacking* backing() const { return m_backing.get(); }
RenderLayerBacking* ensureBacking();
- void clearBacking();
+ void clearBacking(bool layerBeingDestroyed = false);
virtual GraphicsLayer* layerForHorizontalScrollbar() const;
virtual GraphicsLayer* layerForVerticalScrollbar() const;
virtual GraphicsLayer* layerForScrollCorner() const;
@@ -560,11 +587,38 @@ public:
#if ENABLE(CSS_FILTERS)
bool paintsWithFilters() const;
- FilterEffectRenderer* filter() const { return m_filter.get(); }
+ bool requiresFullLayerImageForFilters() const;
+ FilterEffectRenderer* filterRenderer() const
+ {
+ RenderLayerFilterInfo* filterInfo = this->filterInfo();
+ return filterInfo ? filterInfo->renderer() : 0;
+ }
+
+ RenderLayerFilterInfo* filterInfo() const { return hasFilterInfo() ? RenderLayerFilterInfo::filterInfoForRenderLayer(this) : 0; }
+ RenderLayerFilterInfo* ensureFilterInfo() { return RenderLayerFilterInfo::createFilterInfoForRenderLayerIfNeeded(this); }
+ void removeFilterInfoIfNeeded()
+ {
+ if (hasFilterInfo())
+ RenderLayerFilterInfo::removeFilterInfoForRenderLayer(this);
+ }
+
+ bool hasFilterInfo() const { return m_hasFilterInfo; }
+ void setHasFilterInfo(bool hasFilterInfo) { m_hasFilterInfo = hasFilterInfo; }
+#endif
+
+#if !ASSERT_DISABLED
+ bool layerListMutationAllowed() const { return m_layerListMutationAllowed; }
+ void setLayerListMutationAllowed(bool flag) { m_layerListMutationAllowed = flag; }
#endif
private:
- void updateZOrderListsSlowCase();
+ void updateZOrderLists();
+ void rebuildZOrderLists();
+ void clearZOrderLists();
+
+ void updateNormalFlowList();
+
+ bool isDirtyStackingContext() const { return m_zOrderListsDirty && isStackingContext(); }
void computeRepaintRects(LayoutPoint* offsetFromRoot = 0);
void clearRepaintRects();
@@ -575,6 +629,9 @@ private:
bool shouldRepaintAfterLayout() const;
+ void updateScrollbarsAfterStyleChange(const RenderStyle* oldStyle);
+ void updateScrollbarsAfterLayout();
+
friend IntSize RenderBox::scrolledContentOffset() const;
IntSize scrolledContentOffset() const { return scrollOffset() + m_scrollOverflow; }
@@ -593,7 +650,6 @@ private:
void collectLayers(bool includeHiddenLayers, Vector<RenderLayer*>*&, Vector<RenderLayer*>*&);
- void updateLayerListsIfNeeded();
void updateCompositingAndLayerListsIfNeeded();
void paintLayer(RenderLayer* rootLayer, GraphicsContext*, const LayoutRect& paintDirtyRect,
@@ -639,7 +695,9 @@ private:
bool hitTestContents(const HitTestRequest&, HitTestResult&, const LayoutRect& layerBounds, const LayoutPoint& hitTestPoint, HitTestFilter) const;
- void computeScrollDimensions(bool* needHBar = 0, bool* needVBar = 0);
+ void computeScrollDimensions();
+ bool hasHorizontalOverflow() const;
+ bool hasVerticalOverflow() const;
bool shouldBeNormalFlowOnly() const;
@@ -675,9 +733,12 @@ private:
// NOTE: This should only be called by the overriden setScrollOffset from ScrollableArea.
void scrollTo(int, int);
+ void updateCompositingLayersAfterScroll();
IntSize scrollbarOffset(const Scrollbar*) const;
+ void updateScrollableAreaSet(bool hasOverflow);
+
void childVisibilityChanged(bool newVisibility);
void dirtyVisibleDescendantStatus();
void updateVisibilityStatus();
@@ -788,12 +849,18 @@ protected:
#endif
bool m_containsDirtyOverlayScrollbars : 1;
-
+#if !ASSERT_DISABLED
+ bool m_layerListMutationAllowed : 1;
+#endif
// This is an optimization added for <table>.
// Currently cells do not need to update their repaint rectangles when scrolling. This also
// saves a lot of time when scrolling on a table.
bool m_canSkipRepaintRectsUpdateOnScroll : 1;
+#if ENABLE(CSS_FILTERS)
+ bool m_hasFilterInfo : 1;
+#endif
+
RenderBoxModelObject* m_renderer;
RenderLayer* m_parent;
@@ -854,10 +921,6 @@ protected:
// May ultimately be extended to many replicas (with their own paint order).
RenderReplica* m_reflection;
-
-#if ENABLE(CSS_FILTERS)
- RefPtr<FilterEffectRenderer> m_filter;
-#endif
// Renderers to hold our custom scroll corner and resizer.
RenderScrollbarPart* m_scrollCorner;
@@ -871,13 +934,55 @@ private:
#endif
};
+inline void RenderLayer::clearZOrderLists()
+{
+ if (m_posZOrderList) {
+ delete m_posZOrderList;
+ m_posZOrderList = 0;
+ }
+
+ if (m_negZOrderList) {
+ delete m_negZOrderList;
+ m_negZOrderList = 0;
+ }
+}
+
inline void RenderLayer::updateZOrderLists()
{
- if (!m_zOrderListsDirty || !isStackingContext())
+ if (!m_zOrderListsDirty)
+ return;
+
+ if (!isStackingContext()) {
+ clearZOrderLists();
+ m_zOrderListsDirty = false;
return;
- updateZOrderListsSlowCase();
+ }
+
+ rebuildZOrderLists();
}
+#if !ASSERT_DISABLED
+class LayerListMutationDetector {
+public:
+ LayerListMutationDetector(RenderLayer* layer)
+ : m_layer(layer)
+ , m_previousMutationAllowedState(layer->layerListMutationAllowed())
+ {
+ m_layer->setLayerListMutationAllowed(false);
+ }
+
+ ~LayerListMutationDetector()
+ {
+ m_layer->setLayerListMutationAllowed(m_previousMutationAllowedState);
+ }
+
+private:
+ RenderLayer* m_layer;
+ bool m_previousMutationAllowedState;
+};
+#endif
+
+
} // namespace WebCore
#ifndef NDEBUG
diff --git a/Source/WebCore/rendering/RenderLayerBacking.cpp b/Source/WebCore/rendering/RenderLayerBacking.cpp
index daed5c265..10a16aff2 100644
--- a/Source/WebCore/rendering/RenderLayerBacking.cpp
+++ b/Source/WebCore/rendering/RenderLayerBacking.cpp
@@ -32,7 +32,6 @@
#include "AnimationController.h"
#include "CanvasRenderingContext.h"
#include "CSSPropertyNames.h"
-#include "CSSStyleSelector.h"
#include "Chrome.h"
#include "FontCache.h"
#include "FrameView.h"
@@ -52,6 +51,8 @@
#include "RenderEmbeddedObject.h"
#include "RenderVideo.h"
#include "RenderView.h"
+#include "StyleResolver.h"
+#include "TiledBacking.h"
#if ENABLE(CSS_FILTERS)
#include "FilterEffectRenderer.h"
@@ -91,6 +92,7 @@ RenderLayerBacking::RenderLayerBacking(RenderLayer* layer)
, m_artificiallyInflatedBounds(false)
, m_isMainFrameRenderViewLayer(false)
, m_usingTiledCacheLayer(false)
+ , m_requiresOwnBackingStore(true)
#if ENABLE(CSS_FILTERS)
, m_canCompositeFilters(false)
#endif
@@ -110,6 +112,15 @@ RenderLayerBacking::RenderLayerBacking(RenderLayer* layer)
}
createPrimaryGraphicsLayer();
+
+ if (m_usingTiledCacheLayer) {
+ if (Page* page = renderer()->frame()->page()) {
+ if (TiledBacking* tiledBacking = m_graphicsLayer->tiledBacking()) {
+ tiledBacking->setIsInWindow(page->isOnscreen());
+ tiledBacking->setCanHaveScrollbars(renderer()->frame()->view()->canHaveScrollbars());
+ }
+ }
+ }
}
RenderLayerBacking::~RenderLayerBacking()
@@ -130,6 +141,11 @@ PassOwnPtr<GraphicsLayer> RenderLayerBacking::createGraphicsLayer(const String&
UNUSED_PARAM(name);
#endif
graphicsLayer->setMaintainsPixelAlignment(compositor()->keepLayersPixelAligned());
+
+#if PLATFORM(MAC) && USE(CA)
+ graphicsLayer->setAcceleratesDrawing(compositor()->acceleratedDrawingEnabled());
+#endif
+
return graphicsLayer.release();
}
@@ -150,6 +166,14 @@ void RenderLayerBacking::createPrimaryGraphicsLayer()
m_graphicsLayer->setContentsOpaque(true);
m_graphicsLayer->setAppliesPageScale();
}
+
+#if PLATFORM(MAC) && USE(CA)
+ if (!compositor()->acceleratedDrawingEnabled() && renderer()->isCanvas()) {
+ HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(renderer()->node());
+ if (canvas->shouldAccelerate(canvas->size()))
+ m_graphicsLayer->setAcceleratesDrawing(true);
+ }
+#endif
updateLayerOpacity(renderer()->style());
updateLayerTransform(renderer()->style());
@@ -481,7 +505,7 @@ void RenderLayerBacking::updateGraphicsLayerGeometry()
}
if (m_owningLayer->hasTransform()) {
- const IntRect borderBox = pixelSnappedIntRect(toRenderBox(renderer())->borderBoxRect());
+ const IntRect borderBox = toRenderBox(renderer())->pixelSnappedBorderBoxRect();
// Get layout bounds in the coords of compAncestor to match relativeCompositingBounds.
IntRect layerBounds = IntRect(delta, borderBox.size());
@@ -542,6 +566,10 @@ void RenderLayerBacking::updateGraphicsLayerGeometry()
}
m_graphicsLayer->setContentsRect(contentsBox());
+
+ // If this layer was created just for clipping or to apply perspective, it doesn't need its own backing store.
+ setRequiresOwnBackingStore(compositor()->requiresOwnBackingStore(m_owningLayer, compAncestor));
+
updateDrawsContent();
updateAfterWidgetResize();
}
@@ -580,7 +608,12 @@ void RenderLayerBacking::updateInternalHierarchy()
void RenderLayerBacking::updateDrawsContent()
{
- m_graphicsLayer->setDrawsContent(containsPaintedContent());
+ bool hasPaintedContent = containsPaintedContent();
+
+ // FIXME: we could refine this to only allocate backing for one of these layers if possible.
+ m_graphicsLayer->setDrawsContent(hasPaintedContent);
+ if (m_foregroundLayer)
+ m_foregroundLayer->setDrawsContent(hasPaintedContent);
}
// Return true if the layers changed.
@@ -786,6 +819,31 @@ void RenderLayerBacking::updateBackgroundColor()
m_graphicsLayer->setContentsToBackgroundColor(rendererBackgroundColor());
}
+bool RenderLayerBacking::paintsBoxDecorations() const
+{
+ if (!m_owningLayer->hasVisibleContent())
+ return false;
+
+ if (hasBoxDecorationsOrBackground(renderer()))
+ return true;
+
+ if (m_owningLayer->hasOverflowControls())
+ return true;
+
+ return false;
+}
+
+bool RenderLayerBacking::paintsChildren() const
+{
+ if (m_owningLayer->hasVisibleContent() && containsNonEmptyRenderers())
+ return true;
+
+ if (hasVisibleNonCompositingDescendantLayers())
+ return true;
+
+ return false;
+}
+
// A "simple container layer" is a RenderLayer which has no visible content to render.
// It may have no children, or all its children may be themselves composited.
// This is a useful optimization, because it allows us to avoid allocating backing store.
@@ -796,29 +854,16 @@ bool RenderLayerBacking::isSimpleContainerCompositingLayer() const
renderObject->hasMask()) // masks require special treatment
return false;
- RenderStyle* style = renderObject->style();
- bool isVisible = m_owningLayer->hasVisibleContent();
-
- // Reject anything that has a border, a border-radius or outline,
- // or any background (color or image).
- // FIXME: we could optimize layers for simple backgrounds.
- if (isVisible && hasBoxDecorationsOrBackground(renderObject))
- return false;
-
- if (isVisible && m_owningLayer->hasOverflowControls())
+ if (paintsBoxDecorations() || paintsChildren())
return false;
-
- // If we have got this far and the renderer has no children, then we're ok.
- if (!renderObject->firstChild())
- return true;
if (renderObject->node() && renderObject->node()->isDocumentNode()) {
// Look to see if the root object has a non-simple background
- RenderObject* rootObject = renderObject->document()->documentElement()->renderer();
+ RenderObject* rootObject = renderObject->document()->documentElement() ? renderObject->document()->documentElement()->renderer() : 0;
if (!rootObject)
return false;
- style = rootObject->style();
+ RenderStyle* style = rootObject->style();
// Reject anything that has a border, a border-radius or outline,
// or is not a simple background (no background, or solid color).
@@ -837,13 +882,6 @@ bool RenderLayerBacking::isSimpleContainerCompositingLayer() const
return false;
}
- // Check to see if all the renderer's children are compositing layers.
- if (isVisible && containsNonEmptyRenderers())
- return false;
-
- if (hasVisibleNonCompositingDescendantLayers())
- return false;
-
return true;
}
@@ -869,6 +907,13 @@ bool RenderLayerBacking::containsNonEmptyRenderers() const
// Conservative test for having no rendered children.
bool RenderLayerBacking::hasVisibleNonCompositingDescendantLayers() const
{
+ // FIXME: We shouldn't be called with a stale z-order lists. See bug 85512.
+ m_owningLayer->updateLayerListsIfNeeded();
+
+#if !ASSERT_DISABLED
+ LayerListMutationDetector mutationChecker(m_owningLayer);
+#endif
+
if (Vector<RenderLayer*>* normalFlowList = m_owningLayer->normalFlowList()) {
size_t listSize = normalFlowList->size();
for (size_t i = 0; i < listSize; ++i) {
@@ -907,7 +952,7 @@ bool RenderLayerBacking::hasVisibleNonCompositingDescendantLayers() const
bool RenderLayerBacking::containsPaintedContent() const
{
- if (isSimpleContainerCompositingLayer() || paintingGoesToWindow() || m_artificiallyInflatedBounds || m_owningLayer->isReflection())
+ if (isSimpleContainerCompositingLayer() || paintsIntoWindow() || paintsIntoCompositedAncestor() || m_artificiallyInflatedBounds || m_owningLayer->isReflection())
return false;
if (isDirectlyCompositedImage())
@@ -946,14 +991,14 @@ bool RenderLayerBacking::isDirectlyCompositedImage() const
return false;
}
-void RenderLayerBacking::contentChanged(RenderLayer::ContentChangeType changeType)
+void RenderLayerBacking::contentChanged(ContentChangeType changeType)
{
- if ((changeType == RenderLayer::ImageChanged) && isDirectlyCompositedImage()) {
+ if ((changeType == ImageChanged) && isDirectlyCompositedImage()) {
updateImageContents();
return;
}
- if ((changeType == RenderLayer::MaskImageChanged) && m_maskLayer) {
+ if ((changeType == MaskImageChanged) && m_maskLayer) {
// The composited layer bounds relies on box->maskClipRect(), which changes
// when the mask image becomes available.
bool isUpdateRoot = true;
@@ -961,7 +1006,7 @@ void RenderLayerBacking::contentChanged(RenderLayer::ContentChangeType changeTyp
}
#if ENABLE(WEBGL) || ENABLE(ACCELERATED_2D_CANVAS)
- if ((changeType == RenderLayer::CanvasChanged) && isAcceleratedCanvas(renderer())) {
+ if ((changeType == CanvasChanged) && isAcceleratedCanvas(renderer())) {
m_graphicsLayer->setContentsNeedsDisplay();
return;
}
@@ -1000,8 +1045,8 @@ FloatPoint3D RenderLayerBacking::computeTransformOrigin(const IntRect& borderBox
RenderStyle* style = renderer()->style();
FloatPoint3D origin;
- origin.setX(style->transformOriginX().calcFloatValue(borderBox.width()));
- origin.setY(style->transformOriginY().calcFloatValue(borderBox.height()));
+ origin.setX(floatValueForLength(style->transformOriginX(), borderBox.width()));
+ origin.setY(floatValueForLength(style->transformOriginY(), borderBox.height()));
origin.setZ(style->transformOriginZ());
return origin;
@@ -1015,8 +1060,8 @@ FloatPoint RenderLayerBacking::computePerspectiveOrigin(const IntRect& borderBox
float boxHeight = borderBox.height();
FloatPoint origin;
- origin.setX(style->perspectiveOriginX().calcFloatValue(boxWidth));
- origin.setY(style->perspectiveOriginY().calcFloatValue(boxHeight));
+ origin.setX(floatValueForLength(style->perspectiveOriginX(), boxWidth));
+ origin.setY(floatValueForLength(style->perspectiveOriginY(), boxHeight));
return origin;
}
@@ -1046,19 +1091,27 @@ IntRect RenderLayerBacking::contentsBox() const
return contentsRect;
}
-bool RenderLayerBacking::paintingGoesToWindow() const
+bool RenderLayerBacking::paintsIntoWindow() const
{
if (m_usingTiledCacheLayer)
return false;
- if (m_owningLayer->isRootLayer())
+ if (m_owningLayer->isRootLayer()) {
+#if PLATFORM(BLACKBERRY)
+ if (compositor()->inForcedCompositingMode())
+ return false;
+#endif
+
return compositor()->rootLayerAttachment() != RenderLayerCompositor::RootLayerAttachedViaEnclosingFrame;
+ }
return false;
}
void RenderLayerBacking::setContentsNeedDisplay()
{
+ ASSERT(!paintsIntoCompositedAncestor());
+
if (m_graphicsLayer && m_graphicsLayer->drawsContent())
m_graphicsLayer->setNeedsDisplay();
@@ -1072,6 +1125,8 @@ void RenderLayerBacking::setContentsNeedDisplay()
// r is in the coordinate space of the layer's render object
void RenderLayerBacking::setContentsNeedDisplayInRect(const IntRect& r)
{
+ ASSERT(!paintsIntoCompositedAncestor());
+
if (m_graphicsLayer && m_graphicsLayer->drawsContent()) {
IntRect layerDirtyRect = r;
layerDirtyRect.move(-m_graphicsLayer->offsetFromRenderer());
@@ -1096,7 +1151,7 @@ void RenderLayerBacking::paintIntoLayer(RenderLayer* rootLayer, GraphicsContext*
PaintBehavior paintBehavior, GraphicsLayerPaintingPhase paintingPhase,
RenderObject* paintingRoot)
{
- if (paintingGoesToWindow()) {
+ if (paintsIntoWindow() || paintsIntoCompositedAncestor()) {
ASSERT_NOT_REACHED();
return;
}
@@ -1134,6 +1189,10 @@ static void paintScrollbar(Scrollbar* scrollbar, GraphicsContext& context, const
// Up-call from compositing layer drawing callback.
void RenderLayerBacking::paintContents(const GraphicsLayer* graphicsLayer, GraphicsContext& context, GraphicsLayerPaintingPhase paintingPhase, const IntRect& clip)
{
+#ifndef NDEBUG
+ if (Page* page = renderer()->frame()->page())
+ page->setIsPainting(true);
+#endif
if (graphicsLayer == m_graphicsLayer.get() || graphicsLayer == m_foregroundLayer.get() || graphicsLayer == m_maskLayer.get()) {
InspectorInstrumentationCookie cookie = InspectorInstrumentation::willPaint(m_owningLayer->renderer()->frame(), &context, clip);
@@ -1159,6 +1218,10 @@ void RenderLayerBacking::paintContents(const GraphicsLayer* graphicsLayer, Graph
m_owningLayer->paintResizer(&context, IntPoint(), transformedClip);
context.restore();
}
+#ifndef NDEBUG
+ if (Page* page = renderer()->frame()->page())
+ page->setIsPainting(false);
+#endif
}
float RenderLayerBacking::pageScaleFactor() const
@@ -1186,6 +1249,13 @@ bool RenderLayerBacking::showRepaintCounter(const GraphicsLayer*) const
return compositor() ? compositor()->compositorShowRepaintCounter() : false;
}
+#ifndef NDEBUG
+void RenderLayerBacking::verifyNotPainting()
+{
+ ASSERT(!renderer()->frame()->page() || !renderer()->frame()->page()->isPainting());
+}
+#endif
+
bool RenderLayerBacking::startAnimation(double timeOffset, const Animation* anim, const KeyframeList& keyframes)
{
bool hasOpacity = keyframes.containsProperty(CSSPropertyOpacity);
@@ -1236,21 +1306,15 @@ bool RenderLayerBacking::startAnimation(double timeOffset, const Animation* anim
bool didAnimateFilter = false;
#endif
- if (hasTransform && m_graphicsLayer->addAnimation(transformVector, pixelSnappedIntRect(toRenderBox(renderer())->borderBoxRect()).size(), anim, keyframes.animationName(), timeOffset)) {
+ if (hasTransform && m_graphicsLayer->addAnimation(transformVector, toRenderBox(renderer())->pixelSnappedBorderBoxRect().size(), anim, keyframes.animationName(), timeOffset))
didAnimateTransform = true;
- compositor()->didStartAcceleratedAnimation(CSSPropertyWebkitTransform);
- }
- if (hasOpacity && m_graphicsLayer->addAnimation(opacityVector, IntSize(), anim, keyframes.animationName(), timeOffset)) {
+ if (hasOpacity && m_graphicsLayer->addAnimation(opacityVector, IntSize(), anim, keyframes.animationName(), timeOffset))
didAnimateOpacity = true;
- compositor()->didStartAcceleratedAnimation(CSSPropertyOpacity);
- }
#if ENABLE(CSS_FILTERS)
- if (hasFilter && m_graphicsLayer->addAnimation(filterVector, IntSize(), anim, keyframes.animationName(), timeOffset)) {
+ if (hasFilter && m_graphicsLayer->addAnimation(filterVector, IntSize(), anim, keyframes.animationName(), timeOffset))
didAnimateFilter = true;
- compositor()->didStartAcceleratedAnimation(CSSPropertyWebkitFilter);
- }
#endif
#if ENABLE(CSS_FILTERS)
@@ -1270,7 +1334,7 @@ void RenderLayerBacking::animationFinished(const String& animationName)
m_graphicsLayer->removeAnimation(animationName);
}
-bool RenderLayerBacking::startTransition(double timeOffset, int property, const RenderStyle* fromStyle, const RenderStyle* toStyle)
+bool RenderLayerBacking::startTransition(double timeOffset, CSSPropertyID property, const RenderStyle* fromStyle, const RenderStyle* toStyle)
{
bool didAnimateOpacity = false;
bool didAnimateTransform = false;
@@ -1278,9 +1342,9 @@ bool RenderLayerBacking::startTransition(double timeOffset, int property, const
bool didAnimateFilter = false;
#endif
- ASSERT(property != cAnimateAll);
+ ASSERT(property != CSSPropertyInvalid);
- if (property == (int)CSSPropertyOpacity) {
+ if (property == CSSPropertyOpacity) {
const Animation* opacityAnim = toStyle->transitionForProperty(CSSPropertyOpacity);
if (opacityAnim && !opacityAnim->isEmptyOrZeroDuration()) {
KeyframeValueList opacityVector(AnimatedPropertyOpacity);
@@ -1295,13 +1359,13 @@ bool RenderLayerBacking::startTransition(double timeOffset, int property, const
}
}
- if (property == (int)CSSPropertyWebkitTransform && m_owningLayer->hasTransform()) {
+ if (property == CSSPropertyWebkitTransform && m_owningLayer->hasTransform()) {
const Animation* transformAnim = toStyle->transitionForProperty(CSSPropertyWebkitTransform);
if (transformAnim && !transformAnim->isEmptyOrZeroDuration()) {
KeyframeValueList transformVector(AnimatedPropertyWebkitTransform);
transformVector.insert(new TransformAnimationValue(0, &fromStyle->transform()));
transformVector.insert(new TransformAnimationValue(1, &toStyle->transform()));
- if (m_graphicsLayer->addAnimation(transformVector, pixelSnappedIntRect(toRenderBox(renderer())->borderBoxRect()).size(), transformAnim, GraphicsLayer::animationNameForTransition(AnimatedPropertyWebkitTransform), timeOffset)) {
+ if (m_graphicsLayer->addAnimation(transformVector, toRenderBox(renderer())->pixelSnappedBorderBoxRect().size(), transformAnim, GraphicsLayer::animationNameForTransition(AnimatedPropertyWebkitTransform), timeOffset)) {
// To ensure that the correct transform is visible when the animation ends, also set the final transform.
updateLayerTransform(toStyle);
didAnimateTransform = true;
@@ -1310,7 +1374,7 @@ bool RenderLayerBacking::startTransition(double timeOffset, int property, const
}
#if ENABLE(CSS_FILTERS)
- if (property == (int)CSSPropertyWebkitFilter && m_owningLayer->hasFilter()) {
+ if (property == CSSPropertyWebkitFilter && m_owningLayer->hasFilter()) {
const Animation* filterAnim = toStyle->transitionForProperty(CSSPropertyWebkitFilter);
if (filterAnim && !filterAnim->isEmptyOrZeroDuration()) {
KeyframeValueList filterVector(AnimatedPropertyWebkitFilter);
@@ -1325,17 +1389,6 @@ bool RenderLayerBacking::startTransition(double timeOffset, int property, const
}
#endif
- if (didAnimateOpacity)
- compositor()->didStartAcceleratedAnimation(CSSPropertyOpacity);
-
- if (didAnimateTransform)
- compositor()->didStartAcceleratedAnimation(CSSPropertyWebkitTransform);
-
-#if ENABLE(CSS_FILTERS)
- if (didAnimateFilter)
- compositor()->didStartAcceleratedAnimation(CSSPropertyWebkitFilter);
-#endif
-
#if ENABLE(CSS_FILTERS)
return didAnimateOpacity || didAnimateTransform || didAnimateFilter;
#else
@@ -1343,14 +1396,14 @@ bool RenderLayerBacking::startTransition(double timeOffset, int property, const
#endif
}
-void RenderLayerBacking::transitionPaused(double timeOffset, int property)
+void RenderLayerBacking::transitionPaused(double timeOffset, CSSPropertyID property)
{
AnimatedPropertyID animatedProperty = cssToGraphicsLayerProperty(property);
if (animatedProperty != AnimatedPropertyInvalid)
m_graphicsLayer->pauseAnimation(GraphicsLayer::animationNameForTransition(animatedProperty), timeOffset);
}
-void RenderLayerBacking::transitionFinished(int property)
+void RenderLayerBacking::transitionFinished(CSSPropertyID property)
{
AnimatedPropertyID animatedProperty = cssToGraphicsLayerProperty(property);
if (animatedProperty != AnimatedPropertyInvalid)
@@ -1387,11 +1440,11 @@ IntRect RenderLayerBacking::compositedBounds() const
void RenderLayerBacking::setCompositedBounds(const IntRect& bounds)
{
m_compositedBounds = bounds;
-
}
-int RenderLayerBacking::graphicsLayerToCSSProperty(AnimatedPropertyID property)
+
+CSSPropertyID RenderLayerBacking::graphicsLayerToCSSProperty(AnimatedPropertyID property)
{
- int cssProperty = CSSPropertyInvalid;
+ CSSPropertyID cssProperty = CSSPropertyInvalid;
switch (property) {
case AnimatedPropertyWebkitTransform:
cssProperty = CSSPropertyWebkitTransform;
@@ -1415,7 +1468,7 @@ int RenderLayerBacking::graphicsLayerToCSSProperty(AnimatedPropertyID property)
return cssProperty;
}
-AnimatedPropertyID RenderLayerBacking::cssToGraphicsLayerProperty(int cssProperty)
+AnimatedPropertyID RenderLayerBacking::cssToGraphicsLayerProperty(CSSPropertyID cssProperty)
{
switch (cssProperty) {
case CSSPropertyWebkitTransform:
@@ -1428,12 +1481,13 @@ AnimatedPropertyID RenderLayerBacking::cssToGraphicsLayerProperty(int cssPropert
case CSSPropertyWebkitFilter:
return AnimatedPropertyWebkitFilter;
#endif
- // It's fine if we see other css properties here; they are just not accelerated.
+ default:
+ // It's fine if we see other css properties here; they are just not accelerated.
+ break;
}
return AnimatedPropertyInvalid;
}
-#ifndef NDEBUG
String RenderLayerBacking::nameForLayer() const
{
String name = renderer()->renderName();
@@ -1449,7 +1503,6 @@ String RenderLayerBacking::nameForLayer() const
return name;
}
-#endif
CompositingLayerType RenderLayerBacking::compositingLayerType() const
{
@@ -1462,6 +1515,30 @@ CompositingLayerType RenderLayerBacking::compositingLayerType() const
return ContainerCompositingLayer;
}
+double RenderLayerBacking::backingStoreArea() const
+{
+ double backingArea;
+
+ // m_ancestorClippingLayer and m_clippingLayer are just used for masking, so have no backing.
+ backingArea = m_graphicsLayer->backingStoreArea();
+ if (m_foregroundLayer)
+ backingArea += m_foregroundLayer->backingStoreArea();
+ if (m_maskLayer)
+ backingArea += m_maskLayer->backingStoreArea();
+
+ if (m_layerForHorizontalScrollbar)
+ backingArea += m_layerForHorizontalScrollbar->backingStoreArea();
+
+ if (m_layerForVerticalScrollbar)
+ backingArea += m_layerForVerticalScrollbar->backingStoreArea();
+
+ if (m_layerForScrollCorner)
+ backingArea += m_layerForScrollCorner->backingStoreArea();
+
+ return backingArea;
+}
+
} // namespace WebCore
#endif // USE(ACCELERATED_COMPOSITING)
+
diff --git a/Source/WebCore/rendering/RenderLayerBacking.h b/Source/WebCore/rendering/RenderLayerBacking.h
index a75e318b9..a6a03ac77 100644
--- a/Source/WebCore/rendering/RenderLayerBacking.h
+++ b/Source/WebCore/rendering/RenderLayerBacking.h
@@ -95,19 +95,25 @@ public:
// for descendants, but its contents usually render into the window (in which case this returns true).
// This returns false for other layers, and when the document layer actually needs to paint into its backing store
// for some reason.
- bool paintingGoesToWindow() const;
+ bool paintsIntoWindow() const;
+
+ // Returns true for a composited layer that has no backing store of its own, so
+ // paints into some ancestor layer.
+ bool paintsIntoCompositedAncestor() const { return !m_requiresOwnBackingStore; }
+
+ void setRequiresOwnBackingStore(bool flag) { m_requiresOwnBackingStore = flag; }
void setContentsNeedDisplay();
// r is in the coordinate space of the layer's render object
void setContentsNeedDisplayInRect(const IntRect&);
// Notification from the renderer that its content changed.
- void contentChanged(RenderLayer::ContentChangeType);
+ void contentChanged(ContentChangeType);
// Interface to start, finish, suspend and resume animations and transitions
- bool startTransition(double timeOffset, int property, const RenderStyle* fromStyle, const RenderStyle* toStyle);
- void transitionPaused(double timeOffset, int property);
- void transitionFinished(int property);
+ bool startTransition(double, CSSPropertyID, const RenderStyle* fromStyle, const RenderStyle* toStyle);
+ void transitionPaused(double timeOffset, CSSPropertyID);
+ void transitionFinished(CSSPropertyID);
bool startAnimation(double timeOffset, const Animation* anim, const KeyframeList& keyframes);
void animationPaused(double timeOffset, const String& name);
@@ -136,6 +142,10 @@ public:
virtual bool showDebugBorders(const GraphicsLayer*) const;
virtual bool showRepaintCounter(const GraphicsLayer*) const;
+#ifndef NDEBUG
+ virtual void verifyNotPainting();
+#endif
+
IntRect contentsBox() const;
// For informative purposes only.
@@ -148,6 +158,11 @@ public:
#if ENABLE(CSS_FILTERS)
bool canCompositeFilters() const { return m_canCompositeFilters; }
#endif
+
+ // Return an estimate of the backing store area (in pixels) allocated by this object's GraphicsLayers.
+ double backingStoreArea() const;
+
+ String nameForLayer() const;
private:
void createPrimaryGraphicsLayer();
@@ -186,6 +201,9 @@ private:
bool isMainFrameRenderViewLayer() const;
+ bool paintsBoxDecorations() const;
+ bool paintsChildren() const;
+
// Returns true if this compositing layer has no visible content.
bool isSimpleContainerCompositingLayer() const;
// Returns true if this layer has content that needs to be rendered by painting into the backing store.
@@ -204,12 +222,8 @@ private:
void paintIntoLayer(RenderLayer* rootLayer, GraphicsContext*, const IntRect& paintDirtyRect, PaintBehavior, GraphicsLayerPaintingPhase, RenderObject* paintingRoot);
- static int graphicsLayerToCSSProperty(AnimatedPropertyID);
- static AnimatedPropertyID cssToGraphicsLayerProperty(int);
-
-#ifndef NDEBUG
- String nameForLayer() const;
-#endif
+ static CSSPropertyID graphicsLayerToCSSProperty(AnimatedPropertyID);
+ static AnimatedPropertyID cssToGraphicsLayerProperty(CSSPropertyID);
RenderLayer* m_owningLayer;
@@ -228,6 +242,7 @@ private:
bool m_artificiallyInflatedBounds; // bounds had to be made non-zero to make transform-origin work
bool m_isMainFrameRenderViewLayer;
bool m_usingTiledCacheLayer;
+ bool m_requiresOwnBackingStore;
#if ENABLE(CSS_FILTERS)
bool m_canCompositeFilters;
#endif
diff --git a/Source/WebCore/rendering/RenderLayerCompositor.cpp b/Source/WebCore/rendering/RenderLayerCompositor.cpp
index dbcbf2158..84ef04bcd 100644
--- a/Source/WebCore/rendering/RenderLayerCompositor.cpp
+++ b/Source/WebCore/rendering/RenderLayerCompositor.cpp
@@ -53,12 +53,13 @@
#include "ScrollbarTheme.h"
#include "ScrollingCoordinator.h"
#include "Settings.h"
+#include "TiledBacking.h"
#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
#include "HTMLMediaElement.h"
#endif
-#if PROFILE_LAYER_REBUILD
+#if !LOG_DISABLED
#include <wtf/CurrentTime.h>
#endif
@@ -128,22 +129,46 @@ private:
};
struct CompositingState {
- CompositingState(RenderLayer* compAncestor)
+ CompositingState(RenderLayer* compAncestor, bool testOverlap)
: m_compositingAncestor(compAncestor)
, m_subtreeIsCompositing(false)
+ , m_testingOverlap(testOverlap)
#ifndef NDEBUG
, m_depth(0)
#endif
{
}
+ CompositingState(const CompositingState& other)
+ : m_compositingAncestor(other.m_compositingAncestor)
+ , m_subtreeIsCompositing(other.m_subtreeIsCompositing)
+ , m_testingOverlap(other.m_testingOverlap)
+#ifndef NDEBUG
+ , m_depth(other.m_depth + 1)
+#endif
+ {
+ }
+
RenderLayer* m_compositingAncestor;
bool m_subtreeIsCompositing;
+ bool m_testingOverlap;
#ifndef NDEBUG
int m_depth;
#endif
};
+
+static inline bool compositingLogEnabled()
+{
+#if !LOG_DISABLED
+ return LogCompositing.state == WTFLogChannelOn;
+#else
+ return false;
+#endif
+}
+
+#define PIXELS_PER_MEGAPIXEL 1000000.0
+
RenderLayerCompositor::RenderLayerCompositor(RenderView* renderView)
: m_renderView(renderView)
, m_updateCompositingLayersTimer(this, &RenderLayerCompositor::updateCompositingLayersTimerFired)
@@ -152,17 +177,21 @@ RenderLayerCompositor::RenderLayerCompositor(RenderView* renderView)
, m_compositedLayerCount(0)
, m_showDebugBorders(false)
, m_showRepaintCounter(false)
+ , m_acceleratedDrawingEnabled(false)
, m_compositingConsultsOverlap(true)
- , m_compositingDependsOnGeometry(false)
- , m_compositingNeedsUpdate(false)
+ , m_reevaluateCompositingAfterLayout(false)
, m_compositing(false)
, m_compositingLayersNeedRebuild(false)
, m_flushingLayers(false)
, m_forceCompositingMode(false)
, m_rootLayerAttachment(RootLayerUnattached)
-#if PROFILE_LAYER_REBUILD
+#if !LOG_DISABLED
, m_rootLayerUpdateCount(0)
-#endif // PROFILE_LAYER_REBUILD
+ , m_obligateCompositedLayerCount(0)
+ , m_secondaryCompositedLayerCount(0)
+ , m_obligatoryBackingAreaMegaPixels(0)
+ , m_secondaryBackingAreaMegaPixels(0)
+#endif
{
}
@@ -190,6 +219,7 @@ void RenderLayerCompositor::cacheAcceleratedCompositingFlags()
bool showDebugBorders = false;
bool showRepaintCounter = false;
bool forceCompositingMode = false;
+ bool acceleratedDrawingEnabled = false;
if (Settings* settings = m_renderView->document()->settings()) {
hasAcceleratedCompositing = settings->acceleratedCompositingEnabled();
@@ -212,8 +242,9 @@ void RenderLayerCompositor::cacheAcceleratedCompositingFlags()
if (forceCompositingMode && m_renderView->document()->ownerElement())
forceCompositingMode = settings->acceleratedCompositingForScrollableFramesEnabled() && requiresCompositingForScrollableFrame();
- }
+ acceleratedDrawingEnabled = settings->acceleratedDrawingEnabled();
+ }
if (hasAcceleratedCompositing != m_hasAcceleratedCompositing || showDebugBorders != m_showDebugBorders || showRepaintCounter != m_showRepaintCounter || forceCompositingMode != m_forceCompositingMode)
setCompositingLayersNeedRebuild();
@@ -222,6 +253,7 @@ void RenderLayerCompositor::cacheAcceleratedCompositingFlags()
m_showDebugBorders = showDebugBorders;
m_showRepaintCounter = showRepaintCounter;
m_forceCompositingMode = forceCompositingMode;
+ m_acceleratedDrawingEnabled = acceleratedDrawingEnabled;
}
bool RenderLayerCompositor::canRender3DTransforms() const
@@ -296,7 +328,7 @@ void RenderLayerCompositor::scheduleCompositingLayerUpdate()
void RenderLayerCompositor::updateCompositingLayersTimerFired(Timer<RenderLayerCompositor>*)
{
- updateCompositingLayers();
+ updateCompositingLayers(CompositingUpdateAfterLayout);
}
bool RenderLayerCompositor::hasAnyAdditionalCompositedLayers(const RenderLayer* rootLayer) const
@@ -315,14 +347,15 @@ void RenderLayerCompositor::updateCompositingLayers(CompositingUpdateType update
if (m_forceCompositingMode && !m_compositing)
enableCompositingMode(true);
- if (!m_compositingDependsOnGeometry && !m_compositing && !m_compositingNeedsUpdate)
+ if (!m_reevaluateCompositingAfterLayout && !m_compositing)
return;
- bool checkForHierarchyUpdate = m_compositingDependsOnGeometry;
+ bool checkForHierarchyUpdate = m_reevaluateCompositingAfterLayout;
bool needGeometryUpdate = false;
switch (updateType) {
- case CompositingUpdateAfterLayoutOrStyleChange:
+ case CompositingUpdateAfterStyleChange:
+ case CompositingUpdateAfterLayout:
case CompositingUpdateOnHitTest:
checkForHierarchyUpdate = true;
break;
@@ -338,22 +371,28 @@ void RenderLayerCompositor::updateCompositingLayers(CompositingUpdateType update
return;
bool needHierarchyUpdate = m_compositingLayersNeedRebuild;
+ bool isFullUpdate = !updateRoot;
if (!updateRoot || m_compositingConsultsOverlap) {
// Only clear the flag if we're updating the entire hierarchy.
m_compositingLayersNeedRebuild = false;
updateRoot = rootRenderLayer();
}
-#if PROFILE_LAYER_REBUILD
- ++m_rootLayerUpdateCount;
-
- double startTime = WTF::currentTime();
-#endif
+ if (isFullUpdate && updateType == CompositingUpdateAfterLayout)
+ m_reevaluateCompositingAfterLayout = false;
+
+#if !LOG_DISABLED
+ double startTime = 0;
+ if (compositingLogEnabled()) {
+ ++m_rootLayerUpdateCount;
+ startTime = currentTime();
+ }
+#endif
if (checkForHierarchyUpdate) {
// Go through the layers in presentation order, so that we can compute which RenderLayers need compositing layers.
// FIXME: we could maybe do this and the hierarchy udpate in one pass, but the parenting logic would be more complex.
- CompositingState compState(updateRoot);
+ CompositingState compState(updateRoot, m_compositingConsultsOverlap);
bool layersChanged = false;
if (m_compositingConsultsOverlap) {
OverlapMap overlapTestRequestMap;
@@ -364,13 +403,27 @@ void RenderLayerCompositor::updateCompositingLayers(CompositingUpdateType update
needHierarchyUpdate |= layersChanged;
}
+#if !LOG_DISABLED
+ if (compositingLogEnabled() && isFullUpdate && (needHierarchyUpdate || needGeometryUpdate)) {
+ m_obligateCompositedLayerCount = 0;
+ m_secondaryCompositedLayerCount = 0;
+ m_obligatoryBackingAreaMegaPixels = 0;
+ m_secondaryBackingAreaMegaPixels = 0;
+
+ Frame* frame = m_renderView->frameView()->frame();
+ bool isMainFrame = !m_renderView->document()->ownerElement();
+ LOG(Compositing, "\nUpdate %d of %s. Overlap testing is %s\n", m_rootLayerUpdateCount, isMainFrame ? "main frame" : frame->tree()->uniqueName().string().utf8().data(),
+ m_compositingConsultsOverlap ? "on" : "off");
+ }
+#endif
+
if (needHierarchyUpdate) {
// Update the hierarchy of the compositing layers.
Vector<GraphicsLayer*> childList;
- rebuildCompositingLayerTree(updateRoot, childList);
+ rebuildCompositingLayerTree(updateRoot, childList, 0);
// Host the document layer in the RenderView's root layer.
- if (updateRoot == rootRenderLayer()) {
+ if (isFullUpdate) {
// Even when childList is empty, don't drop out of compositing mode if there are
// composited layers that we didn't hit in our traversal (e.g. because of visibility:hidden).
if (childList.isEmpty() && !hasAnyAdditionalCompositedLayers(updateRoot))
@@ -381,22 +434,45 @@ void RenderLayerCompositor::updateCompositingLayers(CompositingUpdateType update
} else if (needGeometryUpdate) {
// We just need to do a geometry update. This is only used for position:fixed scrolling;
// most of the time, geometry is updated via RenderLayer::styleChanged().
- updateLayerTreeGeometry(updateRoot);
+ updateLayerTreeGeometry(updateRoot, 0);
}
-#if PROFILE_LAYER_REBUILD
- double endTime = WTF::currentTime();
- if (updateRoot == rootRenderLayer())
- fprintf(stderr, "Update %d: computeCompositingRequirements for the world took %fms\n",
- m_rootLayerUpdateCount, 1000.0 * (endTime - startTime));
+#if !LOG_DISABLED
+ if (compositingLogEnabled() && isFullUpdate && (needHierarchyUpdate || needGeometryUpdate)) {
+ double endTime = currentTime();
+ LOG(Compositing, "Total layers primary secondary obligatory backing (MP) secondary backing(MP) total backing (MP) update time (ms)\n");
+
+ LOG(Compositing, "%8d %11d %9d %20.2f %22.2f %22.2f %18.2f\n",
+ m_obligateCompositedLayerCount + m_secondaryCompositedLayerCount, m_obligateCompositedLayerCount,
+ m_secondaryCompositedLayerCount, m_obligatoryBackingAreaMegaPixels, m_secondaryBackingAreaMegaPixels, m_obligatoryBackingAreaMegaPixels + m_secondaryBackingAreaMegaPixels, 1000.0 * (endTime - startTime));
+ }
#endif
ASSERT(updateRoot || !m_compositingLayersNeedRebuild);
if (!hasAcceleratedCompositing())
enableCompositingMode(false);
+}
+
+#if !LOG_DISABLED
+void RenderLayerCompositor::logLayerInfo(const RenderLayer* layer, int depth)
+{
+ if (!compositingLogEnabled())
+ return;
+
+ RenderLayerBacking* backing = layer->backing();
+ if (requiresCompositingLayer(layer) || layer->isRootLayer()) {
+ ++m_obligateCompositedLayerCount;
+ m_obligatoryBackingAreaMegaPixels += backing->backingStoreArea() / PIXELS_PER_MEGAPIXEL;
+ } else {
+ ++m_secondaryCompositedLayerCount;
+ m_secondaryBackingAreaMegaPixels += backing->backingStoreArea() / PIXELS_PER_MEGAPIXEL;
+ }
- m_compositingNeedsUpdate = false;
+ LOG(Compositing, "%*p %dx%d %.3fMP (%s) %s\n", 12 + depth * 2, layer, backing->compositedBounds().width(), backing->compositedBounds().height(),
+ backing->backingStoreArea() / PIXELS_PER_MEGAPIXEL,
+ reasonForCompositing(layer), layer->backing()->nameForLayer().utf8().data());
}
+#endif
bool RenderLayerCompositor::updateBacking(RenderLayer* layer, CompositingChangeRepaint shouldRepaint)
{
@@ -405,12 +481,7 @@ bool RenderLayerCompositor::updateBacking(RenderLayer* layer, CompositingChangeR
if (needsToBeComposited(layer)) {
enableCompositingMode();
- // Non-identity 3D transforms turn off the testing of overlap.
- if (hasNonIdentity3DTransform(layer->renderer()))
- setCompositingConsultsOverlap(false);
-
if (!layer->backing()) {
-
// If we need to repaint, do so before making backing
if (shouldRepaint == CompositingChangeRepaintNow)
repaintOnCompositingChange(layer);
@@ -420,18 +491,9 @@ bool RenderLayerCompositor::updateBacking(RenderLayer* layer, CompositingChangeR
// The RenderLayer's needs to update repaint rects here, because the target
// repaintContainer may have changed after becoming a composited layer.
// https://bugs.webkit.org/show_bug.cgi?id=80641
- layer->computeRepaintRects();
+ if (layer->parent())
+ layer->computeRepaintRects();
-#if PLATFORM(MAC) && USE(CA)
- Settings* settings = m_renderView->document()->settings();
- if (settings && settings->acceleratedDrawingEnabled())
- layer->backing()->graphicsLayer()->setAcceleratesDrawing(true);
- else if (layer->renderer()->isCanvas()) {
- HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(layer->renderer()->node());
- if (canvas->shouldAccelerate(canvas->size()))
- layer->backing()->graphicsLayer()->setAcceleratesDrawing(true);
- }
-#endif
layerChanged = true;
}
} else {
@@ -514,83 +576,7 @@ IntRect RenderLayerCompositor::calculateCompositedBounds(const RenderLayer* laye
{
if (!canBeComposited(layer))
return IntRect();
-
- LayoutRect boundingBoxRect = layer->localBoundingBox();
- 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
- // to the code in RenderBox::paintRootBoxFillLayers().
- if (m_renderView->frameView()) {
- LayoutUnit rw = m_renderView->frameView()->contentsWidth();
- LayoutUnit rh = m_renderView->frameView()->contentsHeight();
-
- boundingBoxRect.setWidth(max(boundingBoxRect.width(), rw - boundingBoxRect.x()));
- boundingBoxRect.setHeight(max(boundingBoxRect.height(), rh - boundingBoxRect.y()));
- }
- }
-
- LayoutRect unionBounds = boundingBoxRect;
-
- if (layer->renderer()->hasOverflowClip() || layer->renderer()->hasMask()) {
- LayoutPoint ancestorRelOffset;
- layer->convertToLayerCoords(ancestorLayer, ancestorRelOffset);
- boundingBoxRect.moveBy(ancestorRelOffset);
- return pixelSnappedIntRect(boundingBoxRect);
- }
-
- if (RenderLayer* reflection = layer->reflectionLayer()) {
- if (!reflection->isComposited()) {
- LayoutRect childUnionBounds = calculateCompositedBounds(reflection, layer);
- unionBounds.unite(childUnionBounds);
- }
- }
-
- ASSERT(layer->isStackingContext() || (!layer->m_posZOrderList || layer->m_posZOrderList->size() == 0));
-
- if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) {
- size_t listSize = negZOrderList->size();
- for (size_t i = 0; i < listSize; ++i) {
- RenderLayer* curLayer = negZOrderList->at(i);
- if (!curLayer->isComposited()) {
- LayoutRect childUnionBounds = calculateCompositedBounds(curLayer, layer);
- unionBounds.unite(childUnionBounds);
- }
- }
- }
-
- if (Vector<RenderLayer*>* posZOrderList = layer->posZOrderList()) {
- size_t listSize = posZOrderList->size();
- for (size_t i = 0; i < listSize; ++i) {
- RenderLayer* curLayer = posZOrderList->at(i);
- if (!curLayer->isComposited()) {
- LayoutRect childUnionBounds = calculateCompositedBounds(curLayer, layer);
- unionBounds.unite(childUnionBounds);
- }
- }
- }
-
- if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) {
- size_t listSize = normalFlowList->size();
- for (size_t i = 0; i < listSize; ++i) {
- RenderLayer* curLayer = normalFlowList->at(i);
- if (!curLayer->isComposited()) {
- LayoutRect curAbsBounds = calculateCompositedBounds(curLayer, layer);
- unionBounds.unite(curAbsBounds);
- }
- }
- }
-
- if (layer->paintsWithTransform(PaintBehaviorNormal)) {
- TransformationMatrix* affineTrans = layer->transform();
- boundingBoxRect = affineTrans->mapRect(boundingBoxRect);
- unionBounds = affineTrans->mapRect(unionBounds);
- }
-
- LayoutPoint ancestorRelOffset;
- layer->convertToLayerCoords(ancestorLayer, ancestorRelOffset);
- unionBounds.moveBy(ancestorRelOffset);
-
- return pixelSnappedIntRect(unionBounds);
+ return pixelSnappedIntRect(RenderLayer::calculateLayerBounds(layer, ancestorLayer));
}
void RenderLayerCompositor::layerWasAdded(RenderLayer* /*parent*/, RenderLayer* /*child*/)
@@ -605,7 +591,7 @@ void RenderLayerCompositor::layerWillBeRemoved(RenderLayer* parent, RenderLayer*
setCompositingParent(child, 0);
- RenderLayer* compLayer = parent->enclosingCompositingLayer();
+ RenderLayer* compLayer = parent->enclosingCompositingLayerForRepaint();
if (compLayer) {
ASSERT(compLayer->backing());
LayoutRect compBounds = child->backing()->compositedBounds();
@@ -643,12 +629,12 @@ void RenderLayerCompositor::addToOverlapMap(OverlapMap& overlapMap, RenderLayer*
if (!boundsComputed) {
layerBounds = layer->renderer()->localToAbsoluteQuad(FloatRect(layer->localBoundingBox())).enclosingBoundingBox();
+ // Empty rects never intersect, but we need them to for the purposes of overlap testing.
+ if (layerBounds.isEmpty())
+ layerBounds.setSize(IntSize(1, 1));
boundsComputed = true;
}
- if (layerBounds.isEmpty())
- return;
-
IntRect clipRect = pixelSnappedIntRect(layer->backgroundClipRect(rootRenderLayer(), 0, true).rect()); // FIXME: Incorrect for CSS regions.
clipRect.scale(pageScaleFactor());
clipRect.intersect(layerBounds);
@@ -664,6 +650,10 @@ void RenderLayerCompositor::addToOverlapMapRecursive(OverlapMap& overlapMap, Ren
bool haveComputedBounds = false;
addToOverlapMap(overlapMap, layer, bounds, haveComputedBounds);
+#if !ASSERT_DISABLED
+ LayerListMutationDetector mutationChecker(layer);
+#endif
+
if (layer->isStackingContext()) {
if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) {
size_t listSize = negZOrderList->size();
@@ -674,7 +664,6 @@ void RenderLayerCompositor::addToOverlapMapRecursive(OverlapMap& overlapMap, Ren
}
}
- ASSERT(!layer->m_normalFlowListDirty);
if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) {
size_t listSize = normalFlowList->size();
for (size_t i = 0; i < listSize; ++i) {
@@ -703,12 +692,11 @@ void RenderLayerCompositor::addToOverlapMapRecursive(OverlapMap& overlapMap, Ren
// must be compositing so that its contents render over that child.
// This implies that its positive z-index children must also be compositing.
//
-void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, OverlapMap* overlapMap, struct CompositingState& compositingState, bool& layersChanged)
+void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, OverlapMap* overlapMap, CompositingState& compositingState, bool& layersChanged)
{
layer->updateLayerPosition();
- layer->updateZOrderLists();
- layer->updateNormalFlowList();
-
+ layer->updateLayerListsIfNeeded();
+
// Clear the flag
layer->setHasCompositingDescendant(false);
@@ -716,10 +704,12 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O
bool haveComputedBounds = false;
IntRect absBounds;
- if (overlapMap && !overlapMap->isEmpty()) {
+ if (overlapMap && !overlapMap->isEmpty() && compositingState.m_testingOverlap) {
// If we're testing for overlap, we only need to composite if we overlap something that is already composited.
absBounds = layer->renderer()->localToAbsoluteQuad(FloatRect(layer->localBoundingBox())).enclosingBoundingBox();
// Empty rects never intersect, but we need them to for the purposes of overlap testing.
+ if (absBounds.isEmpty())
+ absBounds.setSize(IntSize(1, 1));
haveComputedBounds = true;
mustOverlapCompositedLayers = overlapMap->overlapsLayers(absBounds);
}
@@ -729,10 +719,8 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O
// The children of this layer don't need to composite, unless there is
// a compositing layer among them, so start by inheriting the compositing
// ancestor with m_subtreeIsCompositing set to false.
- CompositingState childState(compositingState.m_compositingAncestor);
-#ifndef NDEBUG
- childState.m_depth = compositingState.m_depth + 1;
-#endif
+ CompositingState childState(compositingState);
+ childState.m_subtreeIsCompositing = false;
bool willBeComposited = needsToBeComposited(layer);
if (willBeComposited) {
@@ -743,6 +731,11 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O
if (overlapMap)
overlapMap->pushCompositingContainer();
+
+ if (hasNonAffineTransform(layer->renderer()) || isRunningAcceleratedTransformAnimation(layer->renderer())) {
+ // If we have a 3D transform, or are animating transform, then turn overlap testing off.
+ childState.m_testingOverlap = false;
+ }
}
#if ENABLE(VIDEO)
@@ -753,8 +746,11 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O
childState.m_subtreeIsCompositing = true;
#endif
+#if !ASSERT_DISABLED
+ LayerListMutationDetector mutationChecker(layer);
+#endif
+
if (layer->isStackingContext()) {
- ASSERT(!layer->m_zOrderListsDirty);
if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) {
size_t listSize = negZOrderList->size();
for (size_t i = 0; i < listSize; ++i) {
@@ -775,7 +771,6 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O
}
}
- ASSERT(!layer->m_normalFlowListDirty);
if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) {
size_t listSize = normalFlowList->size();
for (size_t i = 0; i < listSize; ++i) {
@@ -822,25 +817,36 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O
}
ASSERT(willBeComposited == needsToBeComposited(layer));
- if (layer->reflectionLayer())
+ if (layer->reflectionLayer()) {
+ // FIXME: Shouldn't we call computeCompositingRequirements to handle a reflection overlapping with another renderer?
layer->reflectionLayer()->setMustOverlapCompositedLayers(willBeComposited);
+ }
// Subsequent layers in the parent stacking context also need to composite.
if (childState.m_subtreeIsCompositing)
compositingState.m_subtreeIsCompositing = true;
+ // We have to keep overlap testing disabled for later layers.
+ if (!childState.m_testingOverlap)
+ compositingState.m_testingOverlap = false;
+
// Set the flag to say that this SC has compositing children.
layer->setHasCompositingDescendant(childState.m_subtreeIsCompositing);
// setHasCompositingDescendant() may have changed the answer to needsToBeComposited() when clipping,
// so test that again.
- if (!willBeComposited && canBeComposited(layer) && clipsCompositingDescendants(layer)) {
- childState.m_compositingAncestor = layer;
- if (overlapMap) {
- overlapMap->pushCompositingContainer();
- addToOverlapMapRecursive(*overlapMap, layer);
- }
- willBeComposited = true;
+ if (canBeComposited(layer) && clipsCompositingDescendants(layer)) {
+ if (!willBeComposited) {
+ childState.m_compositingAncestor = layer;
+ if (overlapMap) {
+ overlapMap->pushCompositingContainer();
+ addToOverlapMapRecursive(*overlapMap, layer);
+ }
+ willBeComposited = true;
+ }
+
+ // We're done processing an element that clips. The container can keep testing overlap.
+ compositingState.m_testingOverlap = true;
}
if (overlapMap && childState.m_compositingAncestor == layer && !layer->isRootLayer())
@@ -905,7 +911,7 @@ bool RenderLayerCompositor::canAccelerateVideoRendering(RenderVideo* o) const
}
#endif
-void RenderLayerCompositor::rebuildCompositingLayerTree(RenderLayer* layer, Vector<GraphicsLayer*>& childLayersOfEnclosingLayer)
+void RenderLayerCompositor::rebuildCompositingLayerTree(RenderLayer* layer, Vector<GraphicsLayer*>& childLayersOfEnclosingLayer, int depth)
{
// Make the layer compositing if necessary, and set up clipping and content layers.
// Note that we can only do work here that is independent of whether the descendant layers
@@ -927,6 +933,12 @@ void RenderLayerCompositor::rebuildCompositingLayerTree(RenderLayer* layer, Vect
if (!layer->parent())
updateRootLayerPosition();
+
+#if !LOG_DISABLED
+ logLayerInfo(layer, depth);
+#else
+ UNUSED_PARAM(depth);
+#endif
}
// If this layer has backing, then we are collecting its children, otherwise appending
@@ -934,14 +946,16 @@ void RenderLayerCompositor::rebuildCompositingLayerTree(RenderLayer* layer, Vect
Vector<GraphicsLayer*> layerChildren;
Vector<GraphicsLayer*>& childList = layerBacking ? layerChildren : childLayersOfEnclosingLayer;
- if (layer->isStackingContext()) {
- ASSERT(!layer->m_zOrderListsDirty);
+#if !ASSERT_DISABLED
+ LayerListMutationDetector mutationChecker(layer);
+#endif
+ if (layer->isStackingContext()) {
if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) {
size_t listSize = negZOrderList->size();
for (size_t i = 0; i < listSize; ++i) {
RenderLayer* curLayer = negZOrderList->at(i);
- rebuildCompositingLayerTree(curLayer, childList);
+ rebuildCompositingLayerTree(curLayer, childList, depth + 1);
}
}
@@ -950,12 +964,11 @@ void RenderLayerCompositor::rebuildCompositingLayerTree(RenderLayer* layer, Vect
childList.append(layerBacking->foregroundLayer());
}
- ASSERT(!layer->m_normalFlowListDirty);
if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) {
size_t listSize = normalFlowList->size();
for (size_t i = 0; i < listSize; ++i) {
RenderLayer* curLayer = normalFlowList->at(i);
- rebuildCompositingLayerTree(curLayer, childList);
+ rebuildCompositingLayerTree(curLayer, childList, depth + 1);
}
}
@@ -964,7 +977,7 @@ void RenderLayerCompositor::rebuildCompositingLayerTree(RenderLayer* layer, Vect
size_t listSize = posZOrderList->size();
for (size_t i = 0; i < listSize; ++i) {
RenderLayer* curLayer = posZOrderList->at(i);
- rebuildCompositingLayerTree(curLayer, childList);
+ rebuildCompositingLayerTree(curLayer, childList, depth + 1);
}
}
}
@@ -1027,8 +1040,8 @@ void RenderLayerCompositor::frameViewDidScroll()
FrameView* frameView = m_renderView->frameView();
IntPoint scrollPosition = frameView->scrollPosition();
- if (RenderLayerBacking* backing = rootRenderLayer()->backing())
- backing->graphicsLayer()->visibleRectChanged(frameView->visibleContentRect(false /* exclude scrollbars */));
+ if (TiledBacking* tiledBacking = frameView->tiledBacking())
+ tiledBacking->visibleRectChanged(frameView->visibleContentRect(false /* exclude scrollbars */));
if (!m_scrollLayer)
return;
@@ -1045,7 +1058,7 @@ void RenderLayerCompositor::frameViewDidScroll()
String RenderLayerCompositor::layerTreeAsText(bool showDebugInfo)
{
- updateCompositingLayers();
+ updateCompositingLayers(CompositingUpdateAfterLayout);
if (!m_rootContentLayer)
return String();
@@ -1089,7 +1102,7 @@ bool RenderLayerCompositor::parentFrameContentLayers(RenderPart* renderer)
}
// This just updates layer geometry without changing the hierarchy.
-void RenderLayerCompositor::updateLayerTreeGeometry(RenderLayer* layer)
+void RenderLayerCompositor::updateLayerTreeGeometry(RenderLayer* layer, int depth)
{
if (RenderLayerBacking* layerBacking = layer->backing()) {
// The compositing state of all our children has been updated already, so now
@@ -1106,30 +1119,37 @@ void RenderLayerCompositor::updateLayerTreeGeometry(RenderLayer* layer)
if (!layer->parent())
updateRootLayerPosition();
+
+#if !LOG_DISABLED
+ logLayerInfo(layer, depth);
+#else
+ UNUSED_PARAM(depth);
+#endif
}
- if (layer->isStackingContext()) {
- ASSERT(!layer->m_zOrderListsDirty);
+#if !ASSERT_DISABLED
+ LayerListMutationDetector mutationChecker(layer);
+#endif
+ if (layer->isStackingContext()) {
if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) {
size_t listSize = negZOrderList->size();
for (size_t i = 0; i < listSize; ++i)
- updateLayerTreeGeometry(negZOrderList->at(i));
+ updateLayerTreeGeometry(negZOrderList->at(i), depth + 1);
}
}
- ASSERT(!layer->m_normalFlowListDirty);
if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) {
size_t listSize = normalFlowList->size();
for (size_t i = 0; i < listSize; ++i)
- updateLayerTreeGeometry(normalFlowList->at(i));
+ updateLayerTreeGeometry(normalFlowList->at(i), depth + 1);
}
if (layer->isStackingContext()) {
if (Vector<RenderLayer*>* posZOrderList = layer->posZOrderList()) {
size_t listSize = posZOrderList->size();
for (size_t i = 0; i < listSize; ++i)
- updateLayerTreeGeometry(posZOrderList->at(i));
+ updateLayerTreeGeometry(posZOrderList->at(i), depth + 1);
}
}
}
@@ -1157,6 +1177,10 @@ void RenderLayerCompositor::updateCompositingDescendantGeometry(RenderLayer* com
if (!layer->hasCompositingDescendant())
return;
+
+#if !ASSERT_DISABLED
+ LayerListMutationDetector mutationChecker(layer);
+#endif
if (layer->isStackingContext()) {
if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) {
@@ -1190,9 +1214,13 @@ void RenderLayerCompositor::repaintCompositedLayersAbsoluteRect(const IntRect& a
void RenderLayerCompositor::recursiveRepaintLayerRect(RenderLayer* layer, const IntRect& rect)
{
// FIXME: This method does not work correctly with transforms.
- if (layer->isComposited())
+ if (layer->isComposited() && !layer->backing()->paintsIntoCompositedAncestor())
layer->setBackingNeedsRepaintInRect(rect);
+#if !ASSERT_DISABLED
+ LayerListMutationDetector mutationChecker(layer);
+#endif
+
if (layer->hasCompositingDescendant()) {
if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) {
size_t listSize = negZOrderList->size();
@@ -1301,15 +1329,6 @@ void RenderLayerCompositor::updateRootLayerPosition()
#endif
}
-void RenderLayerCompositor::didStartAcceleratedAnimation(CSSPropertyID property)
-{
- // If an accelerated animation or transition runs, we have to turn off overlap checking because
- // we don't do layout for every frame, but we have to ensure that the layering is
- // correct between the animating object and other objects on the page.
- if (property == CSSPropertyWebkitTransform)
- setCompositingConsultsOverlap(false);
-}
-
bool RenderLayerCompositor::has3DContent() const
{
return layerHas3DContent(rootRenderLayer());
@@ -1381,22 +1400,106 @@ bool RenderLayerCompositor::requiresCompositingLayer(const RenderLayer* layer) c
}
// The root layer always has a compositing layer, but it may not have backing.
return requiresCompositingForTransform(renderer)
- || requiresCompositingForVideo(renderer)
- || requiresCompositingForCanvas(renderer)
- || requiresCompositingForPlugin(renderer)
- || requiresCompositingForFrame(renderer)
- || (canRender3DTransforms() && renderer->style()->backfaceVisibility() == BackfaceVisibilityHidden)
- || clipsCompositingDescendants(layer)
- || requiresCompositingForAnimation(renderer)
- || requiresCompositingForFilters(renderer)
- || requiresCompositingForPosition(renderer, layer);
+ || requiresCompositingForVideo(renderer)
+ || requiresCompositingForCanvas(renderer)
+ || requiresCompositingForPlugin(renderer)
+ || requiresCompositingForFrame(renderer)
+ || (canRender3DTransforms() && renderer->style()->backfaceVisibility() == BackfaceVisibilityHidden)
+ || clipsCompositingDescendants(layer)
+ || requiresCompositingForAnimation(renderer)
+ || requiresCompositingForFilters(renderer)
+ || requiresCompositingForPosition(renderer, layer);
}
bool RenderLayerCompositor::canBeComposited(const RenderLayer* layer) const
{
- return m_hasAcceleratedCompositing && layer->isSelfPaintingLayer();
+ // FIXME: We disable accelerated compositing for elements in a RenderFlowThread as it doesn't work properly.
+ // See http://webkit.org/b/84900 to re-enable it.
+ return m_hasAcceleratedCompositing && layer->isSelfPaintingLayer() && !layer->renderer()->inRenderFlowThread();
}
+bool RenderLayerCompositor::requiresOwnBackingStore(const RenderLayer* layer, const RenderLayer* compositingAncestorLayer) const
+{
+ RenderObject* renderer = layer->renderer();
+ if (compositingAncestorLayer
+ && !(compositingAncestorLayer->backing()->graphicsLayer()->drawsContent()
+ || compositingAncestorLayer->backing()->paintsIntoWindow()
+ || compositingAncestorLayer->backing()->paintsIntoCompositedAncestor()))
+ return true;
+
+ return layer->isRootLayer()
+ || layer->transform() // note: excludes perspective and transformStyle3D.
+ || requiresCompositingForVideo(renderer)
+ || requiresCompositingForCanvas(renderer)
+ || requiresCompositingForPlugin(renderer)
+ || requiresCompositingForFrame(renderer)
+ || (canRender3DTransforms() && renderer->style()->backfaceVisibility() == BackfaceVisibilityHidden)
+ || requiresCompositingForAnimation(renderer)
+ || requiresCompositingForFilters(renderer)
+ || requiresCompositingForPosition(renderer, layer)
+ || renderer->isTransparent()
+ || renderer->hasMask()
+ || renderer->hasReflection()
+ || renderer->hasFilter()
+ || layer->mustOverlapCompositedLayers();
+}
+
+#if !LOG_DISABLED
+const char* RenderLayerCompositor::reasonForCompositing(const RenderLayer* layer)
+{
+ RenderObject* renderer = layer->renderer();
+ if (layer->isReflection()) {
+ renderer = renderer->parent();
+ layer = toRenderBoxModelObject(renderer)->layer();
+ }
+
+ if (renderer->hasTransform() && renderer->style()->hasPerspective())
+ return "perspective";
+
+ if (renderer->hasTransform() && (renderer->style()->transformStyle3D() == TransformStyle3DPreserve3D))
+ return "preserve-3d";
+
+ if (renderer->hasTransform())
+ return "transform";
+
+ if (requiresCompositingForVideo(renderer))
+ return "video";
+
+ if (requiresCompositingForCanvas(renderer))
+ return "canvas";
+
+ if (requiresCompositingForPlugin(renderer))
+ return "plugin";
+
+ if (requiresCompositingForFrame(renderer))
+ return "iframe";
+
+ if ((canRender3DTransforms() && renderer->style()->backfaceVisibility() == BackfaceVisibilityHidden))
+ return "backface-visibility: hidden";
+
+ if (clipsCompositingDescendants(layer))
+ return "clips compositing descendants";
+
+ if (requiresCompositingForAnimation(renderer))
+ return "animation";
+
+ if (requiresCompositingForFilters(renderer))
+ return "filters";
+
+ if (requiresCompositingForPosition(renderer, layer))
+ return "position: fixed";
+
+ // This includes layers made composited by requiresCompositingWhenDescendantsAreCompositing().
+ if (layer->mustOverlapCompositedLayers())
+ return "overlap/stacking";
+
+ if (inCompositingMode() && layer->isRootLayer())
+ return "root";
+
+ return "";
+}
+#endif
+
// Return true if the given layer has some ancestor in the RenderLayer hierarchy that clips,
// up to the enclosing compositing ancestor. This is required because compositing layers are parented
// according to the z-order hierarchy, yet clipping goes down the renderer hierarchy.
@@ -1510,7 +1613,7 @@ bool RenderLayerCompositor::requiresCompositingForPlugin(RenderObject* renderer)
if (!composite)
return false;
- m_compositingDependsOnGeometry = true;
+ m_reevaluateCompositingAfterLayout = true;
RenderWidget* pluginRenderer = toRenderWidget(renderer);
// If we can't reliably know the size of the plugin yet, don't change compositing state.
@@ -1532,7 +1635,7 @@ bool RenderLayerCompositor::requiresCompositingForFrame(RenderObject* renderer)
if (!frameRenderer->requiresAcceleratedCompositing())
return false;
- m_compositingDependsOnGeometry = true;
+ m_reevaluateCompositingAfterLayout = true;
RenderLayerCompositor* innerCompositor = frameContentsCompositor(frameRenderer);
if (!innerCompositor || !innerCompositor->shouldPropagateCompositingToEnclosingFrame())
@@ -1598,7 +1701,7 @@ bool RenderLayerCompositor::requiresCompositingForPosition(RenderObject* rendere
RenderObject* container = renderer->container();
// If the renderer is not hooked up yet then we have to wait until it is.
if (!container) {
- m_compositingNeedsUpdate = true;
+ m_reevaluateCompositingAfterLayout = true;
return false;
}
@@ -1609,26 +1712,34 @@ bool RenderLayerCompositor::requiresCompositingForPosition(RenderObject* rendere
// Fixed position elements that are invisible in the current view don't get their own layer.
FrameView* frameView = m_renderView->frameView();
- if (frameView && !layer->absoluteBoundingBox().intersects(LayoutRect(frameView->scrollXForFixedPosition(), frameView->scrollYForFixedPosition(), frameView->layoutWidth(), frameView->layoutHeight())))
+ if (frameView && !layer->absoluteBoundingBox().intersects(IntRect(frameView->scrollXForFixedPosition(), frameView->scrollYForFixedPosition(), frameView->layoutWidth(), frameView->layoutHeight())))
return false;
return true;
}
-bool RenderLayerCompositor::hasNonIdentity3DTransform(RenderObject* renderer) const
+bool RenderLayerCompositor::hasNonAffineTransform(RenderObject* renderer) const
{
if (!renderer->hasTransform())
return false;
- if (renderer->style()->hasPerspective())
- return true;
-
if (TransformationMatrix* transform = toRenderBoxModelObject(renderer)->layer()->transform())
return !transform->isAffine();
return false;
}
+bool RenderLayerCompositor::isRunningAcceleratedTransformAnimation(RenderObject* renderer) const
+{
+ if (!(m_compositingTriggers & ChromeClient::AnimationTrigger))
+ return false;
+
+ if (AnimationController* animController = renderer->animation())
+ return animController->isRunningAnimationOnRenderer(renderer, CSSPropertyWebkitTransform);
+
+ return false;
+}
+
// If an element has negative z-index children, those children render in front of the
// layer background, so we need an extra 'contents' layer for the foreground of the layer
// object.
@@ -2098,7 +2209,7 @@ void RenderLayerCompositor::updateRootLayerAttachment()
void RenderLayerCompositor::rootLayerAttachmentChanged()
{
- // The attachment can affect whether the RenderView layer's paintingGoesToWindow() behavior,
+ // The attachment can affect whether the RenderView layer's paintsIntoWindow() behavior,
// so call updateGraphicsLayerGeometry() to udpate that.
RenderLayer* layer = m_renderView->layer();
if (RenderLayerBacking* backing = layer ? layer->backing() : 0)
@@ -2135,6 +2246,12 @@ bool RenderLayerCompositor::layerHas3DContent(const RenderLayer* layer) const
style->transform().has3DOperation()))
return true;
+ const_cast<RenderLayer*>(layer)->updateLayerListsIfNeeded();
+
+#if !ASSERT_DISABLED
+ LayerListMutationDetector mutationChecker(const_cast<RenderLayer*>(layer));
+#endif
+
if (layer->isStackingContext()) {
if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) {
size_t listSize = negZOrderList->size();
diff --git a/Source/WebCore/rendering/RenderLayerCompositor.h b/Source/WebCore/rendering/RenderLayerCompositor.h
index 98a2a9f95..e294b5866 100644
--- a/Source/WebCore/rendering/RenderLayerCompositor.h
+++ b/Source/WebCore/rendering/RenderLayerCompositor.h
@@ -32,8 +32,6 @@
namespace WebCore {
-#define PROFILE_LAYER_REBUILD 0
-
class GraphicsLayer;
class RenderEmbeddedObject;
class RenderPart;
@@ -43,7 +41,8 @@ class RenderVideo;
#endif
enum CompositingUpdateType {
- CompositingUpdateAfterLayoutOrStyleChange,
+ CompositingUpdateAfterStyleChange,
+ CompositingUpdateAfterLayout,
CompositingUpdateOnHitTest,
CompositingUpdateOnScroll
};
@@ -66,7 +65,9 @@ public:
// This will make a compositing layer at the root automatically, and hook up to
// the native view/window system.
void enableCompositingMode(bool enable = true);
-
+
+ bool inForcedCompositingMode() const { return m_forceCompositingMode; }
+
// Returns true if the accelerated compositing is enabled
bool hasAcceleratedCompositing() const { return m_hasAcceleratedCompositing; }
@@ -98,7 +99,7 @@ public:
void didFlushChangesForLayer(RenderLayer*);
// Rebuild the tree of compositing layers
- void updateCompositingLayers(CompositingUpdateType = CompositingUpdateAfterLayoutOrStyleChange, RenderLayer* updateRoot = 0);
+ void updateCompositingLayers(CompositingUpdateType, RenderLayer* updateRoot = 0);
// This is only used when state changes and we do not exepect a style update or layout to happen soon (e.g. when
// we discover that an iframe is overlapped during painting).
void scheduleCompositingLayerUpdate();
@@ -134,6 +135,9 @@ public:
// Repaint parts of all composited layers that intersect the given absolute rectangle.
void repaintCompositedLayersAbsoluteRect(const IntRect&);
+ // Returns true if the given layer needs it own backing store.
+ bool requiresOwnBackingStore(const RenderLayer*, const RenderLayer* compositingAncestorLayer) const;
+
RenderLayer* rootRenderLayer() const;
GraphicsLayer* rootGraphicsLayer() const;
GraphicsLayer* scrollLayer() const;
@@ -160,8 +164,6 @@ public:
--m_compositedLayerCount;
}
- void didStartAcceleratedAnimation(CSSPropertyID);
-
#if ENABLE(VIDEO)
// Use by RenderVideo to ask if it should try to use accelerated compositing.
bool canAccelerateVideoRendering(RenderVideo*) const;
@@ -197,6 +199,7 @@ public:
virtual void didCommitChangesForLayer(const GraphicsLayer*) const;
bool keepLayersPixelAligned() const;
+ bool acceleratedDrawingEnabled() const { return m_acceleratedDrawingEnabled; }
void deviceOrPageScaleFactorChanged();
@@ -244,18 +247,19 @@ private:
void computeCompositingRequirements(RenderLayer*, OverlapMap*, struct CompositingState&, bool& layersChanged);
// Recurses down the tree, parenting descendant compositing layers and collecting an array of child layers for the current compositing layer.
- void rebuildCompositingLayerTree(RenderLayer*, Vector<GraphicsLayer*>& childGraphicsLayersOfEnclosingLayer);
+ void rebuildCompositingLayerTree(RenderLayer*, Vector<GraphicsLayer*>& childGraphicsLayersOfEnclosingLayer, int depth);
// Recurses down the tree, updating layer geometry only.
- void updateLayerTreeGeometry(RenderLayer*);
+ void updateLayerTreeGeometry(RenderLayer*, int depth);
// Hook compositing layers together
void setCompositingParent(RenderLayer* childLayer, RenderLayer* parentLayer);
void removeCompositedChildren(RenderLayer*);
bool layerHas3DContent(const RenderLayer*) const;
- bool hasNonIdentity3DTransform(RenderObject*) const;
-
+ bool hasNonAffineTransform(RenderObject*) const;
+ bool isRunningAcceleratedTransformAnimation(RenderObject*) const;
+
bool hasAnyAdditionalCompositedLayers(const RenderLayer* rootLayer) const;
void ensureRootLayer();
@@ -295,6 +299,11 @@ private:
bool requiresContentShadowLayer() const;
#endif
+#if !LOG_DISABLED
+ const char* reasonForCompositing(const RenderLayer*);
+ void logLayerInfo(const RenderLayer*, int depth);
+#endif
+
private:
RenderView* m_renderView;
OwnPtr<GraphicsLayer> m_rootContentLayer;
@@ -306,14 +315,12 @@ private:
int m_compositedLayerCount;
bool m_showDebugBorders;
bool m_showRepaintCounter;
+ bool m_acceleratedDrawingEnabled;
bool m_compositingConsultsOverlap;
// When true, we have to wait until layout has happened before we can decide whether to enter compositing mode,
// because only then do we know the final size of plugins and iframes.
- // FIXME: once set, this is never cleared.
- mutable bool m_compositingDependsOnGeometry;
-
- mutable bool m_compositingNeedsUpdate;
+ mutable bool m_reevaluateCompositingAfterLayout;
bool m_compositing;
bool m_compositingLayersNeedRebuild;
@@ -337,8 +344,13 @@ private:
OwnPtr<GraphicsLayer> m_layerForOverhangAreas;
OwnPtr<GraphicsLayer> m_contentShadowLayer;
#endif
-#if PROFILE_LAYER_REBUILD
+
+#if !LOG_DISABLED
int m_rootLayerUpdateCount;
+ int m_obligateCompositedLayerCount; // count of layer that have to be composited.
+ int m_secondaryCompositedLayerCount; // count of layers that have to be composited because of stacking or overlap.
+ double m_obligatoryBackingAreaMegaPixels;
+ double m_secondaryBackingAreaMegaPixels;
#endif
};
diff --git a/Source/WebCore/rendering/RenderLayerFilterInfo.cpp b/Source/WebCore/rendering/RenderLayerFilterInfo.cpp
new file mode 100644
index 000000000..703df638c
--- /dev/null
+++ b/Source/WebCore/rendering/RenderLayerFilterInfo.cpp
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(CSS_FILTERS)
+#include "RenderLayerFilterInfo.h"
+
+#include "FilterEffectRenderer.h"
+#include "RenderLayer.h"
+
+#if ENABLE(CSS_SHADERS)
+#include "CustomFilterOperation.h"
+#include "CustomFilterProgram.h"
+#endif
+
+namespace WebCore {
+
+RenderLayerFilterInfoMap* RenderLayerFilterInfo::s_filterMap = 0;
+
+RenderLayerFilterInfo* RenderLayerFilterInfo::filterInfoForRenderLayer(const RenderLayer* layer)
+{
+ if (!s_filterMap)
+ return 0;
+ RenderLayerFilterInfoMap::iterator iter = s_filterMap->find(layer);
+ return (iter != s_filterMap->end()) ? iter->second : 0;
+}
+
+RenderLayerFilterInfo* RenderLayerFilterInfo::createFilterInfoForRenderLayerIfNeeded(RenderLayer* layer)
+{
+ if (!s_filterMap)
+ s_filterMap = new RenderLayerFilterInfoMap();
+
+ RenderLayerFilterInfoMap::iterator iter = s_filterMap->find(layer);
+ if (iter != s_filterMap->end()) {
+ ASSERT(layer->hasFilterInfo());
+ return iter->second;
+ }
+
+ RenderLayerFilterInfo* filter = new RenderLayerFilterInfo(layer);
+ s_filterMap->set(layer, filter);
+ layer->setHasFilterInfo(true);
+ return filter;
+}
+
+void RenderLayerFilterInfo::removeFilterInfoForRenderLayer(RenderLayer* layer)
+{
+ if (!s_filterMap)
+ return;
+ RenderLayerFilterInfo* filter = s_filterMap->take(layer);
+ if (s_filterMap->isEmpty()) {
+ delete s_filterMap;
+ s_filterMap = 0;
+ }
+ if (!filter) {
+ ASSERT(!layer->hasFilterInfo());
+ return;
+ }
+ layer->setHasFilterInfo(false);
+ delete filter;
+}
+
+RenderLayerFilterInfo::RenderLayerFilterInfo(RenderLayer* layer)
+ : m_layer(layer)
+{
+}
+
+RenderLayerFilterInfo::~RenderLayerFilterInfo()
+{
+#if ENABLE(CSS_SHADERS)
+ removeCustomFilterClients();
+#endif
+}
+
+void RenderLayerFilterInfo::setRenderer(PassRefPtr<FilterEffectRenderer> renderer)
+{
+ m_renderer = renderer;
+}
+
+#if ENABLE(CSS_SHADERS)
+void RenderLayerFilterInfo::notifyCustomFilterProgramLoaded(CustomFilterProgram*)
+{
+ RenderObject* renderer = m_layer->renderer();
+ renderer->node()->setNeedsStyleRecalc(SyntheticStyleChange);
+ renderer->repaint();
+}
+
+void RenderLayerFilterInfo::updateCustomFilterClients(const FilterOperations& operations)
+{
+ if (!operations.size()) {
+ removeCustomFilterClients();
+ return;
+ }
+ CustomFilterProgramList cachedCustomFilterPrograms;
+ for (size_t i = 0; i < operations.size(); ++i) {
+ const FilterOperation* filterOperation = operations.at(i);
+ if (filterOperation->getOperationType() != FilterOperation::CUSTOM)
+ continue;
+ const CustomFilterOperation* customFilterOperation = static_cast<const CustomFilterOperation*>(filterOperation);
+ RefPtr<CustomFilterProgram> program = customFilterOperation->program();
+ cachedCustomFilterPrograms.append(program);
+ program->addClient(this);
+ }
+ // Remove the old clients here, after we've added the new ones, so that we don't flicker if some shaders are unchanged.
+ removeCustomFilterClients();
+ m_cachedCustomFilterPrograms.swap(cachedCustomFilterPrograms);
+}
+
+void RenderLayerFilterInfo::removeCustomFilterClients()
+{
+ for (size_t i = 0; i < m_cachedCustomFilterPrograms.size(); ++i)
+ m_cachedCustomFilterPrograms.at(i)->removeClient(this);
+ m_cachedCustomFilterPrograms.clear();
+}
+#endif
+
+} // namespace WebCore
+
+#endif // ENABLE(CSS_FILTERS)
diff --git a/Source/WebCore/rendering/RenderLayerFilterInfo.h b/Source/WebCore/rendering/RenderLayerFilterInfo.h
new file mode 100644
index 000000000..86a9c1393
--- /dev/null
+++ b/Source/WebCore/rendering/RenderLayerFilterInfo.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef RenderLayerFilterInfo_h
+#define RenderLayerFilterInfo_h
+
+#if ENABLE(CSS_FILTERS)
+
+#include "LayoutTypes.h"
+#include <wtf/HashMap.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefPtr.h>
+
+#if ENABLE(CSS_SHADERS)
+#include "CustomFilterProgramClient.h"
+#endif
+
+namespace WebCore {
+
+class FilterEffectRenderer;
+class FilterOperations;
+class RenderLayer;
+class RenderLayerFilterInfo;
+
+typedef HashMap<const RenderLayer*, RenderLayerFilterInfo*> RenderLayerFilterInfoMap;
+
+class RenderLayerFilterInfo
+#if ENABLE(CSS_SHADERS)
+ : public CustomFilterProgramClient
+#endif
+{
+public:
+ static RenderLayerFilterInfo* filterInfoForRenderLayer(const RenderLayer*);
+ static RenderLayerFilterInfo* createFilterInfoForRenderLayerIfNeeded(RenderLayer*);
+ static void removeFilterInfoForRenderLayer(RenderLayer*);
+
+ const LayoutRect& dirtySourceRect() const { return m_dirtySourceRect; }
+ void expandDirtySourceRect(const LayoutRect& rect) { m_dirtySourceRect.unite(rect); }
+ void resetDirtySourceRect() { m_dirtySourceRect = LayoutRect(); }
+
+ FilterEffectRenderer* renderer() const { return m_renderer.get(); }
+ void setRenderer(PassRefPtr<FilterEffectRenderer>);
+
+#if ENABLE(CSS_SHADERS)
+ // Implementation of the CustomFilterProgramClient interface.
+ virtual void notifyCustomFilterProgramLoaded(CustomFilterProgram*);
+
+ void updateCustomFilterClients(const FilterOperations&);
+ void removeCustomFilterClients();
+#endif
+
+
+private:
+ RenderLayerFilterInfo(RenderLayer*);
+ ~RenderLayerFilterInfo();
+
+ RenderLayer* m_layer;
+
+ RefPtr<FilterEffectRenderer> m_renderer;
+ LayoutRect m_dirtySourceRect;
+
+#if ENABLE(CSS_SHADERS)
+ typedef Vector<RefPtr<CustomFilterProgram> > CustomFilterProgramList;
+ CustomFilterProgramList m_cachedCustomFilterPrograms;
+#endif
+
+ static RenderLayerFilterInfoMap* s_filterMap;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(CSS_FILTERS)
+
+#endif // RenderLayerFilterInfo_h
diff --git a/Source/WebCore/rendering/RenderLineBoxList.cpp b/Source/WebCore/rendering/RenderLineBoxList.cpp
index 6040e0e73..df8a545f3 100644
--- a/Source/WebCore/rendering/RenderLineBoxList.cpp
+++ b/Source/WebCore/rendering/RenderLineBoxList.cpp
@@ -146,16 +146,16 @@ void RenderLineBoxList::dirtyLineBoxes()
curr->dirtyLineBoxes();
}
-bool RenderLineBoxList::rangeIntersectsRect(RenderBoxModelObject* renderer, int logicalTop, int logicalBottom, const IntRect& rect, const IntPoint& offset) const
+bool RenderLineBoxList::rangeIntersectsRect(RenderBoxModelObject* renderer, LayoutUnit logicalTop, LayoutUnit logicalBottom, const LayoutRect& rect, const LayoutPoint& offset) const
{
RenderBox* block;
if (renderer->isBox())
block = toRenderBox(renderer);
else
block = renderer->containingBlock();
- int physicalStart = block->flipForWritingMode(logicalTop);
- int physicalEnd = block->flipForWritingMode(logicalBottom);
- int physicalExtent = abs(physicalEnd - physicalStart);
+ LayoutUnit physicalStart = block->flipForWritingMode(logicalTop);
+ LayoutUnit physicalEnd = block->flipForWritingMode(logicalBottom);
+ LayoutUnit physicalExtent = absoluteValue(physicalEnd - physicalStart);
physicalStart = min(physicalStart, physicalEnd);
if (renderer->style()->isHorizontalWritingMode()) {
@@ -191,11 +191,11 @@ bool RenderLineBoxList::anyLineIntersectsRect(RenderBoxModelObject* renderer, co
return rangeIntersectsRect(renderer, logicalTop, logicalBottom, rect, offset);
}
-bool RenderLineBoxList::lineIntersectsDirtyRect(RenderBoxModelObject* renderer, InlineFlowBox* box, const PaintInfo& paintInfo, const IntPoint& offset) const
+bool RenderLineBoxList::lineIntersectsDirtyRect(RenderBoxModelObject* renderer, InlineFlowBox* box, const PaintInfo& paintInfo, const LayoutPoint& offset) const
{
RootInlineBox* root = box->root();
- int logicalTop = min(box->logicalTopVisualOverflow(root->lineTop()), root->selectionTop()) - renderer->maximalOutlineSize(paintInfo.phase);
- int logicalBottom = box->logicalBottomVisualOverflow(root->lineBottom()) + renderer->maximalOutlineSize(paintInfo.phase);
+ LayoutUnit logicalTop = min<LayoutUnit>(box->logicalTopVisualOverflow(root->lineTop()), root->selectionTop()) - renderer->maximalOutlineSize(paintInfo.phase);
+ LayoutUnit logicalBottom = box->logicalBottomVisualOverflow(root->lineBottom()) + renderer->maximalOutlineSize(paintInfo.phase);
return rangeIntersectsRect(renderer, logicalTop, logicalBottom, paintInfo.rect, offset);
}
@@ -245,7 +245,7 @@ void RenderLineBoxList::paint(RenderBoxModelObject* renderer, PaintInfo& paintIn
if (bottomForPaginationCheck - topForPaginationCheck <= v->printRect().height()) {
if (paintOffset.y() + bottomForPaginationCheck > v->printRect().maxY()) {
if (RootInlineBox* nextRootBox = curr->root()->nextRootBox())
- bottomForPaginationCheck = min(bottomForPaginationCheck, min(nextRootBox->logicalTopVisualOverflow(), nextRootBox->lineTop()));
+ bottomForPaginationCheck = min(bottomForPaginationCheck, min<LayoutUnit>(nextRootBox->logicalTopVisualOverflow(), nextRootBox->lineTop()));
}
if (paintOffset.y() + bottomForPaginationCheck > v->printRect().maxY()) {
if (paintOffset.y() + topForPaginationCheck < v->truncatedAt())
@@ -321,9 +321,9 @@ void RenderLineBoxList::dirtyLinesFromChangedChild(RenderObject* container, Rend
if (!firstBox) {
// For an empty inline, go ahead and propagate the check up to our parent, unless the parent
// is already dirty.
- if (container->isInline() && !container->parent()->selfNeedsLayout()) {
+ if (container->isInline() && !container->parent()->ancestorLineBoxDirty()) {
container->parent()->dirtyLinesFromChangedChild(container);
- container->setNeedsLayout(true); // Mark the container as needing layout to avoid dirtying the same lines again across multiple destroy() calls of the same subtree.
+ container->setAncestorLineBoxDirty(); // Mark the container to avoid dirtying the same lines again across multiple destroy() calls of the same subtree.
}
return;
}
@@ -361,9 +361,9 @@ void RenderLineBoxList::dirtyLinesFromChangedChild(RenderObject* container, Rend
// we won't find a previous sibling, but firstBox can be pointing to a following sibling.
// This isn't good enough, since we won't locate the root line box that encloses the removed
// <br>. We have to just over-invalidate a bit and go up to our parent.
- if (!inlineContainer->parent()->selfNeedsLayout()) {
+ if (!inlineContainer->parent()->ancestorLineBoxDirty()) {
inlineContainer->parent()->dirtyLinesFromChangedChild(inlineContainer);
- inlineContainer->setNeedsLayout(true); // Mark the container as needing layout to avoid dirtying the same lines again across multiple destroy() calls of the same subtree.
+ inlineContainer->setAncestorLineBoxDirty(); // Mark the container to avoid dirtying the same lines again across multiple destroy() calls of the same subtree.
}
return;
}
diff --git a/Source/WebCore/rendering/RenderListBox.cpp b/Source/WebCore/rendering/RenderListBox.cpp
index e9b0ede36..8cb7d7bb4 100644
--- a/Source/WebCore/rendering/RenderListBox.cpp
+++ b/Source/WebCore/rendering/RenderListBox.cpp
@@ -32,7 +32,6 @@
#include "AXObjectCache.h"
#include "CSSFontSelector.h"
-#include "CSSStyleSelector.h"
#include "Document.h"
#include "DocumentEventQueue.h"
#include "EventHandler.h"
@@ -58,6 +57,7 @@
#include "Scrollbar.h"
#include "ScrollbarTheme.h"
#include "SpatialNavigation.h"
+#include "StyleResolver.h"
#include <math.h>
using namespace std;
@@ -125,7 +125,7 @@ void RenderListBox::updateFromElement()
FontDescription d = itemFont.fontDescription();
d.setWeight(d.bolderWeight());
itemFont = Font(d, itemFont.letterSpacing(), itemFont.wordSpacing());
- itemFont.update(document()->styleSelector()->fontSelector());
+ itemFont.update(document()->styleResolver()->fontSelector());
}
if (!text.isEmpty()) {
@@ -345,7 +345,7 @@ void RenderListBox::addFocusRingRects(Vector<IntRect>& rects, const LayoutPoint&
void RenderListBox::paintScrollbar(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
if (m_vBar) {
- LayoutRect scrollRect(paintOffset.x() + width() - borderRight() - m_vBar->width(),
+ IntRect scrollRect = pixelSnappedIntRect(paintOffset.x() + width() - borderRight() - m_vBar->width(),
paintOffset.y() + borderTop(),
m_vBar->width(),
height() - (borderTop() + borderBottom()));
@@ -409,7 +409,7 @@ void RenderListBox::paintItemForeground(PaintInfo& paintInfo, const LayoutPoint&
unsigned length = itemText.length();
const UChar* string = itemText.characters();
- TextRun textRun(string, length, false, 0, 0, TextRun::AllowTrailingExpansion, itemStyle->direction(), isOverride(itemStyle->unicodeBidi()), TextRun::NoRounding);
+ TextRun textRun(string, length, false, 0, 0, TextRun::AllowTrailingExpansion, itemStyle->direction(), isOverride(itemStyle->unicodeBidi()), true, TextRun::NoRounding);
Font itemFont = style()->font();
LayoutRect r = itemBoundingBoxRect(paintOffset, listIndex);
r.move(itemOffsetForAlignment(textRun, itemStyle, itemFont, r));
@@ -418,11 +418,11 @@ void RenderListBox::paintItemForeground(PaintInfo& paintInfo, const LayoutPoint&
FontDescription d = itemFont.fontDescription();
d.setWeight(d.bolderWeight());
itemFont = Font(d, itemFont.letterSpacing(), itemFont.wordSpacing());
- itemFont.update(document()->styleSelector()->fontSelector());
+ itemFont.update(document()->styleResolver()->fontSelector());
}
// Draw the item text
- paintInfo.context->drawBidiText(itemFont, textRun, r.location());
+ paintInfo.context->drawBidiText(itemFont, textRun, roundedIntPoint(r.location()));
}
void RenderListBox::paintItemBackground(PaintInfo& paintInfo, const LayoutPoint& paintOffset, int listIndex)
@@ -444,7 +444,7 @@ void RenderListBox::paintItemBackground(PaintInfo& paintInfo, const LayoutPoint&
ColorSpace colorSpace = element->renderStyle() ? element->renderStyle()->colorSpace() : style()->colorSpace();
LayoutRect itemRect = itemBoundingBoxRect(paintOffset, listIndex);
itemRect.intersect(controlClipRect(paintOffset));
- paintInfo.context->fillRect(itemRect, backColor, colorSpace);
+ paintInfo.context->fillRect(pixelSnappedIntRect(itemRect), backColor, colorSpace);
}
}
@@ -490,7 +490,7 @@ void RenderListBox::panScroll(const IntPoint& panStartMousePosition)
// FIXME: This doesn't work correctly with transforms.
FloatPoint absOffset = localToAbsolute();
- IntPoint currentMousePosition = roundedIntPoint(frame()->eventHandler()->currentMousePosition());
+ IntPoint currentMousePosition = frame()->eventHandler()->currentMousePosition();
// We need to check if the current mouse position is out of the window. When the mouse is out of the window, the position is incoherent
static IntPoint previousMousePosition;
if (currentMousePosition.y() < 0)
diff --git a/Source/WebCore/rendering/RenderListItem.cpp b/Source/WebCore/rendering/RenderListItem.cpp
index 6c0677ed8..3e6a7dcae 100644
--- a/Source/WebCore/rendering/RenderListItem.cpp
+++ b/Source/WebCore/rendering/RenderListItem.cpp
@@ -381,7 +381,7 @@ void RenderListItem::positionListMarker()
void RenderListItem::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
- if (!logicalHeight())
+ if (!logicalHeight() && hasOverflowClip())
return;
RenderBlock::paint(paintInfo, paintOffset);
diff --git a/Source/WebCore/rendering/RenderListMarker.cpp b/Source/WebCore/rendering/RenderListMarker.cpp
index 8c804549e..0d2f48dd5 100644
--- a/Source/WebCore/rendering/RenderListMarker.cpp
+++ b/Source/WebCore/rendering/RenderListMarker.cpp
@@ -1090,16 +1090,16 @@ bool RenderListMarker::isImage() const
return m_image && !m_image->errorOccurred();
}
-IntRect RenderListMarker::localSelectionRect()
+LayoutRect RenderListMarker::localSelectionRect()
{
InlineBox* box = inlineBoxWrapper();
if (!box)
- return IntRect(IntPoint(), size());
+ return LayoutRect(LayoutPoint(), size());
RootInlineBox* root = m_inlineBoxWrapper->root();
- int newLogicalTop = root->block()->style()->isFlippedBlocksWritingMode() ? m_inlineBoxWrapper->logicalBottom() - root->selectionBottom() : root->selectionTop() - m_inlineBoxWrapper->logicalTop();
+ LayoutUnit newLogicalTop = root->block()->style()->isFlippedBlocksWritingMode() ? m_inlineBoxWrapper->logicalBottom() - root->selectionBottom() : root->selectionTop() - m_inlineBoxWrapper->logicalTop();
if (root->block()->style()->isHorizontalWritingMode())
- return IntRect(0, newLogicalTop, width(), root->selectionHeight());
- return IntRect(newLogicalTop, 0, root->selectionHeight(), height());
+ return LayoutRect(0, newLogicalTop, width(), root->selectionHeight());
+ return LayoutRect(newLogicalTop, 0, root->selectionHeight(), height());
}
void RenderListMarker::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
@@ -1110,18 +1110,18 @@ void RenderListMarker::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffse
if (style()->visibility() != VISIBLE)
return;
- IntPoint boxOrigin(paintOffset + location());
+ LayoutPoint boxOrigin(paintOffset + location());
LayoutRect overflowRect(visualOverflowRect());
overflowRect.moveBy(boxOrigin);
overflowRect.inflate(maximalOutlineSize(paintInfo.phase));
- if (!paintInfo.rect.intersects(overflowRect))
+ if (!paintInfo.rect.intersects(pixelSnappedIntRect(overflowRect)))
return;
- LayoutRect box(boxOrigin, LayoutSize(width(), height()));
+ LayoutRect box(boxOrigin, size());
- LayoutRect marker = getRelativeMarkerRect();
- marker.moveBy(boxOrigin);
+ IntRect marker = getRelativeMarkerRect();
+ marker.moveBy(roundedIntPoint(boxOrigin));
GraphicsContext* context = paintInfo.context;
@@ -1134,7 +1134,7 @@ void RenderListMarker::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffse
if (selectionState() != SelectionNone) {
LayoutRect selRect = localSelectionRect();
selRect.moveBy(boxOrigin);
- context->fillRect(selRect, selectionBackgroundColor(), style()->colorSpace());
+ context->fillRect(pixelSnappedIntRect(selRect), selectionBackgroundColor(), style()->colorSpace());
}
return;
}
@@ -1148,7 +1148,7 @@ void RenderListMarker::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffse
if (selectionState() != SelectionNone) {
LayoutRect selRect = localSelectionRect();
selRect.moveBy(boxOrigin);
- context->fillRect(selRect, selectionBackgroundColor(), style()->colorSpace());
+ context->fillRect(pixelSnappedIntRect(selRect), selectionBackgroundColor(), style()->colorSpace());
}
const Color color(style()->visitedDependentColor(CSSPropertyColor));
@@ -1258,16 +1258,16 @@ void RenderListMarker::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffse
GraphicsContextStateSaver stateSaver(*context, false);
if (!style()->isHorizontalWritingMode()) {
- marker.moveBy(-boxOrigin);
+ marker.moveBy(roundedIntPoint(-boxOrigin));
marker = marker.transposedRect();
- marker.move(box.x(), box.y() - logicalHeight());
+ marker.moveBy(IntPoint(roundToInt(box.x()), roundToInt(box.y() - logicalHeight())));
stateSaver.save();
context->translate(marker.x(), marker.maxY());
context->rotate(static_cast<float>(deg2rad(90.)));
context->translate(-marker.x(), -marker.maxY());
}
- LayoutPoint textOrigin = LayoutPoint(marker.x(), marker.y() + style()->fontMetrics().ascent());
+ IntPoint textOrigin = IntPoint(marker.x(), marker.y() + style()->fontMetrics().ascent());
if (type == Asterisks || type == Footnotes)
context->drawText(font, textRun, textOrigin);
@@ -1286,14 +1286,14 @@ void RenderListMarker::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffse
const UChar suffix = listMarkerSuffix(type, m_listItem->value());
if (style()->isLeftToRightDirection()) {
- LayoutUnit width = font.width(textRun);
+ int width = font.width(textRun);
context->drawText(font, textRun, textOrigin);
UChar suffixSpace[2] = { suffix, ' ' };
context->drawText(font, RenderBlock::constructTextRun(this, font, suffixSpace, 2, style()), textOrigin + IntSize(width, 0));
} else {
UChar spaceSuffix[2] = { ' ', suffix };
TextRun spaceSuffixRun = RenderBlock::constructTextRun(this, font, spaceSuffix, 2, style());
- LayoutUnit width = font.width(spaceSuffixRun);
+ int width = font.width(spaceSuffixRun);
context->drawText(font, spaceSuffixRun, textOrigin);
context->drawText(font, textRun, textOrigin + IntSize(width, 0));
}
@@ -1349,8 +1349,8 @@ void RenderListMarker::computePreferredLogicalWidths()
if (isImage()) {
// FIXME: This is a somewhat arbitrary width. Generated images for markers really won't become particularly useful
// until we support the CSS3 marker pseudoclass to allow control over the width and height of the marker box.
- LayoutUnit bulletWidth = fontMetrics.ascent() / 2;
- m_image->setContainerSizeForRenderer(this, LayoutSize(bulletWidth, bulletWidth), style()->effectiveZoom());
+ int bulletWidth = fontMetrics.ascent() / 2;
+ m_image->setContainerSizeForRenderer(this, IntSize(bulletWidth, bulletWidth), style()->effectiveZoom());
LayoutSize imageSize = m_image->imageSize(this, style()->effectiveZoom());
m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = style()->isHorizontalWritingMode() ? imageSize.width() : imageSize.height();
setPreferredLogicalWidthsDirty(false);
@@ -1473,8 +1473,8 @@ void RenderListMarker::updateMargins()
{
const FontMetrics& fontMetrics = style()->fontMetrics();
- int marginStart = 0;
- int marginEnd = 0;
+ LayoutUnit marginStart = 0;
+ LayoutUnit marginEnd = 0;
if (isInside()) {
if (isImage())
@@ -1504,7 +1504,7 @@ void RenderListMarker::updateMargins()
case NoneListStyle:
break;
default:
- marginStart = m_text.isEmpty() ? 0 : -minPreferredLogicalWidth() - offset / 2;
+ marginStart = m_text.isEmpty() ? ZERO_LAYOUT_UNIT : -minPreferredLogicalWidth() - offset / 2;
}
}
marginEnd = -marginStart - minPreferredLogicalWidth();
diff --git a/Source/WebCore/rendering/RenderListMarker.h b/Source/WebCore/rendering/RenderListMarker.h
index 50e666dbf..d88d922b0 100644
--- a/Source/WebCore/rendering/RenderListMarker.h
+++ b/Source/WebCore/rendering/RenderListMarker.h
@@ -74,7 +74,7 @@ private:
virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
IntRect getRelativeMarkerRect();
- IntRect localSelectionRect();
+ LayoutRect localSelectionRect();
String m_text;
RefPtr<StyleImage> m_image;
diff --git a/Source/WebCore/rendering/RenderMarquee.cpp b/Source/WebCore/rendering/RenderMarquee.cpp
index fe5dbaa22..db082538f 100644
--- a/Source/WebCore/rendering/RenderMarquee.cpp
+++ b/Source/WebCore/rendering/RenderMarquee.cpp
@@ -115,8 +115,8 @@ int RenderMarquee::computePosition(EMarqueeDirection dir, bool stopAtContentEdge
RenderStyle* s = box->style();
if (isHorizontal()) {
bool ltr = s->isLeftToRightDirection();
- int clientWidth = box->clientWidth();
- int contentWidth = ltr ? box->maxPreferredLogicalWidth() : box->minPreferredLogicalWidth();
+ LayoutUnit clientWidth = box->clientWidth();
+ LayoutUnit contentWidth = ltr ? box->maxPreferredLogicalWidth() : box->minPreferredLogicalWidth();
if (ltr)
contentWidth += (box->paddingRight() - box->borderLeft());
else {
@@ -125,13 +125,13 @@ int RenderMarquee::computePosition(EMarqueeDirection dir, bool stopAtContentEdge
}
if (dir == MRIGHT) {
if (stopAtContentEdge)
- return max(zeroLayoutUnit, ltr ? (contentWidth - clientWidth) : (clientWidth - contentWidth));
+ return max(ZERO_LAYOUT_UNIT, ltr ? (contentWidth - clientWidth) : (clientWidth - contentWidth));
else
return ltr ? contentWidth : clientWidth;
}
else {
if (stopAtContentEdge)
- return min(zeroLayoutUnit, ltr ? (contentWidth - clientWidth) : (clientWidth - contentWidth));
+ return min(ZERO_LAYOUT_UNIT, ltr ? (contentWidth - clientWidth) : (clientWidth - contentWidth));
else
return ltr ? -clientWidth : -contentWidth;
}
@@ -289,7 +289,7 @@ void RenderMarquee::timerFired(Timer<RenderMarquee>*)
}
bool positive = range > 0;
int clientSize = (isHorizontal() ? m_layer->renderBox()->clientWidth() : m_layer->renderBox()->clientHeight());
- int increment = abs(m_layer->renderer()->style()->marqueeIncrement().calcValue(clientSize));
+ int increment = abs(intValueForLength(m_layer->renderer()->style()->marqueeIncrement(), clientSize));
int currentPos = (isHorizontal() ? m_layer->scrollXOffset() : m_layer->scrollYOffset());
newPos = currentPos + (addIncrement ? increment : -increment);
if (positive)
diff --git a/Source/WebCore/rendering/RenderMedia.cpp b/Source/WebCore/rendering/RenderMedia.cpp
index be4adde7b..9af648b02 100644
--- a/Source/WebCore/rendering/RenderMedia.cpp
+++ b/Source/WebCore/rendering/RenderMedia.cpp
@@ -77,13 +77,17 @@ void RenderMedia::layout()
controlsRenderer->setLocation(LayoutPoint(borderLeft(), borderTop()) + LayoutSize(paddingLeft(), paddingTop()));
controlsRenderer->style()->setHeight(Length(newSize.height(), Fixed));
controlsRenderer->style()->setWidth(Length(newSize.width(), Fixed));
- controlsRenderer->setNeedsLayout(true, false);
+ controlsRenderer->setNeedsLayout(true, MarkOnlyThis);
controlsRenderer->layout();
setChildNeedsLayout(false);
statePusher.pop();
}
+void RenderMedia::paintReplaced(PaintInfo&, const LayoutPoint&)
+{
+}
+
} // namespace WebCore
#endif
diff --git a/Source/WebCore/rendering/RenderMedia.h b/Source/WebCore/rendering/RenderMedia.h
index 54e625af3..abcc3b64b 100644
--- a/Source/WebCore/rendering/RenderMedia.h
+++ b/Source/WebCore/rendering/RenderMedia.h
@@ -56,6 +56,7 @@ private:
virtual const char* renderName() const { return "RenderMedia"; }
virtual bool isMedia() const { return true; }
virtual bool isImage() const { return false; }
+ virtual void paintReplaced(PaintInfo&, const LayoutPoint&);
virtual bool requiresForcedStyleRecalcPropagation() const { return true; }
diff --git a/Source/WebCore/rendering/RenderMediaControls.cpp b/Source/WebCore/rendering/RenderMediaControls.cpp
index f791274e7..3ecd86748 100644
--- a/Source/WebCore/rendering/RenderMediaControls.cpp
+++ b/Source/WebCore/rendering/RenderMediaControls.cpp
@@ -119,83 +119,87 @@ bool RenderMediaControls::paintMediaControlsPart(MediaControlElementType part, R
GraphicsContextStateSaver stateSaver(*paintInfo.context);
switch (part) {
- case MediaFullscreenButton:
- wkDrawMediaUIPart(WKMediaUIPartFullscreenButton, themeStyle, paintInfo.context->platformContext(), r, determineState(o));
- break;
- case MediaShowClosedCaptionsButton:
- case MediaHideClosedCaptionsButton:
- if (MediaControlToggleClosedCaptionsButtonElement* btn = static_cast<MediaControlToggleClosedCaptionsButtonElement*>(o->node())) {
- bool captionsVisible = btn->displayType() == MediaHideClosedCaptionsButton;
- wkDrawMediaUIPart(captionsVisible ? WKMediaUIPartHideClosedCaptionsButton : WKMediaUIPartShowClosedCaptionsButton, themeStyle, paintInfo.context->platformContext(), r, determineState(o));
- }
- break;
- case MediaMuteButton:
- case MediaUnMuteButton:
- if (MediaControlMuteButtonElement* btn = static_cast<MediaControlMuteButtonElement*>(o->node())) {
- bool audioEnabled = btn->displayType() == MediaMuteButton;
- wkDrawMediaUIPart(audioEnabled ? WKMediaUIPartMuteButton : WKMediaUIPartUnMuteButton, themeStyle, paintInfo.context->platformContext(), r, determineState(o));
- }
- break;
- case MediaPauseButton:
- case MediaPlayButton:
- if (MediaControlPlayButtonElement* btn = static_cast<MediaControlPlayButtonElement*>(o->node())) {
- bool canPlay = btn->displayType() == MediaPlayButton;
- wkDrawMediaUIPart(canPlay ? WKMediaUIPartPlayButton : WKMediaUIPartPauseButton, themeStyle, paintInfo.context->platformContext(), r, determineState(o));
- }
- break;
- case MediaRewindButton:
- wkDrawMediaUIPart(WKMediaUIPartRewindButton, themeStyle, paintInfo.context->platformContext(), r, determineState(o));
- break;
- case MediaReturnToRealtimeButton:
- wkDrawMediaUIPart(WKMediaUIPartSeekToRealtimeButton, themeStyle, paintInfo.context->platformContext(), r, determineState(o));
- break;
- case MediaSeekBackButton:
- wkDrawMediaUIPart(WKMediaUIPartSeekBackButton, themeStyle, paintInfo.context->platformContext(), r, determineState(o));
- break;
- case MediaSeekForwardButton:
- wkDrawMediaUIPart(WKMediaUIPartSeekForwardButton, themeStyle, paintInfo.context->platformContext(), r, determineState(o));
- break;
- case MediaSlider: {
- if (HTMLMediaElement* mediaElement = toParentMediaElement(o)) {
- FloatRect unzoomedRect = getUnzoomedRectAndAdjustCurrentContext(o, paintInfo, r);
- wkDrawMediaSliderTrack(themeStyle, paintInfo.context->platformContext(), unzoomedRect, mediaElement->percentLoaded() * mediaElement->duration(), mediaElement->currentTime(), mediaElement->duration(), determineState(o));
- }
- break;
+ case MediaEnterFullscreenButton:
+ case MediaExitFullscreenButton:
+ if (MediaControlFullscreenButtonElement* btn = static_cast<MediaControlFullscreenButtonElement*>(o->node())) {
+ bool enterButton = btn->displayType() == MediaEnterFullscreenButton;
+ wkDrawMediaUIPart(enterButton ? WKMediaUIPartFullscreenButton : WKMediaUIPartExitFullscreenButton, themeStyle, paintInfo.context->platformContext(), r, determineState(o));
}
- case MediaSliderThumb:
- wkDrawMediaUIPart(WKMediaUIPartTimelineSliderThumb, themeStyle, paintInfo.context->platformContext(), r, determineState(o));
- break;
- case MediaVolumeSliderContainer:
- wkDrawMediaUIPart(WKMediaUIPartVolumeSliderContainer, themeStyle, paintInfo.context->platformContext(), r, determineState(o));
- break;
- case MediaVolumeSlider:
- wkDrawMediaUIPart(WKMediaUIPartVolumeSlider, themeStyle, paintInfo.context->platformContext(), r, determineState(o));
- break;
- case MediaVolumeSliderThumb:
- wkDrawMediaUIPart(WKMediaUIPartVolumeSliderThumb, themeStyle, paintInfo.context->platformContext(), r, determineState(o));
- break;
- case MediaFullScreenVolumeSlider:
- wkDrawMediaUIPart(WKMediaUIPartFullScreenVolumeSlider, themeStyle, paintInfo.context->platformContext(), r, determineState(o));
- break;
- case MediaFullScreenVolumeSliderThumb:
- wkDrawMediaUIPart(WKMediaUIPartFullScreenVolumeSliderThumb, themeStyle, paintInfo.context->platformContext(), r, determineState(o));
- break;
- case MediaTimelineContainer:
- wkDrawMediaUIPart(WKMediaUIPartBackground, themeStyle, paintInfo.context->platformContext(), r, determineState(o));
- break;
- case MediaCurrentTimeDisplay:
- ASSERT_NOT_REACHED();
- break;
- case MediaTimeRemainingDisplay:
- ASSERT_NOT_REACHED();
- break;
- case MediaControlsPanel:
- ASSERT_NOT_REACHED();
- case MediaTextTrackDisplayContainer:
- case MediaTextTrackDisplay:
- ASSERT_NOT_REACHED();
- break;
+ break;
+ case MediaShowClosedCaptionsButton:
+ case MediaHideClosedCaptionsButton:
+ if (MediaControlToggleClosedCaptionsButtonElement* btn = static_cast<MediaControlToggleClosedCaptionsButtonElement*>(o->node())) {
+ bool captionsVisible = btn->displayType() == MediaHideClosedCaptionsButton;
+ wkDrawMediaUIPart(captionsVisible ? WKMediaUIPartHideClosedCaptionsButton : WKMediaUIPartShowClosedCaptionsButton, themeStyle, paintInfo.context->platformContext(), r, determineState(o));
+ }
+ break;
+ case MediaMuteButton:
+ case MediaUnMuteButton:
+ if (MediaControlMuteButtonElement* btn = static_cast<MediaControlMuteButtonElement*>(o->node())) {
+ bool audioEnabled = btn->displayType() == MediaMuteButton;
+ wkDrawMediaUIPart(audioEnabled ? WKMediaUIPartMuteButton : WKMediaUIPartUnMuteButton, themeStyle, paintInfo.context->platformContext(), r, determineState(o));
+ }
+ break;
+ case MediaPauseButton:
+ case MediaPlayButton:
+ if (MediaControlPlayButtonElement* btn = static_cast<MediaControlPlayButtonElement*>(o->node())) {
+ bool canPlay = btn->displayType() == MediaPlayButton;
+ wkDrawMediaUIPart(canPlay ? WKMediaUIPartPlayButton : WKMediaUIPartPauseButton, themeStyle, paintInfo.context->platformContext(), r, determineState(o));
+ }
+ break;
+ case MediaRewindButton:
+ wkDrawMediaUIPart(WKMediaUIPartRewindButton, themeStyle, paintInfo.context->platformContext(), r, determineState(o));
+ break;
+ case MediaReturnToRealtimeButton:
+ wkDrawMediaUIPart(WKMediaUIPartSeekToRealtimeButton, themeStyle, paintInfo.context->platformContext(), r, determineState(o));
+ break;
+ case MediaSeekBackButton:
+ wkDrawMediaUIPart(WKMediaUIPartSeekBackButton, themeStyle, paintInfo.context->platformContext(), r, determineState(o));
+ break;
+ case MediaSeekForwardButton:
+ wkDrawMediaUIPart(WKMediaUIPartSeekForwardButton, themeStyle, paintInfo.context->platformContext(), r, determineState(o));
+ break;
+ case MediaSlider: {
+ if (HTMLMediaElement* mediaElement = toParentMediaElement(o)) {
+ FloatRect unzoomedRect = getUnzoomedRectAndAdjustCurrentContext(o, paintInfo, r);
+ wkDrawMediaSliderTrack(themeStyle, paintInfo.context->platformContext(), unzoomedRect, mediaElement->percentLoaded() * mediaElement->duration(), mediaElement->currentTime(), mediaElement->duration(), determineState(o));
+ }
+ break;
}
+ case MediaSliderThumb:
+ wkDrawMediaUIPart(WKMediaUIPartTimelineSliderThumb, themeStyle, paintInfo.context->platformContext(), r, determineState(o));
+ break;
+ case MediaVolumeSliderContainer:
+ wkDrawMediaUIPart(WKMediaUIPartVolumeSliderContainer, themeStyle, paintInfo.context->platformContext(), r, determineState(o));
+ break;
+ case MediaVolumeSlider:
+ wkDrawMediaUIPart(WKMediaUIPartVolumeSlider, themeStyle, paintInfo.context->platformContext(), r, determineState(o));
+ break;
+ case MediaVolumeSliderThumb:
+ wkDrawMediaUIPart(WKMediaUIPartVolumeSliderThumb, themeStyle, paintInfo.context->platformContext(), r, determineState(o));
+ break;
+ case MediaFullScreenVolumeSlider:
+ wkDrawMediaUIPart(WKMediaUIPartFullScreenVolumeSlider, themeStyle, paintInfo.context->platformContext(), r, determineState(o));
+ break;
+ case MediaFullScreenVolumeSliderThumb:
+ wkDrawMediaUIPart(WKMediaUIPartFullScreenVolumeSliderThumb, themeStyle, paintInfo.context->platformContext(), r, determineState(o));
+ break;
+ case MediaTimelineContainer:
+ wkDrawMediaUIPart(WKMediaUIPartBackground, themeStyle, paintInfo.context->platformContext(), r, determineState(o));
+ break;
+ case MediaCurrentTimeDisplay:
+ ASSERT_NOT_REACHED();
+ break;
+ case MediaTimeRemainingDisplay:
+ ASSERT_NOT_REACHED();
+ break;
+ case MediaControlsPanel:
+ ASSERT_NOT_REACHED();
+ case MediaTextTrackDisplayContainer:
+ case MediaTextTrackDisplay:
+ ASSERT_NOT_REACHED();
+ break;
+}
return false;
}
@@ -208,10 +212,10 @@ IntPoint RenderMediaControls::volumeSliderOffsetFromMuteButton(RenderBox* muteBu
static const int yOffset = 5;
float zoomLevel = muteButtonBox->style()->effectiveZoom();
- int y = yOffset * zoomLevel + muteButtonBox->offsetHeight() - size.height();
- FloatPoint absPoint = muteButtonBox->localToAbsolute(FloatPoint(muteButtonBox->offsetLeft(), y), true, true);
+ int y = yOffset * zoomLevel + muteButtonBox->pixelSnappedOffsetHeight() - size.height();
+ FloatPoint absPoint = muteButtonBox->localToAbsolute(FloatPoint(muteButtonBox->pixelSnappedOffsetLeft(), y), true, true);
if (absPoint.y() < 0)
- y = muteButtonBox->height();
+ y = muteButtonBox->pixelSnappedHeight();
return IntPoint(xOffset * zoomLevel, y);
}
diff --git a/Source/WebCore/rendering/RenderMediaControlsChromium.cpp b/Source/WebCore/rendering/RenderMediaControlsChromium.cpp
index 66b088260..89383c0d1 100644
--- a/Source/WebCore/rendering/RenderMediaControlsChromium.cpp
+++ b/Source/WebCore/rendering/RenderMediaControlsChromium.cpp
@@ -267,7 +267,8 @@ bool RenderMediaControlsChromium::paintMediaControlsPart(MediaControlElementType
return paintMediaVolumeSliderThumb(object, paintInfo, rect);
case MediaTimelineContainer:
return paintMediaTimelineContainer(object, paintInfo, rect);
- case MediaFullscreenButton:
+ case MediaEnterFullscreenButton:
+ case MediaExitFullscreenButton:
return paintMediaFullscreenButton(object, paintInfo, rect);
case MediaVolumeSliderMuteButton:
case MediaSeekBackButton:
diff --git a/Source/WebCore/rendering/RenderMenuList.cpp b/Source/WebCore/rendering/RenderMenuList.cpp
index a47aebbae..6d25c3572 100644
--- a/Source/WebCore/rendering/RenderMenuList.cpp
+++ b/Source/WebCore/rendering/RenderMenuList.cpp
@@ -28,7 +28,6 @@
#include "AXObjectCache.h"
#include "AccessibilityMenuList.h"
#include "CSSFontSelector.h"
-#include "CSSStyleSelector.h"
#include "Chrome.h"
#include "FontCache.h"
#include "Frame.h"
@@ -43,6 +42,8 @@
#include "RenderBR.h"
#include "RenderScrollbar.h"
#include "RenderTheme.h"
+#include "Settings.h"
+#include "StyleResolver.h"
#include "TextRun.h"
#include <math.h>
@@ -161,7 +162,7 @@ void RenderMenuList::updateOptionsWidth()
// Add in the option's text indent. We can't calculate percentage values for now.
float optionWidth = 0;
if (RenderStyle* optionStyle = element->renderStyle())
- optionWidth += optionStyle->textIndent().calcMinValue(0);
+ optionWidth += minimumValueForLength(optionStyle->textIndent(), 0, view());
if (!text.isEmpty())
optionWidth += style()->font().width(text);
maxOptionWidth = max(maxOptionWidth, optionWidth);
@@ -307,8 +308,11 @@ void RenderMenuList::showPopup()
// Compute the top left taking transforms into account, but use
// the actual width of the element to size the popup.
FloatPoint absTopLeft = localToAbsolute(FloatPoint(), false, true);
- LayoutRect absBounds = absoluteBoundingBoxRectIgnoringTransforms();
- absBounds.setLocation(roundedLayoutPoint(absTopLeft));
+ IntRect absBounds = absoluteBoundingBoxRectIgnoringTransforms();
+ int scale = document()->page()->settings()->defaultDeviceScaleFactor();
+ if (scale && scale != 1)
+ absBounds.scale(scale);
+ absBounds.setLocation(roundedIntPoint(absTopLeft));
HTMLSelectElement* select = toHTMLSelectElement(node());
m_popup->show(absBounds, document()->view(), select->optionToListIndex(select->selectedIndex()));
}
@@ -507,13 +511,13 @@ int RenderMenuList::clientInsetRight() const
return 0;
}
-int RenderMenuList::clientPaddingLeft() const
+LayoutUnit RenderMenuList::clientPaddingLeft() const
{
return paddingLeft() + m_innerBlock->paddingLeft();
}
const int endOfLinePadding = 2;
-int RenderMenuList::clientPaddingRight() const
+LayoutUnit RenderMenuList::clientPaddingRight() const
{
if (style()->appearance() == MenulistPart || style()->appearance() == MenulistButtonPart) {
// For these appearance values, the theme applies padding to leave room for the
@@ -572,7 +576,7 @@ void RenderMenuList::setTextFromItem(unsigned listIndex)
FontSelector* RenderMenuList::fontSelector() const
{
- return document()->styleSelector()->fontSelector();
+ return document()->styleResolver()->fontSelector();
}
}
diff --git a/Source/WebCore/rendering/RenderMeter.cpp b/Source/WebCore/rendering/RenderMeter.cpp
index 78ed8cdeb..5540a1942 100644
--- a/Source/WebCore/rendering/RenderMeter.cpp
+++ b/Source/WebCore/rendering/RenderMeter.cpp
@@ -46,13 +46,13 @@ RenderMeter::~RenderMeter()
void RenderMeter::computeLogicalWidth()
{
RenderBox::computeLogicalWidth();
- setWidth(theme()->meterSizeForBounds(this, frameRect()).width());
+ setWidth(theme()->meterSizeForBounds(this, pixelSnappedIntRect(frameRect())).width());
}
void RenderMeter::computeLogicalHeight()
{
RenderBox::computeLogicalHeight();
- setHeight(theme()->meterSizeForBounds(this, frameRect()).height());
+ setHeight(theme()->meterSizeForBounds(this, pixelSnappedIntRect(frameRect())).height());
}
double RenderMeter::valueRatio() const
diff --git a/Source/WebCore/rendering/RenderMultiColumnBlock.cpp b/Source/WebCore/rendering/RenderMultiColumnBlock.cpp
new file mode 100644
index 000000000..d29055e68
--- /dev/null
+++ b/Source/WebCore/rendering/RenderMultiColumnBlock.cpp
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "RenderMultiColumnBlock.h"
+
+using namespace std;
+
+namespace WebCore {
+
+RenderMultiColumnBlock::RenderMultiColumnBlock(Node* node)
+ : RenderBlock(node)
+ , m_columnCount(1)
+ , m_columnWidth(0)
+{
+}
+
+void RenderMultiColumnBlock::computeColumnCountAndWidth()
+{
+ // Calculate our column width and column count.
+ // FIXME: Can overflow on fast/block/float/float-not-removed-from-next-sibling4.html, see https://bugs.webkit.org/show_bug.cgi?id=68744
+ m_columnCount = 1;
+ m_columnWidth = contentLogicalWidth();
+
+ ASSERT(!style()->hasAutoColumnCount() || !style()->hasAutoColumnWidth());
+
+ LayoutUnit availWidth = m_columnWidth;
+ LayoutUnit colGap = columnGap();
+ LayoutUnit colWidth = max<LayoutUnit>(1, LayoutUnit(style()->columnWidth()));
+ int colCount = max<int>(1, style()->columnCount());
+
+ if (style()->hasAutoColumnWidth() && !style()->hasAutoColumnCount()) {
+ m_columnCount = colCount;
+ m_columnWidth = max<LayoutUnit>(0, (availWidth - ((m_columnCount - 1) * colGap)) / m_columnCount);
+ } else if (!style()->hasAutoColumnWidth() && style()->hasAutoColumnCount()) {
+ m_columnCount = max<LayoutUnit>(1, (availWidth + colGap) / (colWidth + colGap));
+ m_columnWidth = ((availWidth + colGap) / m_columnCount) - colGap;
+ } else {
+ m_columnCount = max<LayoutUnit>(min<LayoutUnit>(colCount, (availWidth + colGap) / (colWidth + colGap)), 1);
+ m_columnWidth = ((availWidth + colGap) / m_columnCount) - colGap;
+ }
+}
+
+bool RenderMultiColumnBlock::recomputeLogicalWidth()
+{
+ bool relayoutChildren = RenderBlock::recomputeLogicalWidth();
+ LayoutUnit oldColumnWidth = m_columnWidth;
+ computeColumnCountAndWidth();
+ if (m_columnWidth != oldColumnWidth)
+ relayoutChildren = true;
+ return relayoutChildren;
+}
+
+const char* RenderMultiColumnBlock::renderName() const
+{
+ if (isFloating())
+ return "RenderMultiColumnBlock (floating)";
+ if (isPositioned())
+ return "RenderMultiColumnBlock (positioned)";
+ if (isAnonymousBlock())
+ return "RenderMultiColumnBlock (anonymous)";
+ if (isAnonymous())
+ return "RenderMultiColumnBlock (generated)";
+ if (isRelPositioned())
+ return "RenderMultiColumnBlock (relative positioned)";
+ return "RenderMultiColumnBlock";
+}
+
+}
diff --git a/Source/WebCore/rendering/RenderMultiColumnBlock.h b/Source/WebCore/rendering/RenderMultiColumnBlock.h
new file mode 100644
index 000000000..2ab642146
--- /dev/null
+++ b/Source/WebCore/rendering/RenderMultiColumnBlock.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef RenderMultiColumnBlock_h
+#define RenderMultiColumnBlock_h
+
+#include "RenderBlock.h"
+
+namespace WebCore {
+
+class RenderMultiColumnBlock : public RenderBlock {
+public:
+ RenderMultiColumnBlock(Node*);
+
+private:
+ virtual const char* renderName() const;
+
+ virtual bool recomputeLogicalWidth();
+ void computeColumnCountAndWidth();
+
+private:
+ unsigned m_columnCount; // The default column count/width that are based off our containing block width. These values represent only the default,
+ LayoutUnit m_columnWidth; // since a multi-column block that is split across variable width pages or regions will have different column counts and widths in each.
+ // These values will be cached (eventually) for multi-column blocks.
+};
+
+} // namespace WebCore
+
+#endif // RenderMultiColumnBlock_h
+
diff --git a/Source/WebCore/rendering/RenderMultiColumnFlowThread.cpp b/Source/WebCore/rendering/RenderMultiColumnFlowThread.cpp
new file mode 100644
index 000000000..e90ef4e3c
--- /dev/null
+++ b/Source/WebCore/rendering/RenderMultiColumnFlowThread.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS IN..0TERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "RenderMultiColumnFlowThread.h"
+
+namespace WebCore {
+
+RenderMultiColumnFlowThread::RenderMultiColumnFlowThread(Node* node)
+ : RenderFlowThread(node)
+{
+}
+
+const char* RenderMultiColumnFlowThread::renderName() const
+{
+ return "RenderMultiColumnFlowThread";
+}
+
+}
diff --git a/Source/WebCore/rendering/RenderMultiColumnFlowThread.h b/Source/WebCore/rendering/RenderMultiColumnFlowThread.h
new file mode 100644
index 000000000..f4a0a0420
--- /dev/null
+++ b/Source/WebCore/rendering/RenderMultiColumnFlowThread.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef RenderMultiColumnFlowThread_h
+#define RenderMultiColumnFlowThread_h
+
+#include "RenderFlowThread.h"
+
+namespace WebCore {
+
+class RenderMultiColumnFlowThread : public RenderFlowThread {
+public:
+ RenderMultiColumnFlowThread(Node*);
+
+private:
+ virtual const char* renderName() const OVERRIDE;
+};
+
+} // namespace WebCore
+
+#endif // RenderMultiColumnFlowThread_h
+
diff --git a/Source/WebCore/rendering/RenderMultiColumnSet.cpp b/Source/WebCore/rendering/RenderMultiColumnSet.cpp
new file mode 100644
index 000000000..437aa4264
--- /dev/null
+++ b/Source/WebCore/rendering/RenderMultiColumnSet.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "RenderMultiColumnSet.h"
+
+namespace WebCore {
+
+RenderMultiColumnSet::RenderMultiColumnSet(Node* node, RenderFlowThread* flowThread)
+ : RenderRegionSet(node, flowThread)
+{
+}
+
+const char* RenderMultiColumnSet::renderName() const
+{
+ return "RenderMultiColumnSet";
+}
+
+}
diff --git a/Source/WebCore/rendering/RenderMultiColumnSet.h b/Source/WebCore/rendering/RenderMultiColumnSet.h
new file mode 100644
index 000000000..c5794c8df
--- /dev/null
+++ b/Source/WebCore/rendering/RenderMultiColumnSet.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef RenderMultiColumnSet_h
+#define RenderMultiColumnSet_h
+
+#include "RenderRegionSet.h"
+
+namespace WebCore {
+
+// RenderMultiColumnSet represents a set of columns that all have the same width and height. By combining runs of same-size columns into a single
+// object, we significantly reduce the number of unique RenderObjects required to represent columns.
+//
+// A simple multi-column block will have exactly one RenderMultiColumnSet child. A simple paginated multi-column block will have three
+// RenderMultiColumnSet children: one for the content at the bottom of the first page (whose columns will have a shorter height), one
+// for the 2nd to n-1 pages, and then one last column set that will hold the shorter columns on the final page (that may have to be balanced
+// as well).
+//
+// Column spans result in the creation of new column sets as well, since a spanning region has to be placed in between the column sets that
+// come before and after the span.
+class RenderMultiColumnSet : public RenderRegionSet {
+public:
+ RenderMultiColumnSet(Node*, RenderFlowThread*);
+
+private:
+ virtual const char* renderName() const;
+};
+
+} // namespace WebCore
+
+#endif // RenderMultiColumnSet_h
+
diff --git a/Source/WebCore/rendering/RenderNamedFlowThread.cpp b/Source/WebCore/rendering/RenderNamedFlowThread.cpp
new file mode 100644
index 000000000..088b87248
--- /dev/null
+++ b/Source/WebCore/rendering/RenderNamedFlowThread.cpp
@@ -0,0 +1,288 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS IN..0TERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "RenderNamedFlowThread.h"
+
+#include "FlowThreadController.h"
+#include "RenderRegion.h"
+#include "RenderView.h"
+#include "WebKitNamedFlow.h"
+
+namespace WebCore {
+
+RenderNamedFlowThread::RenderNamedFlowThread(Node* node, const AtomicString& name)
+ : RenderFlowThread(node)
+ , m_flowThreadName(name)
+{
+}
+
+const char* RenderNamedFlowThread::renderName() const
+{
+ return "RenderNamedFlowThread";
+}
+
+
+RenderObject* RenderNamedFlowThread::nextRendererForNode(Node* node) const
+{
+ FlowThreadChildList::const_iterator it = m_flowThreadChildList.begin();
+ FlowThreadChildList::const_iterator end = m_flowThreadChildList.end();
+
+ for (; it != end; ++it) {
+ RenderObject* child = *it;
+ ASSERT(child->node());
+ unsigned short position = node->compareDocumentPosition(child->node());
+ if (position & Node::DOCUMENT_POSITION_FOLLOWING)
+ return child;
+ }
+
+ return 0;
+}
+
+RenderObject* RenderNamedFlowThread::previousRendererForNode(Node* node) const
+{
+ if (m_flowThreadChildList.isEmpty())
+ return 0;
+
+ FlowThreadChildList::const_iterator begin = m_flowThreadChildList.begin();
+ FlowThreadChildList::const_iterator end = m_flowThreadChildList.end();
+ FlowThreadChildList::const_iterator it = end;
+
+ do {
+ --it;
+ RenderObject* child = *it;
+ ASSERT(child->node());
+ unsigned short position = node->compareDocumentPosition(child->node());
+ if (position & Node::DOCUMENT_POSITION_PRECEDING)
+ return child;
+ } while (it != begin);
+
+ return 0;
+}
+
+void RenderNamedFlowThread::addFlowChild(RenderObject* newChild, RenderObject* beforeChild)
+{
+ // The child list is used to sort the flow thread's children render objects
+ // based on their corresponding nodes DOM order. The list is needed to avoid searching the whole DOM.
+
+ // Do not add anonymous objects.
+ if (!newChild->node())
+ return;
+
+ if (beforeChild)
+ m_flowThreadChildList.insertBefore(beforeChild, newChild);
+ else
+ m_flowThreadChildList.add(newChild);
+}
+
+void RenderNamedFlowThread::removeFlowChild(RenderObject* child)
+{
+ m_flowThreadChildList.remove(child);
+}
+
+bool RenderNamedFlowThread::dependsOn(RenderNamedFlowThread* otherRenderFlowThread) const
+{
+ if (m_layoutBeforeThreadsSet.contains(otherRenderFlowThread))
+ return true;
+
+ // Recursively traverse the m_layoutBeforeThreadsSet.
+ RenderNamedFlowThreadCountedSet::const_iterator iterator = m_layoutBeforeThreadsSet.begin();
+ RenderNamedFlowThreadCountedSet::const_iterator end = m_layoutBeforeThreadsSet.end();
+ for (; iterator != end; ++iterator) {
+ const RenderNamedFlowThread* beforeFlowThread = (*iterator).first;
+ if (beforeFlowThread->dependsOn(otherRenderFlowThread))
+ return true;
+ }
+
+ return false;
+}
+
+// Compare two regions to determine in which one the content should flow first.
+// The function returns true if the first passed region is "less" than the second passed region.
+// If the first region appears before second region in DOM,
+// the first region is "less" than the second region.
+// If the first region is "less" than the second region, the first region receives content before second region.
+static bool compareRenderRegions(const RenderRegion* firstRegion, const RenderRegion* secondRegion)
+{
+ ASSERT(firstRegion);
+ ASSERT(secondRegion);
+
+ // If the regions have the same region-index, compare their position in dom.
+ ASSERT(firstRegion->node());
+ ASSERT(secondRegion->node());
+
+ unsigned short position = firstRegion->node()->compareDocumentPosition(secondRegion->node());
+ return (position & Node::DOCUMENT_POSITION_FOLLOWING);
+}
+
+void RenderNamedFlowThread::addRegionToThread(RenderRegion* renderRegion)
+{
+ ASSERT(renderRegion);
+ if (m_regionList.isEmpty())
+ m_regionList.add(renderRegion);
+ else {
+ // Find the first region "greater" than renderRegion.
+ RenderRegionList::iterator it = m_regionList.begin();
+ while (it != m_regionList.end() && !compareRenderRegions(renderRegion, *it))
+ ++it;
+ m_regionList.insertBefore(it, renderRegion);
+ }
+
+ ASSERT(!renderRegion->isValid());
+ if (renderRegion->parentNamedFlowThread()) {
+ if (renderRegion->parentNamedFlowThread()->dependsOn(this)) {
+ // Register ourself to get a notification when the state changes.
+ renderRegion->parentNamedFlowThread()->m_observerThreadsSet.add(this);
+ return;
+ }
+
+ addDependencyOnFlowThread(renderRegion->parentNamedFlowThread());
+ }
+
+ renderRegion->setIsValid(true);
+
+ invalidateRegions();
+}
+
+void RenderNamedFlowThread::removeRegionFromThread(RenderRegion* renderRegion)
+{
+ ASSERT(renderRegion);
+ m_regionRangeMap.clear();
+ m_regionList.remove(renderRegion);
+
+ if (renderRegion->parentNamedFlowThread()) {
+ if (!renderRegion->isValid()) {
+ renderRegion->parentNamedFlowThread()->m_observerThreadsSet.remove(this);
+ // No need to invalidate the regions rectangles. The removed region
+ // was not taken into account. Just return here.
+ return;
+ }
+ removeDependencyOnFlowThread(renderRegion->parentNamedFlowThread());
+ }
+
+ invalidateRegions();
+}
+
+
+void RenderNamedFlowThread::checkInvalidRegions()
+{
+ for (RenderRegionList::iterator iter = m_regionList.begin(); iter != m_regionList.end(); ++iter) {
+ RenderRegion* region = *iter;
+ // The only reason a region would be invalid is because it has a parent flow thread.
+ ASSERT(region->isValid() || region->parentNamedFlowThread());
+ if (region->isValid() || region->parentNamedFlowThread()->dependsOn(this))
+ continue;
+
+ region->parentNamedFlowThread()->m_observerThreadsSet.remove(this);
+ addDependencyOnFlowThread(region->parentNamedFlowThread());
+ region->setIsValid(true);
+ invalidateRegions();
+ }
+
+ if (m_observerThreadsSet.isEmpty())
+ return;
+
+ // Notify all the flow threads that were dependent on this flow.
+
+ // Create a copy of the list first. That's because observers might change the list when calling checkInvalidRegions.
+ Vector<RenderNamedFlowThread*> observers;
+ copyToVector(m_observerThreadsSet, observers);
+
+ for (size_t i = 0; i < observers.size(); ++i) {
+ RenderNamedFlowThread* flowThread = observers.at(i);
+ flowThread->checkInvalidRegions();
+ }
+}
+
+void RenderNamedFlowThread::addDependencyOnFlowThread(RenderNamedFlowThread* otherFlowThread)
+{
+ RenderNamedFlowThreadCountedSet::AddResult result = m_layoutBeforeThreadsSet.add(otherFlowThread);
+ if (result.isNewEntry) {
+ // This is the first time we see this dependency. Make sure we recalculate all the dependencies.
+ view()->flowThreadController()->setIsRenderNamedFlowThreadOrderDirty(true);
+ }
+}
+
+void RenderNamedFlowThread::removeDependencyOnFlowThread(RenderNamedFlowThread* otherFlowThread)
+{
+ bool removed = m_layoutBeforeThreadsSet.remove(otherFlowThread);
+ if (removed) {
+ checkInvalidRegions();
+ view()->flowThreadController()->setIsRenderNamedFlowThreadOrderDirty(true);
+ }
+}
+
+void RenderNamedFlowThread::pushDependencies(RenderNamedFlowThreadList& list)
+{
+ for (RenderNamedFlowThreadCountedSet::iterator iter = m_layoutBeforeThreadsSet.begin(); iter != m_layoutBeforeThreadsSet.end(); ++iter) {
+ RenderNamedFlowThread* flowThread = (*iter).first;
+ if (list.contains(flowThread))
+ continue;
+ flowThread->pushDependencies(list);
+ list.add(flowThread);
+ }
+}
+
+WebKitNamedFlow* RenderNamedFlowThread::ensureNamedFlow()
+{
+ if (!m_namedFlow)
+ m_namedFlow = WebKitNamedFlow::create(this);
+
+ return m_namedFlow.get();
+}
+
+// The content nodes list contains those nodes with -webkit-flow-into: flow.
+// An element with display:none should also be listed among those nodes.
+// The list of nodes is ordered.
+void RenderNamedFlowThread::registerNamedFlowContentNode(Node* contentNode)
+{
+ ASSERT(contentNode && contentNode->isElementNode());
+
+ contentNode->setInNamedFlow();
+
+ // Find the first content node following the new content node.
+ for (NamedFlowContentNodes::iterator it = m_contentNodes.begin(); it != m_contentNodes.end(); ++it) {
+ Node* node = *it;
+ unsigned short position = contentNode->compareDocumentPosition(node);
+ if (position & Node::DOCUMENT_POSITION_FOLLOWING) {
+ m_contentNodes.insertBefore(node, contentNode);
+ return;
+ }
+ }
+ m_contentNodes.add(contentNode);
+}
+
+void RenderNamedFlowThread::unregisterNamedFlowContentNode(Node* contentNode)
+{
+ ASSERT(contentNode && contentNode->isElementNode());
+ ASSERT(m_contentNodes.contains(contentNode));
+ ASSERT(contentNode->inNamedFlow());
+
+ contentNode->clearInNamedFlow();
+ m_contentNodes.remove(contentNode);
+
+}
+
+}
diff --git a/Source/WebCore/rendering/RenderNamedFlowThread.h b/Source/WebCore/rendering/RenderNamedFlowThread.h
new file mode 100644
index 000000000..d0c8ca014
--- /dev/null
+++ b/Source/WebCore/rendering/RenderNamedFlowThread.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef RenderNamedFlowThread_h
+#define RenderNamedFlowThread_h
+
+#include "RenderFlowThread.h"
+#include <wtf/HashCountedSet.h>
+#include <wtf/ListHashSet.h>
+#include <wtf/text/AtomicString.h>
+
+namespace WebCore {
+
+class Node;
+class RenderNamedFlowThread;
+class WebKitNamedFlow;
+
+typedef ListHashSet<RenderNamedFlowThread*> RenderNamedFlowThreadList;
+typedef HashCountedSet<RenderNamedFlowThread*> RenderNamedFlowThreadCountedSet;
+typedef ListHashSet<Node*> NamedFlowContentNodes;
+
+class RenderNamedFlowThread : public RenderFlowThread {
+public:
+ RenderNamedFlowThread(Node*, const AtomicString&);
+
+ AtomicString flowThreadName() const { return m_flowThreadName; }
+
+ RenderObject* nextRendererForNode(Node*) const;
+ RenderObject* previousRendererForNode(Node*) const;
+
+ void addFlowChild(RenderObject* newChild, RenderObject* beforeChild = 0);
+ void removeFlowChild(RenderObject*);
+ bool hasChildren() const { return !m_flowThreadChildList.isEmpty(); }
+#ifndef NDEBUG
+ bool hasChild(RenderObject* child) const { return m_flowThreadChildList.contains(child); }
+#endif
+
+ void pushDependencies(RenderNamedFlowThreadList&);
+
+ virtual void addRegionToThread(RenderRegion*) OVERRIDE;
+ virtual void removeRegionFromThread(RenderRegion*) OVERRIDE;
+
+ WebKitNamedFlow* ensureNamedFlow();
+ void registerNamedFlowContentNode(Node*);
+ void unregisterNamedFlowContentNode(Node*);
+ const NamedFlowContentNodes& contentNodes() const { return m_contentNodes; }
+ bool hasContentNode(Node* contentNode) const { ASSERT(contentNode); return m_contentNodes.contains(contentNode); }
+
+private:
+ virtual const char* renderName() const OVERRIDE;
+ virtual bool isRenderNamedFlowThread() const OVERRIDE { return true; }
+
+ bool dependsOn(RenderNamedFlowThread* otherRenderFlowThread) const;
+ void addDependencyOnFlowThread(RenderNamedFlowThread*);
+ void removeDependencyOnFlowThread(RenderNamedFlowThread*);
+ void checkInvalidRegions();
+
+private:
+ // The name of the flow thread as specified in CSS.
+ AtomicString m_flowThreadName;
+
+ // Observer flow threads have invalid regions that depend on the state of this thread
+ // to re-validate their regions. Keeping a set of observer threads make it easy
+ // to notify them when a region was removed from this flow.
+ RenderNamedFlowThreadCountedSet m_observerThreadsSet;
+
+ // Some threads need to have a complete layout before we layout this flow.
+ // That's because they contain a RenderRegion that should display this thread. The set makes it
+ // easy to sort the order of threads layout.
+ RenderNamedFlowThreadCountedSet m_layoutBeforeThreadsSet;
+
+ // Holds the sorted children of a named flow. This is the only way we can get the ordering right.
+ typedef ListHashSet<RenderObject*> FlowThreadChildList;
+ FlowThreadChildList m_flowThreadChildList;
+
+ NamedFlowContentNodes m_contentNodes;
+
+ // The DOM Object that represents a named flow.
+ RefPtr<WebKitNamedFlow> m_namedFlow;
+};
+
+inline RenderNamedFlowThread* toRenderNamedFlowThread(RenderObject* object)
+{
+ ASSERT(!object || object->isRenderNamedFlowThread());
+ return static_cast<RenderNamedFlowThread*>(object);
+}
+
+inline const RenderNamedFlowThread* toRenderNamedFlowThread(const RenderObject* object)
+{
+ ASSERT(!object || object->isRenderNamedFlowThread());
+ return static_cast<const RenderNamedFlowThread*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderNamedFlowThread(const RenderNamedFlowThread*);
+
+} // namespace WebCore
+
+#endif // RenderNamedFlowThread_h
+
diff --git a/Source/WebCore/rendering/RenderObject.cpp b/Source/WebCore/rendering/RenderObject.cpp
index fbe452577..cc80bae9b 100755
--- a/Source/WebCore/rendering/RenderObject.cpp
+++ b/Source/WebCore/rendering/RenderObject.cpp
@@ -28,13 +28,13 @@
#include "RenderObject.h"
#include "AXObjectCache.h"
-#include "CSSStyleSelector.h"
#include "Chrome.h"
#include "ContentData.h"
#include "CursorList.h"
#include "DashArray.h"
#include "EditingBoundary.h"
#include "FloatQuad.h"
+#include "FlowThreadController.h"
#include "Frame.h"
#include "FrameView.h"
#include "GraphicsContext.h"
@@ -46,12 +46,13 @@
#include "RenderCounter.h"
#include "RenderDeprecatedFlexibleBox.h"
#include "RenderFlexibleBox.h"
-#include "RenderFlowThread.h"
#include "RenderImage.h"
#include "RenderImageResourceStyleImage.h"
#include "RenderInline.h"
#include "RenderLayer.h"
#include "RenderListItem.h"
+#include "RenderMultiColumnBlock.h"
+#include "RenderNamedFlowThread.h"
#include "RenderRegion.h"
#include "RenderRuby.h"
#include "RenderRubyText.h"
@@ -61,6 +62,8 @@
#include "RenderTableRow.h"
#include "RenderTheme.h"
#include "RenderView.h"
+#include "Settings.h"
+#include "StyleResolver.h"
#include "TransformState.h"
#include "htmlediting.h"
#include <algorithm>
@@ -100,6 +103,8 @@ COMPILE_ASSERT(sizeof(RenderObject) == sizeof(SameSizeAsRenderObject), RenderObj
bool RenderObject::s_affectsParentBlock = false;
+RenderObjectAncestorLineboxDirtySet* RenderObject::s_ancestorLineboxDirtySet = 0;
+
void* RenderObject::operator new(size_t sz, RenderArena* renderArena)
{
return renderArena->allocate(sz);
@@ -159,7 +164,9 @@ RenderObject* RenderObject::createObject(Node* node, RenderStyle* style)
case COMPACT:
// Only non-replaced block elements can become a region.
if (doc->cssRegionsEnabled() && !style->regionThread().isEmpty() && doc->renderView())
- return new (arena) RenderRegion(node, doc->renderView()->ensureRenderFlowThreadWithName(style->regionThread()));
+ return new (arena) RenderRegion(node, doc->renderView()->flowThreadController()->ensureRenderFlowThreadWithName(style->regionThread()));
+ if ((!style->hasAutoColumnCount() || !style->hasAutoColumnWidth()) && doc->regionBasedColumnsEnabled())
+ return new (arena) RenderMultiColumnBlock(node);
return new (arena) RenderBlock(node);
case LIST_ITEM:
return new (arena) RenderListItem(node);
@@ -256,26 +263,6 @@ bool RenderObject::isHTMLMarquee() const
return node() && node()->renderer() == this && node()->hasTagName(marqueeTag);
}
-static bool isBeforeAfterContentGeneratedByAncestor(RenderObject* renderer, RenderObject* beforeAfterContent)
-{
- while (renderer) {
- if (renderer->generatingNode() == beforeAfterContent->generatingNode())
- return true;
- renderer = renderer->parent();
- }
- return false;
-}
-
-RenderTable* RenderObject::createAnonymousTable() const
-{
- RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyle(style());
- newStyle->setDisplay(TABLE);
-
- RenderTable* table = new (renderArena()) RenderTable(document() /* is anonymous */);
- table->setStyle(newStyle.release());
- return table;
-}
-
void RenderObject::addChild(RenderObject* newChild, RenderObject* beforeChild)
{
RenderObjectChildList* children = virtualChildren();
@@ -283,17 +270,6 @@ void RenderObject::addChild(RenderObject* newChild, RenderObject* beforeChild)
if (!children)
return;
- RenderObject* beforeContent = 0;
- bool beforeChildHasBeforeAndAfterContent = false;
- if (beforeChild && (beforeChild->isTable() || beforeChild->isTableSection() || beforeChild->isTableRow() || beforeChild->isTableCell())) {
- beforeContent = beforeChild->beforePseudoElementRenderer();
- RenderObject* afterContent = beforeChild->afterPseudoElementRenderer();
- if (beforeContent && afterContent && isBeforeAfterContentGeneratedByAncestor(this, beforeContent)) {
- beforeChildHasBeforeAndAfterContent = true;
- beforeContent->destroy();
- }
- }
-
bool needsTable = false;
if (newChild->isTableCol() && newChild->style()->display() == TABLE_COLUMN_GROUP)
@@ -320,7 +296,7 @@ void RenderObject::addChild(RenderObject* newChild, RenderObject* beforeChild)
if (afterChild && afterChild->isAnonymous() && afterChild->isTable() && !afterChild->isBeforeContent())
table = toRenderTable(afterChild);
else {
- table = createAnonymousTable();
+ table = RenderTable::createAnonymousWithParentRenderer(this);
addChild(table, beforeChild);
}
table->addChild(newChild);
@@ -329,11 +305,8 @@ void RenderObject::addChild(RenderObject* newChild, RenderObject* beforeChild)
children->insertChildNode(this, newChild, beforeChild);
}
- if (newChild->isText() && newChild->style()->textTransform() == CAPITALIZE) {
- RefPtr<StringImpl> textToTransform = toRenderText(newChild)->originalText();
- if (textToTransform)
- toRenderText(newChild)->setText(textToTransform.release(), true);
- }
+ if (newChild->isText() && newChild->style()->textTransform() == CAPITALIZE)
+ toRenderText(newChild)->transformText();
// SVG creates renderers for <g display="none">, as SVG requires children of hidden
// <g>s to have renderers - at least that's how our implementation works. Consider:
@@ -345,9 +318,6 @@ void RenderObject::addChild(RenderObject* newChild, RenderObject* beforeChild)
// and stop creating layers at all for these cases - they're not used anyways.
if (newChild->hasLayer() && !layerCreationAllowedForSubtree())
toRenderBoxModelObject(newChild)->layer()->removeOnlyThisLayer();
-
- if (beforeChildHasBeforeAndAfterContent)
- children->updateBeforeAfterContent(this, BEFORE);
}
void RenderObject::removeChild(RenderObject* oldChild)
@@ -565,6 +535,16 @@ RenderLayer* RenderObject::enclosingLayer() const
return 0;
}
+bool RenderObject::scrollRectToVisible(const LayoutRect& rect, const ScrollAlignment& alignX, const ScrollAlignment& alignY)
+{
+ RenderLayer* enclosingLayer = this->enclosingLayer();
+ if (!enclosingLayer)
+ return false;
+
+ enclosingLayer->scrollRectToVisible(rect, alignX, alignY);
+ return true;
+}
+
RenderBox* RenderObject::enclosingBox() const
{
RenderObject* curr = const_cast<RenderObject*>(this);
@@ -597,7 +577,7 @@ RenderFlowThread* RenderObject::enclosingRenderFlowThread() const
return 0;
// See if we have the thread cached because we're in the middle of layout.
- RenderFlowThread* flowThread = view()->currentRenderFlowThread();
+ RenderFlowThread* flowThread = view()->flowThreadController()->currentRenderFlowThread();
if (flowThread)
return flowThread;
@@ -680,11 +660,11 @@ void RenderObject::markContainingBlocksForLayout(bool scheduleRelayout, RenderOb
last->scheduleRelayout();
}
-void RenderObject::setPreferredLogicalWidthsDirty(bool b, bool markParents)
+void RenderObject::setPreferredLogicalWidthsDirty(bool shouldBeDirty, MarkingBehavior markParents)
{
bool alreadyDirty = preferredLogicalWidthsDirty();
- m_bitfields.setPreferredLogicalWidthsDirty(b);
- if (b && !alreadyDirty && markParents && (isText() || !style()->isPositioned()))
+ m_bitfields.setPreferredLogicalWidthsDirty(shouldBeDirty);
+ if (shouldBeDirty && !alreadyDirty && markParents == MarkContainingBlockChain && (isText() || !style()->isPositioned()))
invalidateContainerPreferredLogicalWidths();
}
@@ -1275,11 +1255,19 @@ RenderBoxModelObject* RenderObject::containerForRepaint() const
#if USE(ACCELERATED_COMPOSITING)
if (v->usesCompositing()) {
- RenderLayer* compLayer = enclosingLayer()->enclosingCompositingLayer();
+ RenderLayer* compLayer = enclosingLayer()->enclosingCompositingLayerForRepaint();
if (compLayer)
repaintContainer = compLayer->renderer();
}
#endif
+
+#if ENABLE(CSS_FILTERS)
+ if (RenderLayer* parentLayer = enclosingLayer()) {
+ RenderLayer* enclosingFilterLayer = parentLayer->enclosingFilterLayer();
+ if (enclosingFilterLayer)
+ return enclosingFilterLayer->renderer();
+ }
+#endif
// If we have a flow thread, then we need to do individual repaints within the RenderRegions instead.
// Return the flow thread as a repaint container in order to create a chokepoint that allows us to change
@@ -1303,12 +1291,19 @@ void RenderObject::repaintUsingContainer(RenderBoxModelObject* repaintContainer,
return;
}
+#if ENABLE(CSS_FILTERS)
+ if (repaintContainer->hasFilter() && repaintContainer->layer() && repaintContainer->layer()->requiresFullLayerImageForFilters()) {
+ repaintContainer->layer()->setFilterBackendNeedsRepaintingInRect(r, immediate);
+ return;
+ }
+#endif
+
#if USE(ACCELERATED_COMPOSITING)
RenderView* v = view();
if (repaintContainer->isRenderView()) {
ASSERT(repaintContainer == v);
bool viewHasCompositedLayer = v->hasLayer() && v->layer()->isComposited();
- if (!viewHasCompositedLayer || v->layer()->backing()->paintingGoesToWindow()) {
+ if (!viewHasCompositedLayer || v->layer()->backing()->paintsIntoWindow()) {
LayoutRect repaintRectangle = r;
if (viewHasCompositedLayer && v->layer()->transform())
repaintRectangle = v->layer()->transform()->mapRect(r);
@@ -1362,6 +1357,11 @@ void RenderObject::repaintRectangle(const LayoutRect& r, bool immediate)
repaintUsingContainer(repaintContainer ? repaintContainer : view, dirtyRect, immediate);
}
+IntRect RenderObject::pixelSnappedAbsoluteClippedOverflowRect() const
+{
+ return pixelSnappedIntRect(absoluteClippedOverflowRect());
+}
+
bool RenderObject::repaintAfterLayoutIfNeeded(RenderBoxModelObject* repaintContainer, const LayoutRect& oldBounds, const LayoutRect& oldOutlineBox, const LayoutRect* newBoundsPtr, const LayoutRect* newOutlineBoxRectPtr)
{
RenderView* v = view();
@@ -1429,34 +1429,34 @@ bool RenderObject::repaintAfterLayoutIfNeeded(RenderBoxModelObject* repaintConta
// two rectangles (but typically only one).
RenderStyle* outlineStyle = outlineStyleForRepaint();
LayoutUnit ow = outlineStyle->outlineSize();
- LayoutUnit width = abs(newOutlineBox.width() - oldOutlineBox.width());
+ LayoutUnit width = absoluteValue(newOutlineBox.width() - oldOutlineBox.width());
if (width) {
LayoutUnit shadowLeft;
LayoutUnit shadowRight;
style()->getBoxShadowHorizontalExtent(shadowLeft, shadowRight);
- LayoutUnit borderRight = isBox() ? toRenderBox(this)->borderRight() : zeroLayoutUnit;
- LayoutUnit boxWidth = isBox() ? toRenderBox(this)->width() : zeroLayoutUnit;
- LayoutUnit borderWidth = max<LayoutUnit>(-outlineStyle->outlineOffset(), max(borderRight, max<LayoutUnit>(style()->borderTopRightRadius().width().calcValue(boxWidth), style()->borderBottomRightRadius().width().calcValue(boxWidth)))) + max(ow, shadowRight);
+ int borderRight = isBox() ? toRenderBox(this)->borderRight() : 0;
+ LayoutUnit boxWidth = isBox() ? toRenderBox(this)->width() : ZERO_LAYOUT_UNIT;
+ LayoutUnit borderWidth = max<LayoutUnit>(-outlineStyle->outlineOffset(), max<LayoutUnit>(borderRight, max<LayoutUnit>(valueForLength(style()->borderTopRightRadius().width(), boxWidth, v), valueForLength(style()->borderBottomRightRadius().width(), boxWidth, v)))) + max<LayoutUnit>(ow, shadowRight);
LayoutRect rightRect(newOutlineBox.x() + min(newOutlineBox.width(), oldOutlineBox.width()) - borderWidth,
newOutlineBox.y(),
width + borderWidth,
max(newOutlineBox.height(), oldOutlineBox.height()));
- LayoutUnit right = min(newBounds.maxX(), oldBounds.maxX());
+ LayoutUnit right = min<LayoutUnit>(newBounds.maxX(), oldBounds.maxX());
if (rightRect.x() < right) {
rightRect.setWidth(min(rightRect.width(), right - rightRect.x()));
repaintUsingContainer(repaintContainer, rightRect);
}
}
- LayoutUnit height = abs(newOutlineBox.height() - oldOutlineBox.height());
+ LayoutUnit height = absoluteValue(newOutlineBox.height() - oldOutlineBox.height());
if (height) {
LayoutUnit shadowTop;
LayoutUnit shadowBottom;
style()->getBoxShadowVerticalExtent(shadowTop, shadowBottom);
- LayoutUnit borderBottom = isBox() ? toRenderBox(this)->borderBottom() : zeroLayoutUnit;
- LayoutUnit boxHeight = isBox() ? toRenderBox(this)->height() : zeroLayoutUnit;
- LayoutUnit borderHeight = max<LayoutUnit>(-outlineStyle->outlineOffset(), max(borderBottom, max<LayoutUnit>(style()->borderBottomLeftRadius().height().calcValue(boxHeight), style()->borderBottomRightRadius().height().calcValue(boxHeight)))) + max(ow, shadowBottom);
+ int borderBottom = isBox() ? toRenderBox(this)->borderBottom() : 0;
+ LayoutUnit boxHeight = isBox() ? toRenderBox(this)->height() : ZERO_LAYOUT_UNIT;
+ LayoutUnit borderHeight = max<LayoutUnit>(-outlineStyle->outlineOffset(), max<LayoutUnit>(borderBottom, max<LayoutUnit>(valueForLength(style()->borderBottomLeftRadius().height(), boxHeight, v), valueForLength(style()->borderBottomRightRadius().height(), boxHeight, v)))) + max<LayoutUnit>(ow, shadowBottom);
LayoutRect bottomRect(newOutlineBox.x(),
min(newOutlineBox.maxY(), oldOutlineBox.maxY()) - borderHeight,
max(newOutlineBox.width(), oldOutlineBox.width()),
@@ -1713,6 +1713,16 @@ StyleDifference RenderObject::adjustStyleDifference(StyleDifference diff, unsign
diff = StyleDifferenceRecompositeLayer;
}
+#if ENABLE(CSS_FILTERS)
+ if ((contextSensitiveProperties & ContextSensitivePropertyFilter) && hasLayer()) {
+ RenderLayer* layer = toRenderBoxModelObject(this)->layer();
+ if (!layer->isComposited() || layer->paintsWithFilters())
+ diff = StyleDifferenceRepaintLayer;
+ else if (diff < StyleDifferenceRecompositeLayer)
+ diff = StyleDifferenceRecompositeLayer;
+ }
+#endif
+
// The answer to requiresLayer() for plugins and iframes can change outside of the style system,
// since it depends on whether we decide to composite these elements. When the layer status of
// one of these elements changes, we need to force a layout.
@@ -1864,7 +1874,10 @@ void RenderObject::styleWillChange(StyleDifference diff, const RenderStyle* newS
// when scrolling a page with a fixed background image. As an optimization, assuming there are
// no fixed positoned elements on the page, we can acclerate scrolling (via blitting) if we
// ignore the CSS property "background-attachment: fixed".
- shouldBlitOnFixedBackgroundImage = true;
+#if PLATFORM(QT)
+ if (view()->frameView()->delegatesScrolling())
+#endif
+ shouldBlitOnFixedBackgroundImage = true;
#endif
bool newStyleSlowScroll = newStyle && !shouldBlitOnFixedBackgroundImage && newStyle->hasFixedBackgroundImage();
@@ -1942,7 +1955,7 @@ void RenderObject::propagateStyleToAnonymousChildren(bool blockChildrenOnly)
continue;
#endif
- RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyle(style());
+ RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(style(), child->style()->display());
if (style()->specifiesColumns()) {
if (child->style()->specifiesColumns())
newStyle->inheritColumnPropertiesFrom(style());
@@ -1955,7 +1968,6 @@ void RenderObject::propagateStyleToAnonymousChildren(bool blockChildrenOnly)
if (child->isRelPositioned() && toRenderBlock(child)->isAnonymousBlockContinuation())
newStyle->setPosition(child->style()->position());
- newStyle->setDisplay(child->style()->display());
child->setStyle(newStyle.release());
}
}
@@ -2011,7 +2023,7 @@ FloatPoint RenderObject::absoluteToLocal(const FloatPoint& containerPoint, bool
return transformState.lastPlanarPoint();
}
-void RenderObject::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed, bool useTransforms, TransformState& transformState, bool* wasFixed) const
+void RenderObject::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed, bool useTransforms, TransformState& transformState, ApplyContainerFlipOrNot, bool* wasFixed) const
{
if (repaintContainer == this)
return;
@@ -2032,7 +2044,7 @@ void RenderObject::mapLocalToContainer(RenderBoxModelObject* repaintContainer, b
if (o->hasOverflowClip())
transformState.move(-toRenderBox(o)->scrolledContentOffset());
- o->mapLocalToContainer(repaintContainer, fixed, useTransforms, transformState, wasFixed);
+ o->mapLocalToContainer(repaintContainer, fixed, useTransforms, transformState, DoNotApplyContainerFlip, wasFixed);
}
void RenderObject::mapAbsoluteToLocalPoint(bool fixed, bool useTransforms, TransformState& transformState) const
@@ -2088,7 +2100,7 @@ FloatQuad RenderObject::localToContainerQuad(const FloatQuad& localQuad, RenderB
// Track the point at the center of the quad's bounding box. As mapLocalToContainer() calls offsetFromContainer(),
// it will use that point as the reference point to decide which column's transform to apply in multiple-column blocks.
TransformState transformState(TransformState::ApplyTransformDirection, localQuad.boundingBox().center(), localQuad);
- mapLocalToContainer(repaintContainer, fixed, true, transformState, wasFixed);
+ mapLocalToContainer(repaintContainer, fixed, true, transformState, ApplyContainerFlip, wasFixed);
transformState.flatten();
return transformState.lastPlanarQuad();
@@ -2097,7 +2109,7 @@ FloatQuad RenderObject::localToContainerQuad(const FloatQuad& localQuad, RenderB
FloatPoint RenderObject::localToContainerPoint(const FloatPoint& localPoint, RenderBoxModelObject* repaintContainer, bool fixed, bool* wasFixed) const
{
TransformState transformState(TransformState::ApplyTransformDirection, localPoint);
- mapLocalToContainer(repaintContainer, fixed, true, transformState, wasFixed);
+ mapLocalToContainer(repaintContainer, fixed, true, transformState, ApplyContainerFlip, wasFixed);
transformState.flatten();
return transformState.lastPlanarPoint();
@@ -2177,6 +2189,13 @@ RenderObject* RenderObject::rendererForRootBackground()
return this;
}
+RespectImageOrientationEnum RenderObject::shouldRespectImageOrientation() const
+{
+ // Respect the image's orientation if it's being used as a full-page image or it's
+ // an <img> and the setting to respect it everywhere is set.
+ return document()->isImageDocument() || (document()->settings() && document()->settings()->shouldRespectImageOrientation() && node() && node()->hasTagName(HTMLNames::imgTag)) ? RespectImageOrientation : DoNotRespectImageOrientation;
+}
+
bool RenderObject::hasOutlineAnnotation() const
{
return node() && node()->isLink() && document()->printing();
@@ -2280,11 +2299,11 @@ void RenderObject::willBeDestroyed()
remove();
#ifndef NDEBUG
- if (!documentBeingDestroyed() && view() && view()->hasRenderFlowThreads()) {
+ if (!documentBeingDestroyed() && view() && view()->hasRenderNamedFlowThreads()) {
// After remove, the object and the associated information should not be in any flow thread.
- const RenderFlowThreadList* flowThreadList = view()->renderFlowThreadList();
- for (RenderFlowThreadList::const_iterator iter = flowThreadList->begin(); iter != flowThreadList->end(); ++iter) {
- const RenderFlowThread* renderFlowThread = *iter;
+ const RenderNamedFlowThreadList* flowThreadList = view()->flowThreadController()->renderNamedFlowThreadList();
+ for (RenderNamedFlowThreadList::const_iterator iter = flowThreadList->begin(); iter != flowThreadList->end(); ++iter) {
+ const RenderNamedFlowThread* renderFlowThread = *iter;
ASSERT(!renderFlowThread->hasChild(this));
ASSERT(!renderFlowThread->hasChildInfo(this));
}
@@ -2306,6 +2325,8 @@ void RenderObject::willBeDestroyed()
toRenderBoxModelObject(this)->destroyLayer();
}
+ setAncestorLineBoxDirty(false);
+
clearLayoutRootIfNeeded();
}
@@ -2390,6 +2411,11 @@ void RenderObject::updateDragState(bool dragOn)
curr->updateDragState(dragOn);
}
+bool RenderObject::isComposited() const
+{
+ return hasLayer() && toRenderBoxModelObject(this)->layer()->isComposited();
+}
+
bool RenderObject::hitTest(const HitTestRequest& request, HitTestResult& result, const LayoutPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestFilter hitTestFilter)
{
bool inside = false;
@@ -2527,19 +2553,20 @@ PassRefPtr<RenderStyle> RenderObject::getUncachedPseudoStyle(PseudoId pseudo, Re
parentStyle = style();
}
+ // FIXME: This "find nearest element parent" should be a helper function.
Node* n = node();
while (n && !n->isElementNode())
n = n->parentNode();
if (!n)
return 0;
+ Element* element = toElement(n);
- RefPtr<RenderStyle> result;
if (pseudo == FIRST_LINE_INHERITED) {
- result = document()->styleSelector()->styleForElement(static_cast<Element*>(n), parentStyle, false);
+ RefPtr<RenderStyle> result = document()->styleResolver()->styleForElement(element, parentStyle, DisallowStyleSharing);
result->setStyleType(FIRST_LINE_INHERITED);
- } else
- result = document()->styleSelector()->pseudoStyleForElement(pseudo, static_cast<Element*>(n), parentStyle);
- return result.release();
+ return result.release();
+ }
+ return document()->styleResolver()->pseudoStyleForElement(pseudo, element, parentStyle);
}
static Color decorationColor(RenderObject* renderer)
@@ -2663,7 +2690,7 @@ bool RenderObject::willRenderImage(CachedImage*)
return !document()->inPageCache() && !document()->view()->isOffscreen();
}
-LayoutUnit RenderObject::maximalOutlineSize(PaintPhase p) const
+int RenderObject::maximalOutlineSize(PaintPhase p) const
{
if (p != PaintPhaseOutline && p != PaintPhaseSelfOutline && p != PaintPhaseChildOutlines)
return 0;
@@ -2701,7 +2728,7 @@ int RenderObject::nextOffset(int current) const
void RenderObject::adjustRectForOutlineAndShadow(LayoutRect& rect) const
{
- LayoutUnit outlineSize = outlineStyleForRepaint()->outlineSize();
+ int outlineSize = outlineStyleForRepaint()->outlineSize();
if (const ShadowData* boxShadow = style()->boxShadow()) {
boxShadow->adjustRectForShadow(rect, outlineSize);
return;
@@ -2828,6 +2855,9 @@ CursorDirective RenderObject::getCursor(const LayoutPoint&, Cursor&) const
bool RenderObject::canUpdateSelectionOnRootLineBoxes()
{
+ if (needsLayout())
+ return false;
+
RenderBlock* containingBlock = this->containingBlock();
return containingBlock ? !containingBlock->needsLayout() : true;
}
diff --git a/Source/WebCore/rendering/RenderObject.h b/Source/WebCore/rendering/RenderObject.h
index 60e2a403c..a4a0596fb 100644
--- a/Source/WebCore/rendering/RenderObject.h
+++ b/Source/WebCore/rendering/RenderObject.h
@@ -29,16 +29,19 @@
#include "CachedImage.h"
#include "Document.h"
#include "Element.h"
+#include "FractionalLayoutUnit.h"
#include "FloatQuad.h"
#include "LayoutTypes.h"
#include "PaintPhase.h"
#include "RenderObjectChildList.h"
#include "RenderStyle.h"
+#include "ScrollBehavior.h"
#include "TextAffinity.h"
#include "TransformationMatrix.h"
+#include <wtf/HashSet.h>
#include <wtf/UnusedParam.h>
-#if USE(CG) || USE(CAIRO) || USE(SKIA) || PLATFORM(QT)
+#if USE(CG) || USE(CAIRO) || USE(SKIA) || PLATFORM(QT) || PLATFORM(WX)
#define HAVE_PATH_BASED_BORDER_RADIUS_DRAWING 1
#endif
@@ -96,6 +99,11 @@ enum BoxSide {
BSLeft
};
+enum MarkingBehavior {
+ MarkOnlyThis,
+ MarkContainingBlockChain,
+};
+
const int caretWidth = 1;
#if ENABLE(DASHBOARD_SUPPORT)
@@ -116,6 +124,8 @@ struct DashboardRegionValue {
};
#endif
+typedef WTF::HashSet<const RenderObject*> RenderObjectAncestorLineboxDirtySet;
+
#ifndef NDEBUG
const int showTreeCharacterOffset = 39;
#endif
@@ -195,6 +205,9 @@ public:
void moveLayers(RenderLayer* oldParent, RenderLayer* newParent);
RenderLayer* findNextLayer(RenderLayer* parentLayer, RenderObject* startPoint, bool checkParent = true);
+ // Scrolling is a RenderBox concept, however some code just cares about recursively scrolling our enclosing ScrollableArea(s).
+ bool scrollRectToVisible(const LayoutRect&, const ScrollAlignment& alignX = ScrollAlignment::alignCenterIfNeeded, const ScrollAlignment& alignY = ScrollAlignment::alignCenterIfNeeded);
+
// Convenience function for getting to the nearest enclosing box of a RenderObject.
RenderBox* enclosingBox() const;
RenderBoxModelObject* enclosingBoxModelObject() const;
@@ -220,8 +233,6 @@ public:
// normal flow object.
void handleDynamicFloatPositionChange();
- RenderTable* createAnonymousTable() const;
-
// RenderObject tree manipulation
//////////////////////////////////////////
virtual bool canHaveChildren() const { return virtualChildren(); }
@@ -343,6 +354,7 @@ public:
#endif
virtual bool isRenderFlowThread() const { return false; }
+ virtual bool isRenderNamedFlowThread() const { return false; }
bool canHaveRegionStyle() const { return isRenderBlock() && !isAnonymous() && !isRenderFlowThread(); }
bool isRoot() const { return document()->documentElement() == m_node; }
@@ -370,6 +382,22 @@ public:
bool hasColumns() const { return m_bitfields.hasColumns(); }
void setHasColumns(bool b = true) { m_bitfields.setHasColumns(b); }
+ bool ancestorLineBoxDirty() const { return s_ancestorLineboxDirtySet && s_ancestorLineboxDirtySet->contains(this); }
+ void setAncestorLineBoxDirty(bool b = true)
+ {
+ if (b) {
+ if (!s_ancestorLineboxDirtySet)
+ s_ancestorLineboxDirtySet = new RenderObjectAncestorLineboxDirtySet;
+ s_ancestorLineboxDirtySet->add(this);
+ } else if (s_ancestorLineboxDirtySet) {
+ s_ancestorLineboxDirtySet->remove(this);
+ if (s_ancestorLineboxDirtySet->isEmpty()) {
+ delete s_ancestorLineboxDirtySet;
+ s_ancestorLineboxDirtySet = 0;
+ }
+ }
+ }
+
bool inRenderFlowThread() const { return m_bitfields.inRenderFlowThread(); }
void setInRenderFlowThread(bool b = true) { m_bitfields.setInRenderFlowThread(b); }
@@ -502,6 +530,7 @@ public:
bool hasTransform() const { return m_bitfields.hasTransform(); }
bool hasMask() const { return style() && style()->hasMask(); }
+ bool hasHiddenBackface() const { return style() && style()->backfaceVisibility() == BackfaceVisibilityHidden; }
#if ENABLE(CSS_FILTERS)
bool hasFilter() const { return style() && style()->hasFilter(); }
@@ -556,11 +585,11 @@ public:
RenderBoxModelObject* offsetParent() const;
void markContainingBlocksForLayout(bool scheduleRelayout = true, RenderObject* newRoot = 0);
- void setNeedsLayout(bool b, bool markParents = true);
- void setChildNeedsLayout(bool b, bool markParents = true);
+ void setNeedsLayout(bool needsLayout, MarkingBehavior = MarkContainingBlockChain);
+ void setChildNeedsLayout(bool childNeedsLayout, MarkingBehavior = MarkContainingBlockChain);
void setNeedsPositionedMovementLayout();
void setNeedsSimplifiedNormalFlowLayout();
- void setPreferredLogicalWidthsDirty(bool, bool markParents = true);
+ void setPreferredLogicalWidthsDirty(bool, MarkingBehavior = MarkContainingBlockChain);
void invalidateContainerPreferredLogicalWidths();
void setNeedsLayoutAndPrefWidthsRecalc()
@@ -605,6 +634,8 @@ public:
void collectDashboardRegions(Vector<DashboardRegionValue>&);
#endif
+ bool isComposited() const;
+
bool hitTest(const HitTestRequest&, HitTestResult&, const LayoutPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestFilter = HitTestAll);
virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const LayoutPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction);
virtual void updateHitTestResult(HitTestResult&, const LayoutPoint&);
@@ -716,6 +747,7 @@ public:
{
return clippedOverflowRectForRepaint(0);
}
+ IntRect pixelSnappedAbsoluteClippedOverflowRect() const;
virtual LayoutRect clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer) const;
virtual LayoutRect rectWithOutlineForRepaint(RenderBoxModelObject* repaintContainer, LayoutUnit outlineWidth) const;
@@ -744,7 +776,7 @@ public:
bool hasReflection() const { return m_bitfields.hasReflection(); }
// Applied as a "slop" to dirty rect checks during the outline painting phase's dirty-rect checks.
- LayoutUnit maximalOutlineSize(PaintPhase) const;
+ int maximalOutlineSize(PaintPhase) const;
enum SelectionState {
SelectionNone, // The object is not selected.
@@ -833,7 +865,8 @@ public:
// Map points and quads through elements, potentially via 3d transforms. You should never need to call these directly; use
// localToAbsolute/absoluteToLocal methods instead.
- virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool useTransforms, bool fixed, TransformState&, bool* wasFixed = 0) const;
+ enum ApplyContainerFlipOrNot { DoNotApplyContainerFlip, ApplyContainerFlip };
+ virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool useTransforms, bool fixed, TransformState&, ApplyContainerFlipOrNot = ApplyContainerFlip, bool* wasFixed = 0) const;
virtual void mapAbsoluteToLocalPoint(bool fixed, bool useTransforms, TransformState&) const;
bool shouldUseTransformFromContainer(const RenderObject* container) const;
@@ -849,6 +882,8 @@ public:
// Return the renderer whose background style is used to paint the root background. Should only be called on the renderer for which isRoot() is true.
RenderObject* rendererForRootBackground();
+ RespectImageOrientationEnum shouldRespectImageOrientation() const;
+
protected:
inline bool layerCreationAllowedForSubtree() const;
@@ -889,6 +924,8 @@ private:
RenderObject* m_previous;
RenderObject* m_next;
+ static RenderObjectAncestorLineboxDirtySet* s_ancestorLineboxDirtySet;
+
#ifndef NDEBUG
bool m_hasAXObject : 1;
bool m_setNeedsLayoutForbidden : 1;
@@ -1031,14 +1068,14 @@ inline bool RenderObject::isBeforeOrAfterContent() const
return isBeforeContent() || isAfterContent();
}
-inline void RenderObject::setNeedsLayout(bool b, bool markParents)
+inline void RenderObject::setNeedsLayout(bool needsLayout, MarkingBehavior markParents)
{
bool alreadyNeededLayout = m_bitfields.needsLayout();
- m_bitfields.setNeedsLayout(b);
- if (b) {
+ m_bitfields.setNeedsLayout(needsLayout);
+ if (needsLayout) {
ASSERT(!isSetNeedsLayoutForbidden());
if (!alreadyNeededLayout) {
- if (markParents)
+ if (markParents == MarkContainingBlockChain)
markContainingBlocksForLayout();
if (hasLayer())
setLayerNeedsFullRepaint();
@@ -1049,16 +1086,17 @@ inline void RenderObject::setNeedsLayout(bool b, bool markParents)
setNeedsSimplifiedNormalFlowLayout(false);
setNormalChildNeedsLayout(false);
setNeedsPositionedMovementLayout(false);
+ setAncestorLineBoxDirty(false);
}
}
-inline void RenderObject::setChildNeedsLayout(bool b, bool markParents)
+inline void RenderObject::setChildNeedsLayout(bool childNeedsLayout, MarkingBehavior markParents)
{
bool alreadyNeededLayout = normalChildNeedsLayout();
- setNormalChildNeedsLayout(b);
- if (b) {
+ setNormalChildNeedsLayout(childNeedsLayout);
+ if (childNeedsLayout) {
ASSERT(!isSetNeedsLayoutForbidden());
- if (!alreadyNeededLayout && markParents)
+ if (!alreadyNeededLayout && markParents == MarkContainingBlockChain)
markContainingBlocksForLayout();
} else {
setPosChildNeedsLayout(false);
diff --git a/Source/WebCore/rendering/RenderObjectChildList.cpp b/Source/WebCore/rendering/RenderObjectChildList.cpp
index efe6b8520..265596c2b 100644
--- a/Source/WebCore/rendering/RenderObjectChildList.cpp
+++ b/Source/WebCore/rendering/RenderObjectChildList.cpp
@@ -31,12 +31,12 @@
#include "ContentData.h"
#include "RenderBlock.h"
#include "RenderCounter.h"
-#include "RenderFlowThread.h"
#include "RenderImage.h"
#include "RenderImageResourceStyleImage.h"
#include "RenderInline.h"
#include "RenderLayer.h"
#include "RenderListItem.h"
+#include "RenderNamedFlowThread.h"
#include "RenderQuote.h"
#include "RenderRegion.h"
#include "RenderStyle.h"
@@ -63,12 +63,12 @@ void RenderObjectChildList::destroyLeftoverChildren()
}
}
-static RenderFlowThread* renderFlowThreadContainer(RenderObject* object)
+static RenderNamedFlowThread* renderNamedFlowThreadContainer(RenderObject* object)
{
- while (object && object->isAnonymousBlock() && !object->isRenderFlowThread())
+ while (object && object->isAnonymousBlock() && !object->isRenderNamedFlowThread())
object = object->parent();
- return object && object->isRenderFlowThread() ? toRenderFlowThread(object) : 0;
+ return object && object->isRenderNamedFlowThread() ? toRenderNamedFlowThread(object) : 0;
}
RenderObject* RenderObjectChildList::removeChildNode(RenderObject* owner, RenderObject* oldChild, bool fullRemove)
@@ -120,7 +120,7 @@ RenderObject* RenderObjectChildList::removeChildNode(RenderObject* owner, Render
oldChild->enclosingRenderFlowThread()->clearRenderBoxCustomStyle(toRenderBox(oldChild));
}
- if (RenderFlowThread* containerFlowThread = renderFlowThreadContainer(owner))
+ if (RenderNamedFlowThread* containerFlowThread = renderNamedFlowThreadContainer(owner))
containerFlowThread->removeFlowChild(oldChild);
#if ENABLE(SVG)
@@ -203,9 +203,10 @@ void RenderObjectChildList::appendChildNode(RenderObject* owner, RenderObject* n
if (newChild->isRenderRegion())
toRenderRegion(newChild)->attachRegion();
- if (RenderFlowThread* containerFlowThread = renderFlowThreadContainer(owner))
+ if (RenderNamedFlowThread* containerFlowThread = renderNamedFlowThreadContainer(owner))
containerFlowThread->addFlowChild(newChild);
}
+
RenderCounter::rendererSubtreeAttached(newChild);
RenderQuote::rendererSubtreeAttached(newChild);
newChild->setNeedsLayoutAndPrefWidthsRecalc(); // Goes up the containing block hierarchy.
@@ -269,7 +270,7 @@ void RenderObjectChildList::insertChildNode(RenderObject* owner, RenderObject* c
if (child->isRenderRegion())
toRenderRegion(child)->attachRegion();
- if (RenderFlowThread* containerFlowThread = renderFlowThreadContainer(owner))
+ if (RenderNamedFlowThread* containerFlowThread = renderNamedFlowThreadContainer(owner))
containerFlowThread->addFlowChild(child, beforeChild);
}
@@ -345,6 +346,88 @@ RenderObject* RenderObjectChildList::afterPseudoElementRenderer(const RenderObje
return last;
}
+void RenderObjectChildList::updateBeforeAfterStyle(RenderObject* child, PseudoId type, RenderStyle* pseudoElementStyle)
+{
+ if (!child || child->style()->styleType() != type)
+ return;
+
+ // We have generated content present still. We want to walk this content and update our
+ // style information with the new pseudo-element style.
+ child->setStyle(pseudoElementStyle);
+
+ RenderObject* beforeAfterParent = findBeforeAfterParent(child);
+ if (!beforeAfterParent)
+ return;
+
+ // When beforeAfterParent is not equal to child (e.g. in tables),
+ // we need to create new styles inheriting from pseudoElementStyle
+ // on all the intermediate parents (leaving their display same).
+ if (beforeAfterParent != child) {
+ RenderObject* curr = beforeAfterParent;
+ while (curr && curr != child) {
+ ASSERT(curr->isAnonymous());
+ RefPtr<RenderStyle> newStyle = RenderStyle::create();
+ newStyle->inheritFrom(pseudoElementStyle);
+ newStyle->setDisplay(curr->style()->display());
+ newStyle->setStyleType(curr->style()->styleType());
+ curr->setStyle(newStyle);
+ curr = curr->parent();
+ }
+ }
+
+ // Note that if we ever support additional types of generated content (which should be way off
+ // in the future), this code will need to be patched.
+ for (RenderObject* genChild = beforeAfterParent->firstChild(); genChild; genChild = genChild->nextSibling()) {
+ if (genChild->isText())
+ // Generated text content is a child whose style also needs to be set to the pseudo-element style.
+ genChild->setStyle(pseudoElementStyle);
+ else if (genChild->isImage()) {
+ // Images get an empty style that inherits from the pseudo.
+ RefPtr<RenderStyle> style = RenderStyle::create();
+ style->inheritFrom(pseudoElementStyle);
+ genChild->setStyle(style.release());
+ } else {
+ // RenderListItem may insert a list marker here. We do not need to care about this case.
+ // Otherwise, genChild must be a first-letter container. updateFirstLetter() will take care of it.
+ ASSERT(genChild->isListMarker() || genChild->style()->styleType() == FIRST_LETTER);
+ }
+ }
+}
+
+static RenderObject* createRenderForBeforeAfterContent(RenderObject* owner, const ContentData* content, RenderStyle* pseudoElementStyle)
+{
+ RenderObject* renderer = 0;
+ switch (content->type()) {
+ case CONTENT_NONE:
+ break;
+ case CONTENT_TEXT:
+ renderer = new (owner->renderArena()) RenderTextFragment(owner->document() /* anonymous object */, static_cast<const TextContentData*>(content)->text().impl());
+ renderer->setStyle(pseudoElementStyle);
+ break;
+ case CONTENT_OBJECT: {
+ RenderImage* image = new (owner->renderArena()) RenderImage(owner->document()); // anonymous object
+ RefPtr<RenderStyle> style = RenderStyle::create();
+ style->inheritFrom(pseudoElementStyle);
+ image->setStyle(style.release());
+ if (const StyleImage* styleImage = static_cast<const ImageContentData*>(content)->image())
+ image->setImageResource(RenderImageResourceStyleImage::create(const_cast<StyleImage*>(styleImage)));
+ else
+ image->setImageResource(RenderImageResource::create());
+ renderer = image;
+ break;
+ }
+ case CONTENT_COUNTER:
+ renderer = new (owner->renderArena()) RenderCounter(owner->document(), *static_cast<const CounterContentData*>(content)->counter());
+ renderer->setStyle(pseudoElementStyle);
+ break;
+ case CONTENT_QUOTE:
+ renderer = new (owner->renderArena()) RenderQuote(owner->document(), static_cast<const QuoteContentData*>(content)->quote());
+ renderer->setStyle(pseudoElementStyle);
+ break;
+ }
+ return renderer;
+}
+
void RenderObjectChildList::updateBeforeAfterContent(RenderObject* owner, PseudoId type, const RenderObject* styledObject)
{
// Double check that the document did in fact use generated content rules. Otherwise we should not have been called.
@@ -390,7 +473,7 @@ void RenderObjectChildList::updateBeforeAfterContent(RenderObject* owner, Pseudo
// If we don't want generated content any longer, or if we have generated content, but it's no longer
// identical to the new content data we want to build render objects for, then we nuke all
// of the old generated content.
- if (oldContentPresent && (!newContentWanted || Node::diff(child->style(), pseudoElementStyle) == Node::Detach)) {
+ if (oldContentPresent && (!newContentWanted || Node::diff(child->style(), pseudoElementStyle, owner->document()) == Node::Detach)) {
// Nuke the child.
if (child->style()->styleType() == type) {
oldContentPresent = false;
@@ -414,49 +497,7 @@ void RenderObjectChildList::updateBeforeAfterContent(RenderObject* owner, Pseudo
pseudoElementStyle->setDisplay(INLINE);
if (oldContentPresent) {
- if (child && child->style()->styleType() == type) {
- // We have generated content present still. We want to walk this content and update our
- // style information with the new pseudo-element style.
- child->setStyle(pseudoElementStyle);
-
- RenderObject* beforeAfterParent = findBeforeAfterParent(child);
- if (!beforeAfterParent)
- return;
-
- // When beforeAfterParent is not equal to child (e.g. in tables),
- // we need to create new styles inheriting from pseudoElementStyle
- // on all the intermediate parents (leaving their display same).
- if (beforeAfterParent != child) {
- RenderObject* curr = beforeAfterParent;
- while (curr && curr != child) {
- ASSERT(curr->isAnonymous());
- RefPtr<RenderStyle> newStyle = RenderStyle::create();
- newStyle->inheritFrom(pseudoElementStyle);
- newStyle->setDisplay(curr->style()->display());
- newStyle->setStyleType(curr->style()->styleType());
- curr->setStyle(newStyle);
- curr = curr->parent();
- }
- }
-
- // Note that if we ever support additional types of generated content (which should be way off
- // in the future), this code will need to be patched.
- for (RenderObject* genChild = beforeAfterParent->firstChild(); genChild; genChild = genChild->nextSibling()) {
- if (genChild->isText())
- // Generated text content is a child whose style also needs to be set to the pseudo-element style.
- genChild->setStyle(pseudoElementStyle);
- else if (genChild->isImage()) {
- // Images get an empty style that inherits from the pseudo.
- RefPtr<RenderStyle> style = RenderStyle::create();
- style->inheritFrom(pseudoElementStyle);
- genChild->setStyle(style.release());
- } else {
- // RenderListItem may insert a list marker here. We do not need to care about this case.
- // Otherwise, genChild must be a first-letter container. updateFirstLetter() will take care of it.
- ASSERT(genChild->isListMarker() || genChild->style()->styleType() == FIRST_LETTER);
- }
- }
- }
+ updateBeforeAfterStyle(child, type, pseudoElementStyle);
return; // We've updated the generated content. That's all we needed to do.
}
@@ -473,38 +514,10 @@ void RenderObjectChildList::updateBeforeAfterContent(RenderObject* owner, Pseudo
// Generated content consists of a single container that houses multiple children (specified
// by the content property). This generated content container gets the pseudo-element style set on it.
RenderObject* generatedContentContainer = 0;
-
+
// Walk our list of generated content and create render objects for each.
for (const ContentData* content = pseudoElementStyle->contentData(); content; content = content->next()) {
- RenderObject* renderer = 0;
- switch (content->type()) {
- case CONTENT_NONE:
- break;
- case CONTENT_TEXT:
- renderer = new (owner->renderArena()) RenderTextFragment(owner->document() /* anonymous object */, static_cast<const TextContentData*>(content)->text().impl());
- renderer->setStyle(pseudoElementStyle);
- break;
- case CONTENT_OBJECT: {
- RenderImage* image = new (owner->renderArena()) RenderImage(owner->document()); // anonymous object
- RefPtr<RenderStyle> style = RenderStyle::create();
- style->inheritFrom(pseudoElementStyle);
- image->setStyle(style.release());
- if (const StyleImage* styleImage = static_cast<const ImageContentData*>(content)->image())
- image->setImageResource(RenderImageResourceStyleImage::create(const_cast<StyleImage*>(styleImage)));
- else
- image->setImageResource(RenderImageResource::create());
- renderer = image;
- break;
- }
- case CONTENT_COUNTER:
- renderer = new (owner->renderArena()) RenderCounter(owner->document(), *static_cast<const CounterContentData*>(content)->counter());
- renderer->setStyle(pseudoElementStyle);
- break;
- case CONTENT_QUOTE:
- renderer = new (owner->renderArena()) RenderQuote(owner->document(), static_cast<const QuoteContentData*>(content)->quote());
- renderer->setStyle(pseudoElementStyle);
- break;
- }
+ RenderObject* renderer = createRenderForBeforeAfterContent(owner, content, pseudoElementStyle);
if (renderer) {
if (!generatedContentContainer) {
diff --git a/Source/WebCore/rendering/RenderObjectChildList.h b/Source/WebCore/rendering/RenderObjectChildList.h
index c8fc978e8..cfe902617 100644
--- a/Source/WebCore/rendering/RenderObjectChildList.h
+++ b/Source/WebCore/rendering/RenderObjectChildList.h
@@ -32,6 +32,7 @@
namespace WebCore {
class RenderObject;
+class RenderStyle;
class RenderObjectChildList {
public:
@@ -60,6 +61,8 @@ public:
RenderObject* afterPseudoElementRenderer(const RenderObject* owner) const;
private:
+ void updateBeforeAfterStyle(RenderObject* child, PseudoId type, RenderStyle* pseudoElementStyle);
+
RenderObject* m_firstChild;
RenderObject* m_lastChild;
};
diff --git a/Source/WebCore/rendering/RenderRegion.cpp b/Source/WebCore/rendering/RenderRegion.cpp
index 5b7692a6c..a7ba2eadc 100644
--- a/Source/WebCore/rendering/RenderRegion.cpp
+++ b/Source/WebCore/rendering/RenderRegion.cpp
@@ -30,24 +30,25 @@
#include "config.h"
#include "RenderRegion.h"
-#include "CSSStyleSelector.h"
#include "GraphicsContext.h"
#include "HitTestResult.h"
#include "IntRect.h"
#include "PaintInfo.h"
#include "RenderBoxRegionInfo.h"
-#include "RenderFlowThread.h"
+#include "RenderNamedFlowThread.h"
#include "RenderView.h"
+#include "StyleResolver.h"
namespace WebCore {
RenderRegion::RenderRegion(Node* node, RenderFlowThread* flowThread)
: RenderReplaced(node, IntSize())
, m_flowThread(flowThread)
- , m_parentFlowThread(0)
+ , m_parentNamedFlowThread(0)
, m_isValid(false)
, m_hasCustomRegionStyle(false)
, m_regionState(RegionUndefined)
+ , m_dispatchRegionLayoutUpdateEvent(false)
{
ASSERT(node->document()->cssRegionsEnabled());
}
@@ -174,7 +175,7 @@ void RenderRegion::styleDidChange(StyleDifference diff, const RenderStyle* oldSt
bool customRegionStyle = false;
if (node()) {
Element* regionElement = static_cast<Element*>(node());
- customRegionStyle = view()->document()->styleSelector()->checkRegionStyle(regionElement);
+ customRegionStyle = view()->document()->styleResolver()->checkRegionStyle(regionElement);
}
setHasCustomRegionStyle(customRegionStyle);
}
@@ -208,13 +209,13 @@ void RenderRegion::attachRegion()
// so we go up the rendering parents and check that this region is not part of the same
// flow that it actually needs to display. It would create a circular reference.
RenderObject* parentObject = parent();
- m_parentFlowThread = 0;
+ m_parentNamedFlowThread = 0;
for ( ; parentObject; parentObject = parentObject->parent()) {
- if (parentObject->isRenderFlowThread()) {
- m_parentFlowThread = toRenderFlowThread(parentObject);
+ if (parentObject->isRenderNamedFlowThread()) {
+ m_parentNamedFlowThread = toRenderNamedFlowThread(parentObject);
// Do not take into account a region that links a flow with itself. The dependency
// cannot change, so it is not worth adding it to the list.
- if (m_flowThread == m_parentFlowThread) {
+ if (m_flowThread == m_parentNamedFlowThread) {
m_flowThread = 0;
return;
}
@@ -245,7 +246,7 @@ RenderBoxRegionInfo* RenderRegion::setRenderBoxRegionInfo(const RenderBox* box,
if (!m_isValid || !m_flowThread)
return 0;
- OwnPtr<RenderBoxRegionInfo>& boxInfo = m_renderBoxRegionInfo.add(box, nullptr).first->second;
+ OwnPtr<RenderBoxRegionInfo>& boxInfo = m_renderBoxRegionInfo.add(box, nullptr).iterator->second;
if (boxInfo)
*boxInfo = RenderBoxRegionInfo(logicalLeftInset, logicalRightInset, containingBlockChainIsInset);
else
@@ -299,7 +300,7 @@ PassRefPtr<RenderStyle> RenderRegion::computeStyleInRegion(const RenderBox* box)
ASSERT(box->node() && box->node()->isElementNode());
Element* element = toElement(box->node());
- RefPtr<RenderStyle> renderBoxRegionStyle = box->view()->document()->styleSelector()->styleForElement(element, 0, false, false, this);
+ RefPtr<RenderStyle> renderBoxRegionStyle = box->view()->document()->styleResolver()->styleForElement(element, 0, DisallowStyleSharing, MatchAllRules, this);
m_renderBoxRegionStyle.add(box, renderBoxRegionStyle);
if (!box->hasBoxDecorations()) {
diff --git a/Source/WebCore/rendering/RenderRegion.h b/Source/WebCore/rendering/RenderRegion.h
index 70fa23b30..1e10bb3ba 100644
--- a/Source/WebCore/rendering/RenderRegion.h
+++ b/Source/WebCore/rendering/RenderRegion.h
@@ -37,6 +37,7 @@ namespace WebCore {
class RenderBox;
class RenderBoxRegionInfo;
class RenderFlowThread;
+class RenderNamedFlowThread;
class RenderRegion : public RenderReplaced {
public:
@@ -56,8 +57,8 @@ public:
void attachRegion();
void detachRegion();
+ RenderNamedFlowThread* parentNamedFlowThread() const { return m_parentNamedFlowThread; }
RenderFlowThread* flowThread() const { return m_flowThread; }
- RenderFlowThread* parentFlowThread() const { return m_parentFlowThread; }
// Valid regions do not create circular dependencies with other flows.
bool isValid() const { return m_isValid; }
@@ -92,6 +93,8 @@ public:
RegionState regionState() const { return isValid() ? m_regionState : RegionUndefined; }
void setRegionState(RegionState regionState) { m_regionState = regionState; }
+ void setDispatchRegionLayoutUpdateEvent(bool value) { m_dispatchRegionLayoutUpdateEvent = value; }
+ bool shouldDispatchRegionLayoutUpdateEvent() { return m_dispatchRegionLayoutUpdateEvent; }
private:
virtual const char* renderName() const { return "RenderRegion"; }
@@ -102,10 +105,10 @@ private:
RenderFlowThread* m_flowThread;
- // If this RenderRegion is displayed as part of another flow,
+ // If this RenderRegion is displayed as part of another named flow,
// we need to create a dependency tree, so that layout of the
// regions is always done before the regions themselves.
- RenderFlowThread* m_parentFlowThread;
+ RenderNamedFlowThread* m_parentNamedFlowThread;
LayoutRect m_regionRect;
// This map holds unique information about a block that is split across regions.
@@ -121,6 +124,7 @@ private:
bool m_isValid;
bool m_hasCustomRegionStyle;
RegionState m_regionState;
+ bool m_dispatchRegionLayoutUpdateEvent;
};
inline RenderRegion* toRenderRegion(RenderObject* object)
diff --git a/Source/WebCore/rendering/RenderRegionSet.cpp b/Source/WebCore/rendering/RenderRegionSet.cpp
new file mode 100644
index 000000000..f9699ac13
--- /dev/null
+++ b/Source/WebCore/rendering/RenderRegionSet.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "RenderRegionSet.h"
+
+namespace WebCore {
+
+RenderRegionSet::RenderRegionSet(Node* node, RenderFlowThread* flowThread)
+ : RenderRegion(node, flowThread)
+{
+}
+
+}
diff --git a/Source/WebCore/rendering/RenderRegionSet.h b/Source/WebCore/rendering/RenderRegionSet.h
new file mode 100644
index 000000000..3977dbc3b
--- /dev/null
+++ b/Source/WebCore/rendering/RenderRegionSet.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef RenderRegionSet_h
+#define RenderRegionSet_h
+
+#include "RenderRegion.h"
+#include "RenderBoxRegionInfo.h"
+
+namespace WebCore {
+
+class RenderFlowThread;
+
+// RenderRegionSet represents a set of regions that all have the same width and height. It is a "composite region box" that
+// can be used to represent a single run of contiguous regions.
+//
+// By combining runs of same-size columns or pages into a single object, we significantly reduce the number of unique RenderObjects
+// required to represent those objects.
+//
+// This class is abstract and is only intended for use by renderers that generate anonymous runs of identical regions, i.e.,
+// columns and printing. RenderMultiColumnSet and RenderPageSet represent runs of columns and pages respectively.
+//
+// FIXME: For now we derive from RenderRegion, but this may change at some point.
+
+class RenderRegionSet : public RenderRegion {
+public:
+ RenderRegionSet(Node*, RenderFlowThread*);
+
+private:
+ virtual const char* renderName() const = 0;
+};
+
+} // namespace WebCore
+
+#endif // RenderRegionSet_h
+
diff --git a/Source/WebCore/rendering/RenderReplaced.cpp b/Source/WebCore/rendering/RenderReplaced.cpp
index 39bacfa7f..fd6b881b3 100644
--- a/Source/WebCore/rendering/RenderReplaced.cpp
+++ b/Source/WebCore/rendering/RenderReplaced.cpp
@@ -2,6 +2,7 @@
* Copyright (C) 1999 Lars Knoll (knoll@kde.org)
* Copyright (C) 2000 Dirk Mueller (mueller@kde.org)
* Copyright (C) 2004, 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) Research In Motion Limited 2011-2012. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -43,7 +44,6 @@ const int cDefaultHeight = 150;
RenderReplaced::RenderReplaced(Node* node)
: RenderBox(node)
, m_intrinsicSize(cDefaultWidth, cDefaultHeight)
- , m_hasIntrinsicSize(false)
{
setReplaced(true);
}
@@ -51,7 +51,6 @@ RenderReplaced::RenderReplaced(Node* node)
RenderReplaced::RenderReplaced(Node* node, const IntSize& intrinsicSize)
: RenderBox(node)
, m_intrinsicSize(intrinsicSize)
- , m_hasIntrinsicSize(true)
{
setReplaced(true);
}
@@ -146,7 +145,7 @@ void RenderReplaced::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
else {
// Push a clip if we have a border radius, since we want to round the foreground content that gets painted.
paintInfo.context->save();
- paintInfo.context->addRoundedRectClip(style()->getRoundedBorderFor(paintRect));
+ paintInfo.context->addRoundedRectClip(style()->getRoundedBorderFor(paintRect, view()));
}
}
@@ -162,7 +161,7 @@ void RenderReplaced::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
if (drawSelectionTint) {
LayoutRect selectionPaintingRect = localSelectionRect();
selectionPaintingRect.moveBy(adjustedPaintOffset);
- paintInfo.context->fillRect(selectionPaintingRect, selectionBackgroundColor(), style()->colorSpace());
+ paintInfo.context->fillRect(pixelSnappedIntRect(selectionPaintingRect), selectionBackgroundColor(), style()->colorSpace());
}
}
@@ -202,24 +201,6 @@ bool RenderReplaced::shouldPaint(PaintInfo& paintInfo, const LayoutPoint& paintO
return true;
}
-int RenderReplaced::computeIntrinsicLogicalWidth(RenderBox* contentRenderer, bool includeMaxWidth) const
-{
- if (m_hasIntrinsicSize)
- return computeReplacedLogicalWidthRespectingMinMaxWidth(calcAspectRatioLogicalWidth(), includeMaxWidth);
- ASSERT(contentRenderer);
- ASSERT(contentRenderer->style());
- return contentRenderer->computeReplacedLogicalWidthRespectingMinMaxWidth(contentRenderer->computeReplacedLogicalWidthUsing(contentRenderer->style()->logicalWidth()), includeMaxWidth);
-}
-
-int RenderReplaced::computeIntrinsicLogicalHeight(RenderBox* contentRenderer) const
-{
- if (m_hasIntrinsicSize)
- return computeReplacedLogicalHeightRespectingMinMaxHeight(calcAspectRatioLogicalHeight());
- ASSERT(contentRenderer);
- ASSERT(contentRenderer->style());
- return contentRenderer->computeReplacedLogicalHeightRespectingMinMaxHeight(contentRenderer->computeReplacedLogicalHeightUsing(contentRenderer->style()->logicalHeight()));
-}
-
static inline RenderBlock* firstContainingBlockWithLogicalWidth(const RenderReplaced* replaced)
{
// We have to lookup the containing block, which has an explicit width, which must not be equal to our direct containing block.
@@ -282,6 +263,56 @@ bool RenderReplaced::hasReplacedLogicalHeight() const
return false;
}
+static inline bool rendererHasAspectRatio(const RenderObject* renderer)
+{
+ ASSERT(renderer);
+ return renderer->isImage() || renderer->isCanvas() || renderer->isVideo();
+}
+
+void RenderReplaced::computeIntrinsicRatioInformationForRenderBox(RenderBox* contentRenderer, FloatSize& intrinsicSize, double& intrinsicRatio, bool& isPercentageIntrinsicSize) const
+{
+ if (contentRenderer) {
+ contentRenderer->computeIntrinsicRatioInformation(intrinsicSize, intrinsicRatio, isPercentageIntrinsicSize);
+ if (intrinsicRatio)
+ ASSERT(!isPercentageIntrinsicSize);
+
+ // Handle zoom & vertical writing modes here, as the embedded document doesn't know about them.
+ if (!isPercentageIntrinsicSize)
+ intrinsicSize.scale(style()->effectiveZoom());
+
+ if (intrinsicRatio && !isHorizontalWritingMode())
+ intrinsicRatio = 1 / intrinsicRatio;
+
+ if (rendererHasAspectRatio(this) && isPercentageIntrinsicSize)
+ intrinsicRatio = 1;
+ return;
+ }
+
+ // This code path can't yield percentage intrinsic sizes, assert that.
+ computeIntrinsicRatioInformation(intrinsicSize, intrinsicRatio, isPercentageIntrinsicSize);
+ ASSERT(!isPercentageIntrinsicSize);
+}
+
+void RenderReplaced::computeIntrinsicRatioInformation(FloatSize& intrinsicSize, double& intrinsicRatio, bool& isPercentageIntrinsicSize) const
+{
+ // If there's an embeddedContentBox() of a remote, referenced document available, this code-path should never be used.
+ ASSERT(!embeddedContentBox());
+ isPercentageIntrinsicSize = false;
+ intrinsicSize = FloatSize(intrinsicLogicalWidth(), intrinsicLogicalHeight());
+
+ // Figure out if we need to compute an intrinsic ratio.
+ if (intrinsicSize.isEmpty() || !rendererHasAspectRatio(this))
+ return;
+
+ intrinsicRatio = intrinsicSize.width() / intrinsicSize.height();
+ if (style()->logicalWidth().isAuto() && style()->logicalHeight().isAuto()) {
+ // We can't multiply or divide by 'intrinsicRatio' here, it breaks tests, like fast/images/zoomed-img-size.html, which
+ // can only be fixed once subpixel precision is available for things like intrinsicWidth/Height - which include zoom!
+ intrinsicSize.setWidth(RenderBox::computeReplacedLogicalHeight() * intrinsicLogicalWidth() / intrinsicLogicalHeight());
+ intrinsicSize.setHeight(RenderBox::computeReplacedLogicalWidth() * intrinsicLogicalHeight() / intrinsicLogicalWidth());
+ }
+}
+
LayoutUnit RenderReplaced::computeReplacedLogicalWidth(bool includeMaxWidth) const
{
if (style()->logicalWidth().isSpecified())
@@ -293,33 +324,25 @@ LayoutUnit RenderReplaced::computeReplacedLogicalWidth(bool includeMaxWidth) con
bool isPercentageIntrinsicSize = false;
double intrinsicRatio = 0;
FloatSize intrinsicSize;
- if (contentRenderer)
- contentRenderer->computeIntrinsicRatioInformation(intrinsicSize, intrinsicRatio, isPercentageIntrinsicSize);
- else
- computeIntrinsicRatioInformation(intrinsicSize, intrinsicRatio, isPercentageIntrinsicSize);
-
- if (intrinsicRatio && !isHorizontalWritingMode())
- intrinsicRatio = 1 / intrinsicRatio;
+ computeIntrinsicRatioInformationForRenderBox(contentRenderer, intrinsicSize, intrinsicRatio, isPercentageIntrinsicSize);
+ // FIXME: Remove unnecessary round/roundToInt calls from this method when layout is off ints: webkit.org/b/63656
if (style()->logicalWidth().isAuto()) {
bool heightIsAuto = style()->logicalHeight().isAuto();
- bool hasIntrinsicWidth = m_hasIntrinsicSize || (!isPercentageIntrinsicSize && intrinsicSize.width() > 0);
+ bool hasIntrinsicWidth = !isPercentageIntrinsicSize && intrinsicSize.width() > 0;
// If 'height' and 'width' both have computed values of 'auto' and the element also has an intrinsic width, then that intrinsic width is the used value of 'width'.
- if (heightIsAuto && hasIntrinsicWidth) {
- if (m_hasIntrinsicSize)
- return computeReplacedLogicalWidthRespectingMinMaxWidth(calcAspectRatioLogicalWidth(), includeMaxWidth);
- return static_cast<LayoutUnit>(intrinsicSize.width() * style()->effectiveZoom());
- }
+ if (heightIsAuto && hasIntrinsicWidth)
+ return computeReplacedLogicalWidthRespectingMinMaxWidth(roundToInt(intrinsicSize.width()), includeMaxWidth);
- bool hasIntrinsicHeight = m_hasIntrinsicSize || (!isPercentageIntrinsicSize && intrinsicSize.height() > 0);
+ bool hasIntrinsicHeight = !isPercentageIntrinsicSize && intrinsicSize.height() > 0;
if (intrinsicRatio || isPercentageIntrinsicSize) {
// If 'height' and 'width' both have computed values of 'auto' and the element has no intrinsic width, but does have an intrinsic height and intrinsic ratio;
// or if 'width' has a computed value of 'auto', 'height' has some other computed value, and the element does have an intrinsic ratio; then the used value
// of 'width' is: (used height) * (intrinsic ratio)
if (intrinsicRatio && ((heightIsAuto && !hasIntrinsicWidth && hasIntrinsicHeight) || !heightIsAuto)) {
LayoutUnit logicalHeight = computeReplacedLogicalHeightUsing(style()->logicalHeight());
- return computeReplacedLogicalWidthRespectingMinMaxWidth(static_cast<LayoutUnit>(ceil(logicalHeight * intrinsicRatio)));
+ return computeReplacedLogicalWidthRespectingMinMaxWidth(roundToInt(round(logicalHeight * intrinsicRatio)));
}
// If 'height' and 'width' both have computed values of 'auto' and the element has an intrinsic ratio but no intrinsic height or width, then the used value of
@@ -335,26 +358,24 @@ LayoutUnit RenderReplaced::computeReplacedLogicalWidth(bool includeMaxWidth) con
logicalWidth = containingBlock()->availableLogicalWidth();
// This solves above equation for 'width' (== logicalWidth).
- LayoutUnit marginStart = style()->marginStart().calcMinValue(logicalWidth);
- LayoutUnit marginEnd = style()->marginEnd().calcMinValue(logicalWidth);
- logicalWidth = max(0, logicalWidth - (marginStart + marginEnd + (width() - clientWidth())));
+ LayoutUnit marginStart = minimumValueForLength(style()->marginStart(), logicalWidth);
+ LayoutUnit marginEnd = minimumValueForLength(style()->marginEnd(), logicalWidth);
+ logicalWidth = max(ZERO_LAYOUT_UNIT, logicalWidth - (marginStart + marginEnd + (width() - clientWidth())));
if (isPercentageIntrinsicSize)
- // FIXME: Remove unnecessary rounding when layout is off ints: webkit.org/b/63656
- logicalWidth = static_cast<LayoutUnit>(round(logicalWidth * intrinsicSize.width() / 100));
- return computeReplacedLogicalWidthRespectingMinMaxWidth(logicalWidth);
+ logicalWidth = roundToInt(logicalWidth * intrinsicSize.width() / 100);
+ return computeReplacedLogicalWidthRespectingMinMaxWidth(logicalWidth, includeMaxWidth);
}
}
// Otherwise, if 'width' has a computed value of 'auto', and the element has an intrinsic width, then that intrinsic width is the used value of 'width'.
- if (hasIntrinsicWidth) {
- if (isPercentageIntrinsicSize || m_hasIntrinsicSize)
- return computeReplacedLogicalWidthRespectingMinMaxWidth(calcAspectRatioLogicalWidth(), includeMaxWidth);
- return static_cast<LayoutUnit>(intrinsicSize.width() * style()->effectiveZoom());
- }
+ if (hasIntrinsicWidth)
+ return computeReplacedLogicalWidthRespectingMinMaxWidth(roundToInt(intrinsicSize.width()), includeMaxWidth);
// Otherwise, if 'width' has a computed value of 'auto', but none of the conditions above are met, then the used value of 'width' becomes 300px. If 300px is too
// wide to fit the device, UAs should use the width of the largest rectangle that has a 2:1 ratio and fits the device instead.
- return computeReplacedLogicalWidthRespectingMinMaxWidth(cDefaultWidth, includeMaxWidth);
+ // Note: We fall through and instead return intrinsicLogicalWidth() here - to preserve existing WebKit behavior, which might or might not be correct, or desired.
+ // Changing this to return cDefaultWidth, will affect lots of test results. Eg. some tests assume that a blank <img> tag (which implies width/height=auto)
+ // has no intrinsic size, which is wrong per CSS 2.1, but matches our behavior since a long time.
}
return computeReplacedLogicalWidthRespectingMinMaxWidth(intrinsicLogicalWidth(), includeMaxWidth);
@@ -372,59 +393,28 @@ LayoutUnit RenderReplaced::computeReplacedLogicalHeight() const
bool isPercentageIntrinsicSize = false;
double intrinsicRatio = 0;
FloatSize intrinsicSize;
- if (contentRenderer)
- contentRenderer->computeIntrinsicRatioInformation(intrinsicSize, intrinsicRatio, isPercentageIntrinsicSize);
- else
- computeIntrinsicRatioInformation(intrinsicSize, intrinsicRatio, isPercentageIntrinsicSize);
-
- if (intrinsicRatio && !isHorizontalWritingMode())
- intrinsicRatio = 1 / intrinsicRatio;
+ computeIntrinsicRatioInformationForRenderBox(contentRenderer, intrinsicSize, intrinsicRatio, isPercentageIntrinsicSize);
+ // FIXME: Remove unnecessary round/roundToInt calls from this method when layout is off ints: webkit.org/b/63656
bool widthIsAuto = style()->logicalWidth().isAuto();
- bool hasIntrinsicHeight = m_hasIntrinsicSize || (!isPercentageIntrinsicSize && intrinsicSize.height() > 0);
+ bool hasIntrinsicHeight = !isPercentageIntrinsicSize && intrinsicSize.height() > 0;
// If 'height' and 'width' both have computed values of 'auto' and the element also has an intrinsic height, then that intrinsic height is the used value of 'height'.
- if (widthIsAuto && hasIntrinsicHeight) {
- if (m_hasIntrinsicSize)
- return computeReplacedLogicalHeightRespectingMinMaxHeight(calcAspectRatioLogicalHeight());
- return static_cast<LayoutUnit>(intrinsicSize.height() * style()->effectiveZoom());
- }
+ if (widthIsAuto && hasIntrinsicHeight)
+ return computeReplacedLogicalHeightRespectingMinMaxHeight(roundToInt(intrinsicSize.height()));
// Otherwise, if 'height' has a computed value of 'auto', and the element has an intrinsic ratio then the used value of 'height' is:
// (used width) / (intrinsic ratio)
- if (intrinsicRatio && !isPercentageIntrinsicSize) {
- // FIXME: Remove unnecessary rounding when layout is off ints: webkit.org/b/63656
- return computeReplacedLogicalHeightRespectingMinMaxHeight(round(availableLogicalWidth() / intrinsicRatio));
- }
+ if (intrinsicRatio)
+ return computeReplacedLogicalHeightRespectingMinMaxHeight(roundToInt(round(availableLogicalWidth() / intrinsicRatio)));
// Otherwise, if 'height' has a computed value of 'auto', and the element has an intrinsic height, then that intrinsic height is the used value of 'height'.
- if (hasIntrinsicHeight) {
- if (m_hasIntrinsicSize)
- return computeReplacedLogicalHeightRespectingMinMaxHeight(calcAspectRatioLogicalHeight());
- return static_cast<LayoutUnit>(intrinsicSize.height() * style()->effectiveZoom());
- }
+ if (hasIntrinsicHeight)
+ return computeReplacedLogicalHeightRespectingMinMaxHeight(roundToInt(intrinsicSize.height()));
// Otherwise, if 'height' has a computed value of 'auto', but none of the conditions above are met, then the used value of 'height' must be set to the height
// of the largest rectangle that has a 2:1 ratio, has a height not greater than 150px, and has a width not greater than the device width.
- return computeReplacedLogicalHeightRespectingMinMaxHeight(cDefaultHeight);
-}
-
-int RenderReplaced::calcAspectRatioLogicalWidth() const
-{
- int intrinsicWidth = intrinsicLogicalWidth();
- int intrinsicHeight = intrinsicLogicalHeight();
- if (!intrinsicHeight)
- return 0;
- return RenderBox::computeReplacedLogicalHeight() * intrinsicWidth / intrinsicHeight;
-}
-
-int RenderReplaced::calcAspectRatioLogicalHeight() const
-{
- int intrinsicWidth = intrinsicLogicalWidth();
- int intrinsicHeight = intrinsicLogicalHeight();
- if (!intrinsicWidth)
- return 0;
- return RenderBox::computeReplacedLogicalWidth() * intrinsicHeight / intrinsicWidth;
+ return computeReplacedLogicalHeightRespectingMinMaxHeight(intrinsicLogicalHeight());
}
void RenderReplaced::computePreferredLogicalWidths()
@@ -435,7 +425,7 @@ void RenderReplaced::computePreferredLogicalWidths()
m_maxPreferredLogicalWidth = computeReplacedLogicalWidth(false) + borderAndPadding;
if (style()->maxWidth().isFixed())
- m_maxPreferredLogicalWidth = min(m_maxPreferredLogicalWidth, style()->maxWidth().value() + (style()->boxSizing() == CONTENT_BOX ? borderAndPadding : zeroLayoutUnit));
+ m_maxPreferredLogicalWidth = min<LayoutUnit>(m_maxPreferredLogicalWidth, style()->maxWidth().value() + (style()->boxSizing() == CONTENT_BOX ? borderAndPadding : ZERO_LAYOUT_UNIT));
if (hasRelativeDimensions())
m_minPreferredLogicalWidth = 0;
@@ -488,20 +478,20 @@ LayoutRect RenderReplaced::selectionRectForRepaint(RenderBoxModelObject* repaint
return rect;
}
-IntRect RenderReplaced::localSelectionRect(bool checkWhetherSelected) const
+LayoutRect RenderReplaced::localSelectionRect(bool checkWhetherSelected) const
{
if (checkWhetherSelected && !isSelected())
- return IntRect();
+ return LayoutRect();
if (!m_inlineBoxWrapper)
// We're a block-level replaced element. Just return our own dimensions.
- return IntRect(IntPoint(), size());
+ return LayoutRect(LayoutPoint(), size());
RootInlineBox* root = m_inlineBoxWrapper->root();
- int newLogicalTop = root->block()->style()->isFlippedBlocksWritingMode() ? m_inlineBoxWrapper->logicalBottom() - root->selectionBottom() : root->selectionTop() - m_inlineBoxWrapper->logicalTop();
+ LayoutUnit newLogicalTop = root->block()->style()->isFlippedBlocksWritingMode() ? m_inlineBoxWrapper->logicalBottom() - root->selectionBottom() : root->selectionTop() - m_inlineBoxWrapper->logicalTop();
if (root->block()->style()->isHorizontalWritingMode())
- return IntRect(0, newLogicalTop, width(), root->selectionHeight());
- return IntRect(newLogicalTop, 0, root->selectionHeight(), height());
+ return LayoutRect(0, newLogicalTop, width(), root->selectionHeight());
+ return LayoutRect(newLogicalTop, 0, root->selectionHeight(), height());
}
void RenderReplaced::setSelectionState(SelectionState state)
@@ -537,17 +527,6 @@ bool RenderReplaced::isSelected() const
return false;
}
-IntSize RenderReplaced::intrinsicSize() const
-{
- return m_intrinsicSize;
-}
-
-void RenderReplaced::setIntrinsicSize(const IntSize& size)
-{
- ASSERT(m_hasIntrinsicSize);
- m_intrinsicSize = size;
-}
-
LayoutRect RenderReplaced::clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer) const
{
if (style()->visibility() != VISIBLE && !enclosingLayer()->hasVisibleContent())
diff --git a/Source/WebCore/rendering/RenderReplaced.h b/Source/WebCore/rendering/RenderReplaced.h
index 1c6ebbc14..9ebc634b0 100644
--- a/Source/WebCore/rendering/RenderReplaced.h
+++ b/Source/WebCore/rendering/RenderReplaced.h
@@ -43,7 +43,8 @@ protected:
virtual void layout();
- virtual IntSize intrinsicSize() const;
+ virtual IntSize intrinsicSize() const { return m_intrinsicSize; }
+ virtual void computeIntrinsicRatioInformation(FloatSize& intrinsicSize, double& intrinsicRatio, bool& isPercentageIntrinsicSize) const;
virtual int minimumReplacedHeight() const { return 0; }
@@ -53,28 +54,20 @@ protected:
virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
- void setIntrinsicSize(const IntSize&);
+ void setIntrinsicSize(const IntSize& intrinsicSize) { m_intrinsicSize = intrinsicSize; }
virtual void intrinsicSizeChanged();
- void setHasIntrinsicSize() { m_hasIntrinsicSize = true; }
virtual void paint(PaintInfo&, const LayoutPoint&);
bool shouldPaint(PaintInfo&, const LayoutPoint&);
- IntRect localSelectionRect(bool checkWhetherSelected = true) const; // This is in local coordinates, but it's a physical rect (so the top left corner is physical top left).
+ LayoutRect localSelectionRect(bool checkWhetherSelected = true) const; // This is in local coordinates, but it's a physical rect (so the top left corner is physical top left).
private:
virtual RenderBox* embeddedContentBox() const { return 0; }
- int computeIntrinsicLogicalWidth(RenderBox* contentRenderer, bool includeMaxWidth) const;
- int computeIntrinsicLogicalHeight(RenderBox* contentRenderer) const;
-
virtual const char* renderName() const { return "RenderReplaced"; }
virtual bool canHaveChildren() const { return false; }
virtual void computePreferredLogicalWidths();
-
- int calcAspectRatioLogicalWidth() const;
- int calcAspectRatioLogicalHeight() const;
-
virtual void paintReplaced(PaintInfo&, const LayoutPoint&) { }
virtual LayoutRect clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer) const;
@@ -84,9 +77,9 @@ private:
virtual bool canBeSelectionLeaf() const { return true; }
virtual LayoutRect selectionRectForRepaint(RenderBoxModelObject* repaintContainer, bool clipToVisibleContent = true);
+ void computeIntrinsicRatioInformationForRenderBox(RenderBox*, FloatSize& intrinsicSize, double& intrinsicRatio, bool& isPercentageIntrinsicSize) const;
IntSize m_intrinsicSize;
- bool m_hasIntrinsicSize;
};
}
diff --git a/Source/WebCore/rendering/RenderRuby.cpp b/Source/WebCore/rendering/RenderRuby.cpp
index 41604d6ac..390db2f56 100644
--- a/Source/WebCore/rendering/RenderRuby.cpp
+++ b/Source/WebCore/rendering/RenderRuby.cpp
@@ -84,9 +84,7 @@ static inline RenderBlock* rubyAfterBlock(const RenderObject* ruby)
static RenderBlock* createAnonymousRubyInlineBlock(RenderObject* ruby)
{
- RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyle(ruby->style());
- newStyle->setDisplay(INLINE_BLOCK);
-
+ RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(ruby->style(), INLINE_BLOCK);
RenderBlock* newBlock = new (ruby->renderArena()) RenderBlock(ruby->document() /* anonymous box */);
newBlock->setStyle(newStyle.release());
return newBlock;
diff --git a/Source/WebCore/rendering/RenderRubyBase.cpp b/Source/WebCore/rendering/RenderRubyBase.cpp
index d62795538..87402f713 100644
--- a/Source/WebCore/rendering/RenderRubyBase.cpp
+++ b/Source/WebCore/rendering/RenderRubyBase.cpp
@@ -58,13 +58,9 @@ void RenderRubyBase::moveChildren(RenderRubyBase* toBase, RenderObject* beforeCh
// This function removes all children that are before (!) beforeChild
// and appends them to toBase.
ASSERT_ARG(toBase, toBase);
-
- // First make sure that beforeChild (if set) is indeed a direct child of this.
- // Inline children might be wrapped in an anonymous block if there's a continuation.
- // Theoretically, in ruby bases, this can happen with only the first such a child,
- // so it should be OK to just climb the tree.
- while (beforeChild && beforeChild->parent() != this)
- beforeChild = beforeChild->parent();
+
+ if (beforeChild && beforeChild->parent() != this)
+ beforeChild = splitAnonymousBoxesAroundChild(beforeChild);
if (childrenInline())
moveInlineChildren(toBase, beforeChild);
diff --git a/Source/WebCore/rendering/RenderRubyRun.cpp b/Source/WebCore/rendering/RenderRubyRun.cpp
index 530c6bdb2..716e55f05 100644
--- a/Source/WebCore/rendering/RenderRubyRun.cpp
+++ b/Source/WebCore/rendering/RenderRubyRun.cpp
@@ -74,6 +74,9 @@ bool RenderRubyRun::isEmpty() const
RenderRubyText* RenderRubyRun::rubyText() const
{
RenderObject* child = firstChild();
+ // If in future it becomes necessary to support floating or positioned ruby text,
+ // layout will have to be changed to handle them properly.
+ ASSERT(!child || !child->isRubyText() || !child->isFloatingOrPositioned());
return child && child->isRubyText() ? static_cast<RenderRubyText*>(child) : 0;
}
@@ -196,8 +199,7 @@ void RenderRubyRun::removeChild(RenderObject* child)
RenderRubyBase* RenderRubyRun::createRubyBase() const
{
RenderRubyBase* rb = new (renderArena()) RenderRubyBase(document() /* anonymous */);
- RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyle(style());
- newStyle->setDisplay(BLOCK);
+ RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(style(), BLOCK);
newStyle->setTextAlign(CENTER); // FIXME: use WEBKIT_CENTER?
rb->setStyle(newStyle.release());
return rb;
@@ -207,8 +209,7 @@ RenderRubyRun* RenderRubyRun::staticCreateRubyRun(const RenderObject* parentRuby
{
ASSERT(parentRuby && parentRuby->isRuby());
RenderRubyRun* rr = new (parentRuby->renderArena()) RenderRubyRun(parentRuby->document() /* anonymous */);
- RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyle(parentRuby->style());
- newStyle->setDisplay(INLINE_BLOCK);
+ RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(parentRuby->style(), INLINE_BLOCK);
rr->setStyle(newStyle.release());
return rr;
}
@@ -220,7 +221,7 @@ RenderObject* RenderRubyRun::layoutSpecialExcludedChild(bool relayoutChildren)
if (!rt)
return 0;
if (relayoutChildren)
- rt->setChildNeedsLayout(true, false);
+ rt->setChildNeedsLayout(true, MarkOnlyThis);
rt->layoutIfNeeded();
return rt;
}
diff --git a/Source/WebCore/rendering/RenderScrollbar.cpp b/Source/WebCore/rendering/RenderScrollbar.cpp
index 6f6fd53ea..0c50c0d39 100644
--- a/Source/WebCore/rendering/RenderScrollbar.cpp
+++ b/Source/WebCore/rendering/RenderScrollbar.cpp
@@ -297,27 +297,26 @@ IntRect RenderScrollbar::buttonRect(ScrollbarPart partType)
bool isHorizontal = orientation() == HorizontalScrollbar;
if (partType == BackButtonStartPart)
- return IntRect(location(), IntSize(isHorizontal ? partRenderer->width() : width(), isHorizontal ? height() : partRenderer->height()));
+ return IntRect(location(), IntSize(isHorizontal ? partRenderer->pixelSnappedWidth() : width(), isHorizontal ? height() : partRenderer->pixelSnappedHeight()));
if (partType == ForwardButtonEndPart)
- return IntRect(isHorizontal ? x() + width() - partRenderer->width() : x(),
-
- isHorizontal ? y() : y() + height() - partRenderer->height(),
- isHorizontal ? partRenderer->width() : width(),
- isHorizontal ? height() : partRenderer->height());
+ return IntRect(isHorizontal ? x() + width() - partRenderer->pixelSnappedWidth() : x(),
+ isHorizontal ? y() : y() + height() - partRenderer->pixelSnappedHeight(),
+ isHorizontal ? partRenderer->pixelSnappedWidth() : width(),
+ isHorizontal ? height() : partRenderer->pixelSnappedHeight());
if (partType == ForwardButtonStartPart) {
IntRect previousButton = buttonRect(BackButtonStartPart);
return IntRect(isHorizontal ? x() + previousButton.width() : x(),
isHorizontal ? y() : y() + previousButton.height(),
- isHorizontal ? partRenderer->width() : width(),
- isHorizontal ? height() : partRenderer->height());
+ isHorizontal ? partRenderer->pixelSnappedWidth() : width(),
+ isHorizontal ? height() : partRenderer->pixelSnappedHeight());
}
IntRect followingButton = buttonRect(ForwardButtonEndPart);
- return IntRect(isHorizontal ? x() + width() - followingButton.width() - partRenderer->width() : x(),
- isHorizontal ? y() : y() + height() - followingButton.height() - partRenderer->height(),
- isHorizontal ? partRenderer->width() : width(),
- isHorizontal ? height() : partRenderer->height());
+ return IntRect(isHorizontal ? x() + width() - followingButton.width() - partRenderer->pixelSnappedWidth() : x(),
+ isHorizontal ? y() : y() + height() - followingButton.height() - partRenderer->pixelSnappedHeight(),
+ isHorizontal ? partRenderer->pixelSnappedWidth() : width(),
+ isHorizontal ? height() : partRenderer->pixelSnappedHeight());
}
IntRect RenderScrollbar::trackRect(int startLength, int endLength)
@@ -327,16 +326,16 @@ IntRect RenderScrollbar::trackRect(int startLength, int endLength)
part->layout();
if (orientation() == HorizontalScrollbar) {
- int marginLeft = part ? part->marginLeft() : 0;
- int marginRight = part ? part->marginRight() : 0;
+ int marginLeft = part ? static_cast<int>(part->marginLeft()) : 0;
+ int marginRight = part ? static_cast<int>(part->marginRight()) : 0;
startLength += marginLeft;
endLength += marginRight;
int totalLength = startLength + endLength;
return IntRect(x() + startLength, y(), width() - totalLength, height());
}
- int marginTop = part ? part->marginTop() : 0;
- int marginBottom = part ? part->marginBottom() : 0;
+ int marginTop = part ? static_cast<int>(part->marginTop()) : 0;
+ int marginBottom = part ? static_cast<int>(part->marginBottom()) : 0;
startLength += marginTop;
endLength += marginBottom;
int totalLength = startLength + endLength;
diff --git a/Source/WebCore/rendering/RenderScrollbarPart.cpp b/Source/WebCore/rendering/RenderScrollbarPart.cpp
index cbae68c02..1a45be2de 100644
--- a/Source/WebCore/rendering/RenderScrollbarPart.cpp
+++ b/Source/WebCore/rendering/RenderScrollbarPart.cpp
@@ -79,41 +79,43 @@ void RenderScrollbarPart::layoutVerticalPart()
}
}
-static int calcScrollbarThicknessUsing(const Length& l, int containingLength)
+static int calcScrollbarThicknessUsing(const Length& length, int containingLength, RenderView* renderView)
{
- if (l.isIntrinsicOrAuto())
+ if (length.isIntrinsicOrAuto())
return ScrollbarTheme::theme()->scrollbarThickness();
- return l.calcMinValue(containingLength);
+ return minimumValueForLength(length, containingLength, renderView);
}
void RenderScrollbarPart::computeScrollbarWidth()
{
if (!m_scrollbar->owningRenderer())
return;
+ RenderView* renderView = view();
int visibleSize = m_scrollbar->owningRenderer()->width() - m_scrollbar->owningRenderer()->borderLeft() - m_scrollbar->owningRenderer()->borderRight();
- int w = calcScrollbarThicknessUsing(style()->width(), visibleSize);
- int minWidth = calcScrollbarThicknessUsing(style()->minWidth(), visibleSize);
- int maxWidth = style()->maxWidth().isUndefined() ? w : calcScrollbarThicknessUsing(style()->maxWidth(), visibleSize);
+ int w = calcScrollbarThicknessUsing(style()->width(), visibleSize, renderView);
+ int minWidth = calcScrollbarThicknessUsing(style()->minWidth(), visibleSize, renderView);
+ int maxWidth = style()->maxWidth().isUndefined() ? w : calcScrollbarThicknessUsing(style()->maxWidth(), visibleSize, renderView);
setWidth(max(minWidth, min(maxWidth, w)));
// Buttons and track pieces can all have margins along the axis of the scrollbar.
- m_marginLeft = style()->marginLeft().calcMinValue(visibleSize);
- m_marginRight = style()->marginRight().calcMinValue(visibleSize);
+ m_marginLeft = minimumValueForLength(style()->marginLeft(), visibleSize, renderView);
+ m_marginRight = minimumValueForLength(style()->marginRight(), visibleSize, renderView);
}
void RenderScrollbarPart::computeScrollbarHeight()
{
if (!m_scrollbar->owningRenderer())
return;
+ RenderView* renderView = view();
int visibleSize = m_scrollbar->owningRenderer()->height() - m_scrollbar->owningRenderer()->borderTop() - m_scrollbar->owningRenderer()->borderBottom();
- int h = calcScrollbarThicknessUsing(style()->height(), visibleSize);
- int minHeight = calcScrollbarThicknessUsing(style()->minHeight(), visibleSize);
- int maxHeight = style()->maxHeight().isUndefined() ? h : calcScrollbarThicknessUsing(style()->maxHeight(), visibleSize);
+ int h = calcScrollbarThicknessUsing(style()->height(), visibleSize, renderView);
+ int minHeight = calcScrollbarThicknessUsing(style()->minHeight(), visibleSize, renderView);
+ int maxHeight = style()->maxHeight().isUndefined() ? h : calcScrollbarThicknessUsing(style()->maxHeight(), visibleSize, renderView);
setHeight(max(minHeight, min(maxHeight, h)));
// Buttons and track pieces can all have margins along the axis of the scrollbar.
- m_marginTop = style()->marginTop().calcMinValue(visibleSize);
- m_marginBottom = style()->marginBottom().calcMinValue(visibleSize);
+ m_marginTop = minimumValueForLength(style()->marginTop(), visibleSize, renderView);
+ m_marginBottom = minimumValueForLength(style()->marginBottom(), visibleSize, renderView);
}
void RenderScrollbarPart::computePreferredLogicalWidths()
@@ -170,7 +172,7 @@ void RenderScrollbarPart::paintIntoRect(GraphicsContext* graphicsContext, const
return;
// Now do the paint.
- PaintInfo paintInfo(graphicsContext, rect, PaintPhaseBlockBackground, false, 0, 0, 0);
+ PaintInfo paintInfo(graphicsContext, pixelSnappedIntRect(rect), PaintPhaseBlockBackground, false, 0, 0, 0);
paint(paintInfo, paintOffset);
paintInfo.phase = PaintPhaseChildBlockBackgrounds;
paint(paintInfo, paintOffset);
diff --git a/Source/WebCore/rendering/RenderScrollbarPart.h b/Source/WebCore/rendering/RenderScrollbarPart.h
index e0b9dbe80..fba180e0f 100644
--- a/Source/WebCore/rendering/RenderScrollbarPart.h
+++ b/Source/WebCore/rendering/RenderScrollbarPart.h
@@ -46,7 +46,13 @@ public:
virtual void computePreferredLogicalWidths();
void paintIntoRect(GraphicsContext*, const LayoutPoint&, const LayoutRect&);
-
+
+ // Scrollbar parts needs to be rendered at device pixel boundaries.
+ virtual LayoutUnit marginTop() const { ASSERT(isIntegerValue(m_marginTop)); return m_marginTop; }
+ virtual LayoutUnit marginBottom() const { ASSERT(isIntegerValue(m_marginBottom)); return m_marginBottom; }
+ virtual LayoutUnit marginLeft() const { ASSERT(isIntegerValue(m_marginLeft)); return m_marginLeft; }
+ virtual LayoutUnit marginRight() const { ASSERT(isIntegerValue(m_marginRight)); return m_marginRight; }
+
protected:
virtual void styleWillChange(StyleDifference diff, const RenderStyle* newStyle);
virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
diff --git a/Source/WebCore/rendering/RenderSelectionInfo.h b/Source/WebCore/rendering/RenderSelectionInfo.h
index 6ce05d6be..8936a377e 100644
--- a/Source/WebCore/rendering/RenderSelectionInfo.h
+++ b/Source/WebCore/rendering/RenderSelectionInfo.h
@@ -62,7 +62,7 @@ class RenderSelectionInfo : public RenderSelectionInfoBase {
public:
RenderSelectionInfo(RenderObject* o, bool clipToVisibleContent)
: RenderSelectionInfoBase(o)
- , m_rect(o->needsLayout() ? LayoutRect() : o->selectionRectForRepaint(m_repaintContainer, clipToVisibleContent))
+ , m_rect(o->canUpdateSelectionOnRootLineBoxes() ? o->selectionRectForRepaint(m_repaintContainer, clipToVisibleContent) : LayoutRect())
{
}
@@ -71,10 +71,10 @@ public:
m_object->repaintUsingContainer(m_repaintContainer, m_rect);
}
- IntRect rect() const { return m_rect; }
+ LayoutRect rect() const { return m_rect; }
private:
- IntRect m_rect; // relative to repaint container
+ LayoutRect m_rect; // relative to repaint container
};
@@ -83,7 +83,7 @@ class RenderBlockSelectionInfo : public RenderSelectionInfoBase {
public:
RenderBlockSelectionInfo(RenderBlock* b)
: RenderSelectionInfoBase(b)
- , m_rects(b->needsLayout() ? GapRects() : block()->selectionGapRectsForRepaint(m_repaintContainer))
+ , m_rects(b->canUpdateSelectionOnRootLineBoxes() ? block()->selectionGapRectsForRepaint(m_repaintContainer) : GapRects())
{
}
diff --git a/Source/WebCore/rendering/RenderSlider.cpp b/Source/WebCore/rendering/RenderSlider.cpp
index e1d6ccc52..f78ba5c75 100644
--- a/Source/WebCore/rendering/RenderSlider.cpp
+++ b/Source/WebCore/rendering/RenderSlider.cpp
@@ -22,7 +22,6 @@
#include "RenderSlider.h"
#include "CSSPropertyNames.h"
-#include "CSSStyleSelector.h"
#include "Document.h"
#include "Event.h"
#include "EventHandler.h"
@@ -40,6 +39,7 @@
#include "ShadowRoot.h"
#include "SliderThumbElement.h"
#include "StepRange.h"
+#include "StyleResolver.h"
#include <wtf/MathExtras.h>
using std::min;
diff --git a/Source/WebCore/rendering/RenderTable.cpp b/Source/WebCore/rendering/RenderTable.cpp
index 2c8cae1dd..e7ada7044 100644
--- a/Source/WebCore/rendering/RenderTable.cpp
+++ b/Source/WebCore/rendering/RenderTable.cpp
@@ -118,7 +118,6 @@ void RenderTable::addChild(RenderObject* child, RenderObject* beforeChild)
if (child->isTableCaption()) {
m_captions.append(toRenderTableCaption(child));
- setNeedsSectionRecalc();
wrapInAnonymousSection = false;
} else if (child->isTableCol()) {
m_hasColElements = true;
@@ -159,9 +158,8 @@ void RenderTable::addChild(RenderObject* child, RenderObject* beforeChild)
wrapInAnonymousSection = true;
if (!wrapInAnonymousSection) {
- // If the next renderer is actually wrapped in an anonymous table section, we need to go up and find that.
- while (beforeChild && beforeChild->parent() != this)
- beforeChild = beforeChild->parent();
+ if (beforeChild && beforeChild->parent() != this)
+ beforeChild = splitAnonymousBoxesAroundChild(beforeChild);
RenderBox::addChild(child, beforeChild);
return;
@@ -192,11 +190,8 @@ void RenderTable::addChild(RenderObject* child, RenderObject* beforeChild)
if (beforeChild && !beforeChild->isTableSection() && beforeChild->style()->display() != TABLE_CAPTION && beforeChild->style()->display() != TABLE_COLUMN_GROUP)
beforeChild = 0;
- RenderTableSection* section = new (renderArena()) RenderTableSection(document() /* anonymous */);
- RefPtr<RenderStyle> newStyle = RenderStyle::create();
- newStyle->inheritFrom(style());
- newStyle->setDisplay(TABLE_ROW_GROUP);
- section->setStyle(newStyle.release());
+
+ RenderTableSection* section = RenderTableSection::createAnonymousWithParentRenderer(this);
addChild(section, beforeChild);
section->addChild(child);
}
@@ -222,6 +217,7 @@ void RenderTable::computeLogicalWidth()
computePositionedLogicalWidth();
RenderBlock* cb = containingBlock();
+ RenderView* renderView = view();
LayoutUnit availableLogicalWidth = containingBlockLogicalWidthForContent();
bool hasPerpendicularContainingBlock = cb->style()->isHorizontalWritingMode() != style()->isHorizontalWritingMode();
@@ -232,10 +228,10 @@ void RenderTable::computeLogicalWidth()
setLogicalWidth(convertStyleLogicalWidthToComputedWidth(styleLogicalWidth, containerWidthInInlineDirection));
else {
// Subtract out any fixed margins from our available width for auto width tables.
- LayoutUnit marginStart = style()->marginStart().calcMinValue(availableLogicalWidth);
- LayoutUnit marginEnd = style()->marginEnd().calcMinValue(availableLogicalWidth);
+ LayoutUnit marginStart = minimumValueForLength(style()->marginStart(), availableLogicalWidth, renderView);
+ LayoutUnit marginEnd = minimumValueForLength(style()->marginEnd(), availableLogicalWidth, renderView);
LayoutUnit marginTotal = marginStart + marginEnd;
-
+
// Subtract out our margins to get the available content width.
LayoutUnit availableContentLogicalWidth = max<LayoutUnit>(0, containerWidthInInlineDirection - marginTotal);
if (shrinkToAvoidFloats() && cb->containsFloats() && !hasPerpendicularContainingBlock) {
@@ -244,25 +240,28 @@ void RenderTable::computeLogicalWidth()
}
// Ensure we aren't bigger than our available width.
- setLogicalWidth(min(availableContentLogicalWidth, maxPreferredLogicalWidth()));
+ setLogicalWidth(min<int>(availableContentLogicalWidth, maxPreferredLogicalWidth()));
}
// Ensure we aren't smaller than our min preferred width.
- setLogicalWidth(max(logicalWidth(), minPreferredLogicalWidth()));
+ setLogicalWidth(max<int>(logicalWidth(), minPreferredLogicalWidth()));
// Ensure we aren't smaller than our min-width style.
Length styleMinLogicalWidth = style()->logicalMinWidth();
if (styleMinLogicalWidth.isSpecified() && styleMinLogicalWidth.isPositive())
- setLogicalWidth(max(logicalWidth(), convertStyleLogicalWidthToComputedWidth(styleMinLogicalWidth, availableLogicalWidth)));
+ setLogicalWidth(max<int>(logicalWidth(), convertStyleLogicalWidthToComputedWidth(styleMinLogicalWidth, availableLogicalWidth)));
// Finally, with our true width determined, compute our margins for real.
setMarginStart(0);
setMarginEnd(0);
- if (!hasPerpendicularContainingBlock)
- computeInlineDirectionMargins(cb, availableLogicalWidth, logicalWidth());
- else {
- setMarginStart(style()->marginStart().calcMinValue(availableLogicalWidth));
- setMarginEnd(style()->marginEnd().calcMinValue(availableLogicalWidth));
+ if (!hasPerpendicularContainingBlock) {
+ LayoutUnit containerLogicalWidthForAutoMargins = availableLogicalWidth;
+ if (avoidsFloats() && cb->containsFloats())
+ containerLogicalWidthForAutoMargins = containingBlockAvailableLineWidthInRegion(0, 0); // FIXME: Work with regions someday.
+ computeInlineDirectionMargins(cb, containerLogicalWidthForAutoMargins, logicalWidth());
+ } else {
+ setMarginStart(minimumValueForLength(style()->marginStart(), availableLogicalWidth, renderView));
+ setMarginEnd(minimumValueForLength(style()->marginEnd(), availableLogicalWidth, renderView));
}
}
@@ -270,28 +269,28 @@ void RenderTable::computeLogicalWidth()
LayoutUnit RenderTable::convertStyleLogicalWidthToComputedWidth(const Length& styleLogicalWidth, LayoutUnit availableWidth)
{
// HTML tables' width styles already include borders and paddings, but CSS tables' width styles do not.
- int borders = 0;
+ LayoutUnit borders = 0;
bool isCSSTable = !node() || !node()->hasTagName(tableTag);
if (isCSSTable && styleLogicalWidth.isFixed() && styleLogicalWidth.isPositive()) {
recalcBordersInRowDirection();
- borders = borderStart() + borderEnd() + (collapseBorders() ? 0 : paddingStart() + paddingEnd());
+ borders = borderStart() + borderEnd() + (collapseBorders() ? ZERO_LAYOUT_UNIT : paddingStart() + paddingEnd());
}
- return styleLogicalWidth.calcMinValue(availableWidth) + borders;
+ return minimumValueForLength(styleLogicalWidth, availableWidth, view()) + borders;
}
void RenderTable::layoutCaption(RenderTableCaption* caption)
{
- IntRect captionRect(caption->x(), caption->y(), caption->width(), caption->height());
+ LayoutRect captionRect(caption->frameRect());
if (caption->needsLayout()) {
// The margins may not be available but ensure the caption is at least located beneath any previous sibling caption
// so that it does not mistakenly think any floats in the previous caption intrude into it.
- caption->setLogicalLocation(IntPoint(caption->marginStart(), caption->marginBefore() + logicalHeight()));
+ caption->setLogicalLocation(LayoutPoint(caption->marginStart(), caption->marginBefore() + logicalHeight()));
// If RenderTableCaption ever gets a layout() function, use it here.
caption->layoutIfNeeded();
}
// Apply the margins to the location now that they are definitely available from layout
- caption->setLogicalLocation(IntPoint(caption->marginStart(), caption->marginBefore() + logicalHeight()));
+ caption->setLogicalLocation(LayoutPoint(caption->marginStart(), caption->marginBefore() + logicalHeight()));
if (!selfNeedsLayout() && caption->checkForRepaintDuringLayout())
caption->repaintDuringLayoutIfMoved(captionRect);
@@ -299,6 +298,20 @@ void RenderTable::layoutCaption(RenderTableCaption* caption)
setLogicalHeight(logicalHeight() + caption->logicalHeight() + caption->marginBefore() + caption->marginAfter());
}
+void RenderTable::distributeExtraLogicalHeight(int extraLogicalHeight)
+{
+ if (extraLogicalHeight <= 0)
+ return;
+
+ // FIXME: Distribute the extra logical height between all table sections instead of giving it all to the first one.
+ if (RenderTableSection* section = firstBody())
+ extraLogicalHeight -= section->distributeExtraLogicalHeightToRows(extraLogicalHeight);
+
+ // FIXME: We really would like to enable this ASSERT to ensure that all the extra space has been distributed.
+ // However our current distribution algorithm does not round properly and thus we can have some remaining height.
+ // ASSERT(!topSection() || !extraLogicalHeight);
+}
+
void RenderTable::layout()
{
ASSERT(needsLayout());
@@ -321,7 +334,7 @@ void RenderTable::layout()
if (logicalWidth() != oldLogicalWidth) {
for (unsigned i = 0; i < m_captions.size(); i++)
- m_captions[i]->setNeedsLayout(true, false);
+ m_captions[i]->setNeedsLayout(true, MarkOnlyThis);
}
// FIXME: The optimisation below doesn't work since the internal table
// layout could have changed. we need to add a flag to the table
@@ -372,8 +385,8 @@ void RenderTable::layout()
}
}
- LayoutUnit borderAndPaddingBefore = borderBefore() + (collapsing ? zeroLayoutUnit : paddingBefore());
- LayoutUnit borderAndPaddingAfter = borderAfter() + (collapsing ? zeroLayoutUnit : paddingAfter());
+ LayoutUnit borderAndPaddingBefore = borderBefore() + (collapsing ? ZERO_LAYOUT_UNIT : paddingBefore());
+ LayoutUnit borderAndPaddingAfter = borderAfter() + (collapsing ? ZERO_LAYOUT_UNIT : paddingAfter());
setLogicalHeight(logicalHeight() + borderAndPaddingBefore);
@@ -384,17 +397,16 @@ void RenderTable::layout()
LayoutUnit computedLogicalHeight = 0;
if (logicalHeightLength.isFixed()) {
// HTML tables size as though CSS height includes border/padding, CSS tables do not.
- LayoutUnit borders = node() && node()->hasTagName(tableTag) ? (borderAndPaddingBefore + borderAndPaddingAfter) : zeroLayoutUnit;
+ LayoutUnit borders = node() && node()->hasTagName(tableTag) ? (borderAndPaddingBefore + borderAndPaddingAfter) : ZERO_LAYOUT_UNIT;
computedLogicalHeight = logicalHeightLength.value() - borders;
} else if (logicalHeightLength.isPercent())
computedLogicalHeight = computePercentageLogicalHeight(logicalHeightLength);
computedLogicalHeight = max<LayoutUnit>(0, computedLogicalHeight);
- for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
- if (child->isTableSection())
- // FIXME: Distribute the extra logical height between all table sections instead of giving it all to the first one.
- toRenderTableSection(child)->layoutRows(child == topSection() ? max<LayoutUnit>(0, computedLogicalHeight - totalSectionLogicalHeight) : 0);
- }
+ distributeExtraLogicalHeight(floorToInt(computedLogicalHeight - totalSectionLogicalHeight));
+
+ for (RenderTableSection* section = topSection(); section; section = sectionBelow(section))
+ section->layoutRows();
if (!topSection() && computedLogicalHeight > totalSectionLogicalHeight && !document()->inQuirksMode()) {
// Completely empty tables (with no sections or anything) should at least honor specified height
@@ -494,7 +506,7 @@ void RenderTable::addOverflowFromChildren()
int bottomBorderOverflow = height() + outerBorderBottom() - borderBottom();
int topBorderOverflow = borderTop() - outerBorderTop();
IntRect borderOverflowRect(leftBorderOverflow, topBorderOverflow, rightBorderOverflow - leftBorderOverflow, bottomBorderOverflow - topBorderOverflow);
- if (borderOverflowRect != borderBoxRect()) {
+ if (borderOverflowRect != pixelSnappedBorderBoxRect()) {
addLayoutOverflow(borderOverflowRect);
addVisualOverflow(borderOverflowRect);
}
@@ -778,46 +790,51 @@ void RenderTable::recalcSections() const
m_foot = 0;
m_firstBody = 0;
m_hasColElements = false;
+ m_captions.clear();
// We need to get valid pointers to caption, head, foot and first body again
RenderObject* nextSibling;
for (RenderObject* child = firstChild(); child; child = nextSibling) {
nextSibling = child->nextSibling();
switch (child->style()->display()) {
- case TABLE_COLUMN:
- case TABLE_COLUMN_GROUP:
- m_hasColElements = true;
- break;
- case TABLE_HEADER_GROUP:
- if (child->isTableSection()) {
- RenderTableSection* section = toRenderTableSection(child);
- if (!m_head)
- m_head = section;
- else if (!m_firstBody)
- m_firstBody = section;
- section->recalcCellsIfNeeded();
- }
- break;
- case TABLE_FOOTER_GROUP:
- if (child->isTableSection()) {
- RenderTableSection* section = toRenderTableSection(child);
- if (!m_foot)
- m_foot = section;
- else if (!m_firstBody)
- m_firstBody = section;
- section->recalcCellsIfNeeded();
- }
- break;
- case TABLE_ROW_GROUP:
- if (child->isTableSection()) {
- RenderTableSection* section = toRenderTableSection(child);
- if (!m_firstBody)
- m_firstBody = section;
- section->recalcCellsIfNeeded();
- }
- break;
- default:
- break;
+ case TABLE_CAPTION:
+ if (child->isTableCaption())
+ m_captions.append(toRenderTableCaption(child));
+ break;
+ case TABLE_COLUMN:
+ case TABLE_COLUMN_GROUP:
+ m_hasColElements = true;
+ break;
+ case TABLE_HEADER_GROUP:
+ if (child->isTableSection()) {
+ RenderTableSection* section = toRenderTableSection(child);
+ if (!m_head)
+ m_head = section;
+ else if (!m_firstBody)
+ m_firstBody = section;
+ section->recalcCellsIfNeeded();
+ }
+ break;
+ case TABLE_FOOTER_GROUP:
+ if (child->isTableSection()) {
+ RenderTableSection* section = toRenderTableSection(child);
+ if (!m_foot)
+ m_foot = section;
+ else if (!m_firstBody)
+ m_firstBody = section;
+ section->recalcCellsIfNeeded();
+ }
+ break;
+ case TABLE_ROW_GROUP:
+ if (child->isTableSection()) {
+ RenderTableSection* section = toRenderTableSection(child);
+ if (!m_firstBody)
+ m_firstBody = section;
+ section->recalcCellsIfNeeded();
+ }
+ break;
+ default:
+ break;
}
}
@@ -1114,7 +1131,7 @@ RenderTableCell* RenderTable::cellAbove(const RenderTableCell* cell) const
recalcSectionsIfNeeded();
// Find the section and row to look in
- unsigned r = cell->row();
+ unsigned r = cell->rowIndex();
RenderTableSection* section = 0;
unsigned rAbove = 0;
if (r > 0) {
@@ -1143,7 +1160,7 @@ RenderTableCell* RenderTable::cellBelow(const RenderTableCell* cell) const
recalcSectionsIfNeeded();
// Find the section and row to look in
- unsigned r = cell->row() + cell->rowSpan() - 1;
+ unsigned r = cell->rowIndex() + cell->rowSpan() - 1;
RenderTableSection* section = 0;
unsigned rBelow = 0;
if (r < cell->section()->numRows() - 1) {
@@ -1175,7 +1192,7 @@ RenderTableCell* RenderTable::cellBefore(const RenderTableCell* cell) const
return 0;
// If we hit a colspan back up to a real cell.
- RenderTableSection::CellStruct& prevCell = section->cellAt(cell->row(), effCol - 1);
+ RenderTableSection::CellStruct& prevCell = section->cellAt(cell->rowIndex(), effCol - 1);
return prevCell.primaryCell();
}
@@ -1186,7 +1203,7 @@ RenderTableCell* RenderTable::cellAfter(const RenderTableCell* cell) const
unsigned effCol = colToEffCol(cell->col() + cell->colSpan());
if (effCol >= numEffCols())
return 0;
- return cell->section()->primaryCellAt(cell->row(), effCol);
+ return cell->section()->primaryCellAt(cell->rowIndex(), effCol);
}
RenderBlock* RenderTable::firstLineBlock() const
@@ -1263,4 +1280,12 @@ bool RenderTable::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu
return false;
}
+RenderTable* RenderTable::createAnonymousWithParentRenderer(const RenderObject* parent)
+{
+ RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(parent->style(), TABLE);
+ RenderTable* newTable = new (parent->renderArena()) RenderTable(parent->document() /* is anonymous */);
+ newTable->setStyle(newStyle.release());
+ return newTable;
+}
+
}
diff --git a/Source/WebCore/rendering/RenderTable.h b/Source/WebCore/rendering/RenderTable.h
index d4e4fca91..b61c95dc1 100644
--- a/Source/WebCore/rendering/RenderTable.h
+++ b/Source/WebCore/rendering/RenderTable.h
@@ -45,7 +45,7 @@ public:
explicit RenderTable(Node*);
virtual ~RenderTable();
- LayoutUnit getColumnPos(unsigned col) const { return m_columnPos[col]; }
+ int getColumnPos(unsigned col) const { return m_columnPos[col]; }
int hBorderSpacing() const { return m_hSpacing; }
int vBorderSpacing() const { return m_vSpacing; }
@@ -136,7 +136,7 @@ public:
};
Vector<ColumnStruct>& columns() { return m_columns; }
- Vector<LayoutUnit>& columnPositions() { return m_columnPos; }
+ Vector<int>& columnPositions() { return m_columnPos; }
RenderTableSection* header() const { return m_head; }
RenderTableSection* footer() const { return m_foot; }
RenderTableSection* firstBody() const { return m_firstBody; }
@@ -172,7 +172,7 @@ public:
LayoutUnit bordersPaddingAndSpacingInRowDirection() const
{
return borderStart() + borderEnd() +
- (collapseBorders() ? zeroLayoutUnit : (paddingStart() + paddingEnd() + (numEffCols() + 1) * hBorderSpacing()));
+ (collapseBorders() ? ZERO_LAYOUT_UNIT : (paddingStart() + paddingEnd() + static_cast<LayoutUnit>(numEffCols() + 1) * hBorderSpacing()));
}
RenderTableCol* colElement(unsigned col, bool* startEdge = 0, bool* endEdge = 0) const;
@@ -211,6 +211,12 @@ public:
recalcSections();
}
+ static RenderTable* createAnonymousWithParentRenderer(const RenderObject*);
+ virtual RenderBox* createAnonymousBoxWithSameTypeAs(const RenderObject* parent) const OVERRIDE
+ {
+ return createAnonymousWithParentRenderer(parent);
+ }
+
protected:
virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
@@ -252,7 +258,9 @@ private:
void recalcSections() const;
void layoutCaption(RenderTableCaption*);
- mutable Vector<LayoutUnit> m_columnPos;
+ void distributeExtraLogicalHeight(int extraLogicalHeight);
+
+ mutable Vector<int> m_columnPos;
mutable Vector<ColumnStruct> m_columns;
mutable Vector<RenderTableCaption*> m_captions;
diff --git a/Source/WebCore/rendering/RenderTableCell.cpp b/Source/WebCore/rendering/RenderTableCell.cpp
index 4243848d9..ec33a7c9f 100644
--- a/Source/WebCore/rendering/RenderTableCell.cpp
+++ b/Source/WebCore/rendering/RenderTableCell.cpp
@@ -43,9 +43,8 @@ using namespace HTMLNames;
RenderTableCell::RenderTableCell(Node* node)
: RenderBlock(node)
- , m_row(unsetRowIndex)
- , m_cellWidthChanged(false)
, m_column(unsetColumnIndex)
+ , m_cellWidthChanged(false)
, m_hasAssociatedTableCellElement(node && (node->hasTagName(tdTag) || node->hasTagName(thTag)))
, m_intrinsicPaddingBefore(0)
, m_intrinsicPaddingAfter(0)
@@ -95,7 +94,7 @@ LayoutUnit RenderTableCell::logicalHeightForRowSizing() const
{
LayoutUnit adjustedLogicalHeight = logicalHeight() - (intrinsicPaddingBefore() + intrinsicPaddingAfter());
- LayoutUnit styleLogicalHeight = style()->logicalHeight().calcValue(0);
+ LayoutUnit styleLogicalHeight = valueForLength(style()->logicalHeight(), 0, view());
if (document()->inQuirksMode() || style()->boxSizing() == BORDER_BOX) {
// Explicit heights use the border box in quirks mode.
// Don't adjust height.
@@ -143,7 +142,7 @@ Length RenderTableCell::styleOrColLogicalWidth() const
// Percentages don't need to be handled since they're always treated this way (even when specified on the cells).
// See Bugzilla bug 8126 for details.
if (colWidthSum.isFixed() && colWidthSum.value() > 0)
- colWidthSum = Length(max<LayoutUnit>(0, colWidthSum.value() - borderAndPaddingLogicalWidth()), Fixed);
+ colWidthSum = Length(max(0.0f, colWidthSum.value() - borderAndPaddingLogicalWidth()), Fixed);
return colWidthSum;
}
@@ -191,53 +190,47 @@ void RenderTableCell::layout()
setCellWidthChanged(false);
}
-LayoutUnit RenderTableCell::paddingTop(PaddingOptions paddingOption) const
+LayoutUnit RenderTableCell::paddingTop() const
{
- LayoutUnit result = RenderBlock::paddingTop();
- if (paddingOption == ExcludeIntrinsicPadding || !isHorizontalWritingMode())
+ LayoutUnit result = computedCSSPaddingTop();
+ if (!isHorizontalWritingMode())
return result;
return result + (style()->writingMode() == TopToBottomWritingMode ? intrinsicPaddingBefore() : intrinsicPaddingAfter());
}
-LayoutUnit RenderTableCell::paddingBottom(PaddingOptions paddingOption) const
+LayoutUnit RenderTableCell::paddingBottom() const
{
- LayoutUnit result = RenderBlock::paddingBottom();
- if (paddingOption == ExcludeIntrinsicPadding || !isHorizontalWritingMode())
+ LayoutUnit result = computedCSSPaddingBottom();
+ if (!isHorizontalWritingMode())
return result;
return result + (style()->writingMode() == TopToBottomWritingMode ? intrinsicPaddingAfter() : intrinsicPaddingBefore());
}
-LayoutUnit RenderTableCell::paddingLeft(PaddingOptions paddingOption) const
+LayoutUnit RenderTableCell::paddingLeft() const
{
- LayoutUnit result = RenderBlock::paddingLeft();
- if (paddingOption == ExcludeIntrinsicPadding || isHorizontalWritingMode())
+ LayoutUnit result = computedCSSPaddingLeft();
+ if (isHorizontalWritingMode())
return result;
return result + (style()->writingMode() == LeftToRightWritingMode ? intrinsicPaddingBefore() : intrinsicPaddingAfter());
}
-LayoutUnit RenderTableCell::paddingRight(PaddingOptions paddingOption) const
+LayoutUnit RenderTableCell::paddingRight() const
{
- LayoutUnit result = RenderBlock::paddingRight();
- if (paddingOption == ExcludeIntrinsicPadding || isHorizontalWritingMode())
+ LayoutUnit result = computedCSSPaddingRight();
+ if (isHorizontalWritingMode())
return result;
return result + (style()->writingMode() == LeftToRightWritingMode ? intrinsicPaddingAfter() : intrinsicPaddingBefore());
}
-LayoutUnit RenderTableCell::paddingBefore(PaddingOptions paddingOption) const
+LayoutUnit RenderTableCell::paddingBefore() const
{
- LayoutUnit result = RenderBlock::paddingBefore();
- if (paddingOption == ExcludeIntrinsicPadding)
- return result;
- return result + intrinsicPaddingBefore();
+ return computedCSSPaddingBefore() + intrinsicPaddingBefore();
}
-LayoutUnit RenderTableCell::paddingAfter(PaddingOptions paddingOption) const
+LayoutUnit RenderTableCell::paddingAfter() const
{
- LayoutUnit result = RenderBlock::paddingAfter();
- if (paddingOption == ExcludeIntrinsicPadding)
- return result;
- return result + intrinsicPaddingAfter();
+ return computedCSSPaddingAfter() + intrinsicPaddingAfter();
}
void RenderTableCell::setOverrideHeightFromRowHeight(LayoutUnit rowHeight)
@@ -296,9 +289,8 @@ LayoutRect RenderTableCell::clippedOverflowRectForRepaint(RenderBoxModelObject*
right = max(right, below->borderHalfRight(true));
}
}
- left = max(left, -minXVisualOverflow());
- top = max(top, -minYVisualOverflow());
- LayoutRect r(-left, - top, left + max(width() + right, maxXVisualOverflow()), top + max(height() + bottom, maxYVisualOverflow()));
+ LayoutPoint location(max<LayoutUnit>(left, -minXVisualOverflow()), max<LayoutUnit>(top, -minYVisualOverflow()));
+ LayoutRect r(-location.x(), -location.y(), location.x() + max(width() + right, maxXVisualOverflow()), location.y() + max(height() + bottom, maxYVisualOverflow()));
if (RenderView* v = view()) {
// FIXME: layoutDelta needs to be applied in parts before/after transforms and
@@ -328,18 +320,19 @@ LayoutUnit RenderTableCell::cellBaselinePosition() const
LayoutUnit firstLineBaseline = firstLineBoxBaseline();
if (firstLineBaseline != -1)
return firstLineBaseline;
- return paddingBefore() + borderBefore() + contentLogicalHeight(IncludeIntrinsicPadding);
+ return paddingBefore() + borderBefore() + contentLogicalHeight();
}
void RenderTableCell::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
ASSERT(style()->display() == TABLE_CELL);
+ ASSERT(!row() || row()->rowIndexWasSet());
RenderBlock::styleDidChange(diff, oldStyle);
setHasBoxDecorations(true);
- if (parent() && section() && oldStyle && style()->height() != oldStyle->height() && rowWasSet())
- section()->rowLogicalHeightChanged(row());
+ if (parent() && section() && oldStyle && style()->height() != oldStyle->height())
+ section()->rowLogicalHeightChanged(rowIndex());
// If border was changed, notify table.
if (parent()) {
@@ -604,7 +597,7 @@ CollapsedBorderValue RenderTableCell::computeCollapsedBeforeBorder(IncludeBorder
// Now check row groups.
RenderTableSection* currSection = section();
- if (!row()) {
+ if (!rowIndex()) {
// (5) Our row group's before border.
result = chooseBorder(result, CollapsedBorderValue(currSection->style()->borderBefore(), includeColor ? currSection->style()->visitedDependentColor(beforeColorProperty) : Color(), BROWGROUP));
if (!result.exists())
@@ -682,7 +675,7 @@ CollapsedBorderValue RenderTableCell::computeCollapsedAfterBorder(IncludeBorderC
// Now check row groups.
RenderTableSection* currSection = section();
- if (row() + rowSpan() >= currSection->numRows()) {
+ if (rowIndex() + rowSpan() >= currSection->numRows()) {
// (5) Our row group's after border.
result = chooseBorder(result, CollapsedBorderValue(currSection->style()->borderAfter(), includeColor ? currSection->style()->visitedDependentColor(afterColorProperty) : Color(), BROWGROUP));
if (!result.exists())
@@ -1118,4 +1111,12 @@ void RenderTableCell::scrollbarsChanged(bool horizontalScrollbarChanged, bool ve
setIntrinsicPaddingAfter(intrinsicPaddingAfter() - scrollbarHeight);
}
+RenderTableCell* RenderTableCell::createAnonymousWithParentRenderer(const RenderObject* parent)
+{
+ RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(parent->style(), TABLE_CELL);
+ RenderTableCell* newCell = new (parent->renderArena()) RenderTableCell(parent->document() /* is anonymous */);
+ newCell->setStyle(newStyle.release());
+ return newCell;
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/rendering/RenderTableCell.h b/Source/WebCore/rendering/RenderTableCell.h
index e18372ac5..dac8a7606 100644
--- a/Source/WebCore/rendering/RenderTableCell.h
+++ b/Source/WebCore/rendering/RenderTableCell.h
@@ -25,15 +25,13 @@
#ifndef RenderTableCell_h
#define RenderTableCell_h
+#include "RenderTableRow.h"
#include "RenderTableSection.h"
namespace WebCore {
-static const unsigned unsetColumnIndex = 0x7FFFFFFF;
-static const unsigned maxColumnIndex = 0x7FFFFFFE; // 2,147,483,646
-
-static const unsigned unsetRowIndex = 0x7FFFFFFF;
-static const unsigned maxRowIndex = 0x7FFFFFFE; // 2,147,483,646
+static const unsigned unsetColumnIndex = 0x3FFFFFFF;
+static const unsigned maxColumnIndex = 0x3FFFFFFE; // 1,073,741,823
enum IncludeBorderColorOrNot { DoNotIncludeBorderColor, IncludeBorderColor };
@@ -65,24 +63,17 @@ public:
return m_column;
}
- void setRow(unsigned row)
- {
- if (UNLIKELY(row > maxRowIndex))
- CRASH();
-
- m_row = row;
- }
+ RenderTableRow* row() const { return toRenderTableRow(parent()); }
+ RenderTableSection* section() const { return toRenderTableSection(parent()->parent()); }
+ RenderTable* table() const { return toRenderTable(parent()->parent()->parent()); }
- bool rowWasSet() const { return m_row != unsetRowIndex; }
- unsigned row() const
+ unsigned rowIndex() const
{
- ASSERT(rowWasSet());
- return m_row;
+ // This function shouldn't be called on a detached cell.
+ ASSERT(row());
+ return row()->rowIndex();
}
- RenderTableSection* section() const { return toRenderTableSection(parent()->parent()); }
- RenderTable* table() const { return toRenderTable(parent()->parent()->parent()); }
-
Length styleOrColLogicalWidth() const;
LayoutUnit logicalHeightForRowSizing() const;
@@ -120,16 +111,16 @@ public:
int intrinsicPaddingBefore() const { return m_intrinsicPaddingBefore; }
int intrinsicPaddingAfter() const { return m_intrinsicPaddingAfter; }
- virtual LayoutUnit paddingTop(PaddingOptions = IncludeIntrinsicPadding) const;
- virtual LayoutUnit paddingBottom(PaddingOptions = IncludeIntrinsicPadding) const;
- virtual LayoutUnit paddingLeft(PaddingOptions = IncludeIntrinsicPadding) const;
- virtual LayoutUnit paddingRight(PaddingOptions = IncludeIntrinsicPadding) const;
+ virtual LayoutUnit paddingTop() const OVERRIDE;
+ virtual LayoutUnit paddingBottom() const OVERRIDE;
+ virtual LayoutUnit paddingLeft() const OVERRIDE;
+ virtual LayoutUnit paddingRight() const OVERRIDE;
// FIXME: For now we just assume the cell has the same block flow direction as the table. It's likely we'll
// create an extra anonymous RenderBlock to handle mixing directionality anyway, in which case we can lock
// the block flow directionality of the cells to the table's directionality.
- virtual LayoutUnit paddingBefore(PaddingOptions = IncludeIntrinsicPadding) const;
- virtual LayoutUnit paddingAfter(PaddingOptions = IncludeIntrinsicPadding) const;
+ virtual LayoutUnit paddingBefore() const OVERRIDE;
+ virtual LayoutUnit paddingAfter() const OVERRIDE;
void setOverrideHeightFromRowHeight(LayoutUnit);
@@ -138,6 +129,12 @@ public:
bool cellWidthChanged() const { return m_cellWidthChanged; }
void setCellWidthChanged(bool b = true) { m_cellWidthChanged = b; }
+ static RenderTableCell* createAnonymousWithParentRenderer(const RenderObject*);
+ virtual RenderBox* createAnonymousBoxWithSameTypeAs(const RenderObject* parent) const OVERRIDE
+ {
+ return createAnonymousWithParentRenderer(parent);
+ }
+
protected:
virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
@@ -184,9 +181,8 @@ private:
CollapsedBorderValue computeCollapsedBeforeBorder(IncludeBorderColorOrNot = IncludeBorderColor) const;
CollapsedBorderValue computeCollapsedAfterBorder(IncludeBorderColorOrNot = IncludeBorderColor) const;
- unsigned m_row : 31;
+ unsigned m_column : 30;
bool m_cellWidthChanged : 1;
- unsigned m_column : 31;
bool m_hasAssociatedTableCellElement : 1;
int m_intrinsicPaddingBefore;
int m_intrinsicPaddingAfter;
diff --git a/Source/WebCore/rendering/RenderTableCol.h b/Source/WebCore/rendering/RenderTableCol.h
index 76c28a3a5..da037b863 100644
--- a/Source/WebCore/rendering/RenderTableCol.h
+++ b/Source/WebCore/rendering/RenderTableCol.h
@@ -43,7 +43,7 @@ public:
unsigned span() const { return m_span; }
void setSpan(unsigned span) { m_span = span; }
-
+ bool isTableColGroup() { return firstChild() ? true : false; }
private:
virtual RenderObjectChildList* virtualChildren() { return children(); }
virtual const RenderObjectChildList* virtualChildren() const { return children(); }
diff --git a/Source/WebCore/rendering/RenderTableRow.cpp b/Source/WebCore/rendering/RenderTableRow.cpp
index 23227448e..d9889008b 100644
--- a/Source/WebCore/rendering/RenderTableRow.cpp
+++ b/Source/WebCore/rendering/RenderTableRow.cpp
@@ -38,6 +38,7 @@ using namespace HTMLNames;
RenderTableRow::RenderTableRow(Node* node)
: RenderBox(node)
+ , m_rowIndex(unsetRowIndex)
{
// init RenderObject attributes
setInline(false); // our object is not Inline
@@ -72,7 +73,7 @@ void RenderTableRow::styleDidChange(StyleDifference diff, const RenderStyle* old
updateBeforeAndAfterContent();
if (section() && oldStyle && style()->logicalHeight() != oldStyle->logicalHeight())
- section()->rowLogicalHeightChanged(section()->rowIndexForRenderer(this));
+ section()->rowLogicalHeightChanged(rowIndex());
// If border was changed, notify table.
if (parent()) {
@@ -113,19 +114,14 @@ void RenderTableRow::addChild(RenderObject* child, RenderObject* beforeChild)
return;
}
- RenderTableCell* cell = new (renderArena()) RenderTableCell(document() /* anonymous object */);
- RefPtr<RenderStyle> newStyle = RenderStyle::create();
- newStyle->inheritFrom(style());
- newStyle->setDisplay(TABLE_CELL);
- cell->setStyle(newStyle.release());
+ RenderTableCell* cell = RenderTableCell::createAnonymousWithParentRenderer(this);
addChild(cell, beforeChild);
cell->addChild(child);
return;
}
-
- // If the next renderer is actually wrapped in an anonymous table cell, we need to go up and find that.
- while (beforeChild && beforeChild->parent() != this)
- beforeChild = beforeChild->parent();
+
+ if (beforeChild && beforeChild->parent() != this)
+ beforeChild = splitAnonymousBoxesAroundChild(beforeChild);
RenderTableCell* cell = toRenderTableCell(child);
@@ -153,7 +149,7 @@ void RenderTableRow::layout()
if (child->isTableCell()) {
RenderTableCell* cell = toRenderTableCell(child);
if (!cell->needsLayout() && paginated && view()->layoutState()->pageLogicalHeight() && view()->layoutState()->pageLogicalOffset(cell->logicalTop()) != cell->pageLogicalOffset())
- cell->setChildNeedsLayout(true, false);
+ cell->setChildNeedsLayout(true, MarkOnlyThis);
if (child->needsLayout()) {
cell->computeBlockDirectionMargins(table());
@@ -249,4 +245,12 @@ void RenderTableRow::imageChanged(WrappedImagePtr, const IntRect*)
repaint();
}
+RenderTableRow* RenderTableRow::createAnonymousWithParentRenderer(const RenderObject* parent)
+{
+ RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(parent->style(), TABLE_ROW);
+ RenderTableRow* newRow = new (parent->renderArena()) RenderTableRow(parent->document() /* is anonymous */);
+ newRow->setStyle(newStyle.release());
+ return newRow;
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/rendering/RenderTableRow.h b/Source/WebCore/rendering/RenderTableRow.h
index f3175dfc0..04696607d 100644
--- a/Source/WebCore/rendering/RenderTableRow.h
+++ b/Source/WebCore/rendering/RenderTableRow.h
@@ -29,6 +29,9 @@
namespace WebCore {
+static const unsigned unsetRowIndex = 0x7FFFFFFF;
+static const unsigned maxRowIndex = 0x7FFFFFFE; // 2,147,483,646
+
class RenderTableRow : public RenderBox {
public:
explicit RenderTableRow(Node*);
@@ -42,6 +45,27 @@ public:
void updateBeforeAndAfterContent();
void paintOutlineForRowIfNeeded(PaintInfo&, const LayoutPoint&);
+ static RenderTableRow* createAnonymousWithParentRenderer(const RenderObject*);
+ virtual RenderBox* createAnonymousBoxWithSameTypeAs(const RenderObject* parent) const OVERRIDE
+ {
+ return createAnonymousWithParentRenderer(parent);
+ }
+
+ void setRowIndex(unsigned rowIndex)
+ {
+ if (UNLIKELY(rowIndex > maxRowIndex))
+ CRASH();
+
+ m_rowIndex = rowIndex;
+ }
+
+ bool rowIndexWasSet() const { return m_rowIndex != unsetRowIndex; }
+ unsigned rowIndex() const
+ {
+ ASSERT(rowIndexWasSet());
+ return m_rowIndex;
+ }
+
private:
virtual RenderObjectChildList* virtualChildren() { return children(); }
virtual const RenderObjectChildList* virtualChildren() const { return children(); }
@@ -57,8 +81,7 @@ private:
virtual LayoutRect clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer) const;
virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const LayoutPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction);
- // We need to allocate a layer whenever we have an overflow clip as RenderTableSection::paintObject does not push rows' clips.
- virtual bool requiresLayer() const OVERRIDE { return isTransparent() || hasOverflowClip() || hasTransform() || hasMask() || hasFilter(); }
+ virtual bool requiresLayer() const OVERRIDE { return isTransparent() || hasOverflowClip() || hasTransform() || hasHiddenBackface() || hasMask() || hasFilter(); }
virtual void paint(PaintInfo&, const LayoutPoint&);
@@ -67,6 +90,7 @@ private:
virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
RenderObjectChildList m_children;
+ unsigned m_rowIndex : 31;
};
inline RenderTableRow* toRenderTableRow(RenderObject* object)
diff --git a/Source/WebCore/rendering/RenderTableSection.cpp b/Source/WebCore/rendering/RenderTableSection.cpp
index 08a8c9b7d..0651c77af 100644
--- a/Source/WebCore/rendering/RenderTableSection.cpp
+++ b/Source/WebCore/rendering/RenderTableSection.cpp
@@ -161,11 +161,7 @@ void RenderTableSection::addChild(RenderObject* child, RenderObject* beforeChild
return;
}
- RenderObject* row = new (renderArena()) RenderTableRow(document() /* anonymous table row */);
- RefPtr<RenderStyle> newStyle = RenderStyle::create();
- newStyle->inheritFrom(style());
- newStyle->setDisplay(TABLE_ROW);
- row->setStyle(newStyle.release());
+ RenderObject* row = RenderTableRow::createAnonymousWithParentRenderer(this);
addChild(row, beforeChild);
row->addChild(child);
return;
@@ -180,14 +176,15 @@ void RenderTableSection::addChild(RenderObject* child, RenderObject* beforeChild
ensureRows(m_cRow);
- m_grid[insertionRow].rowRenderer = toRenderTableRow(child);
+ RenderTableRow* row = toRenderTableRow(child);
+ m_grid[insertionRow].rowRenderer = row;
+ row->setRowIndex(insertionRow);
if (!beforeChild)
setRowLogicalHeightToRowStyleLogicalHeightIfNotRelative(m_grid[insertionRow]);
- // If the next renderer is actually wrapped in an anonymous table row, we need to go up and find that.
- while (beforeChild && beforeChild->parent() != this)
- beforeChild = beforeChild->parent();
+ if (beforeChild && beforeChild->parent() != this)
+ beforeChild = splitAnonymousBoxesAroundChild(beforeChild);
ASSERT(!beforeChild || beforeChild->isTableRow());
RenderBox::addChild(child, beforeChild);
@@ -225,9 +222,7 @@ void RenderTableSection::addCell(RenderTableCell* cell, RenderTableRow* row)
unsigned cSpan = cell->colSpan();
Vector<RenderTable::ColumnStruct>& columns = table()->columns();
unsigned nCols = columns.size();
- // addCell should be called only after m_cRow has been incremented.
- ASSERT(m_cRow);
- unsigned insertionRow = m_cRow - 1;
+ unsigned insertionRow = row->rowIndex();
// ### mozilla still seems to do the old HTML way, even for strict DTD
// (see the annotation on table cell layouting in the CSS specs and the testcase below:
@@ -271,7 +266,6 @@ void RenderTableSection::addCell(RenderTableCell* cell, RenderTableRow* row)
cSpan -= currentSpan;
inColSpan = true;
}
- cell->setRow(insertionRow);
cell->setCol(table()->effColToCol(col));
}
@@ -327,8 +321,9 @@ int RenderTableSection::calcRowLogicalHeight()
RenderTableCell* cell;
int spacing = table()->vBorderSpacing();
-
- LayoutStateMaintainer statePusher(view());
+
+ RenderView* viewRenderer = view();
+ LayoutStateMaintainer statePusher(viewRenderer);
m_rowPos.resize(m_grid.size() + 1);
m_rowPos[0] = spacing;
@@ -338,7 +333,7 @@ int RenderTableSection::calcRowLogicalHeight()
LayoutUnit baselineDescent = 0;
// Our base size is the biggest logical height from our cells' styles (excluding row spanning cells).
- m_rowPos[r + 1] = max(m_rowPos[r] + m_grid[r].logicalHeight.calcMinValue(0), 0);
+ m_rowPos[r + 1] = max(m_rowPos[r] + minimumIntValueForLength(m_grid[r].logicalHeight, 0, viewRenderer), 0);
Row& row = m_grid[r].row;
unsigned totalCols = row.size();
@@ -352,11 +347,11 @@ int RenderTableSection::calcRowLogicalHeight()
// FIXME: We are always adding the height of a rowspan to the last rows which doesn't match
// other browsers. See webkit.org/b/52185 for example.
- if ((cell->row() + cell->rowSpan() - 1) != r)
+ if ((cell->rowIndex() + cell->rowSpan() - 1) != r)
continue;
// For row spanning cells, |r| is the last row in the span.
- unsigned cellStartRow = cell->row();
+ unsigned cellStartRow = cell->rowIndex();
if (cell->hasOverrideHeight()) {
if (!statePusher.didPush()) {
@@ -366,7 +361,7 @@ int RenderTableSection::calcRowLogicalHeight()
}
cell->clearIntrinsicPadding();
cell->clearOverrideSize();
- cell->setChildNeedsLayout(true, false);
+ cell->setChildNeedsLayout(true, MarkOnlyThis);
cell->layoutIfNeeded();
}
@@ -376,7 +371,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) {
- int baselinePosition = cell->cellBaselinePosition();
+ LayoutUnit baselinePosition = cell->cellBaselinePosition();
if (baselinePosition > cell->borderBefore() + cell->paddingBefore()) {
m_grid[r].baseline = max(m_grid[r].baseline, baselinePosition - cell->intrinsicPaddingBefore());
baselineDescent = max(baselineDescent, m_rowPos[cellStartRow] + cellLogicalHeight - (baselinePosition - cell->intrinsicPaddingBefore()));
@@ -387,7 +382,7 @@ int RenderTableSection::calcRowLogicalHeight()
// do we have baseline aligned elements?
if (m_grid[r].baseline)
// increase rowheight if baseline requires
- m_rowPos[r + 1] = max(m_rowPos[r + 1], m_grid[r].baseline + baselineDescent);
+ m_rowPos[r + 1] = max<int>(m_rowPos[r + 1], m_grid[r].baseline + baselineDescent);
// Add the border-spacing to our final position.
m_rowPos[r + 1] += m_grid[r].rowRenderer ? spacing : 0;
@@ -417,21 +412,17 @@ void RenderTableSection::layout()
}
}
statePusher.pop();
-
- if (hasOverflowClip() && !hasLayer())
- updateCachedSizeForOverflowClip();
-
setNeedsLayout(false);
}
-int RenderTableSection::distributeExtraLogicalHeightToPercentRows(int extraLogicalHeight, int totalPercent)
+void RenderTableSection::distributeExtraLogicalHeightToPercentRows(int& extraLogicalHeight, int totalPercent)
{
if (!totalPercent)
- return extraLogicalHeight;
+ return;
unsigned totalRows = m_grid.size();
int totalHeight = m_rowPos[totalRows] + extraLogicalHeight;
- int add = 0;
+ int totalLogicalHeightAdded = 0;
totalPercent = min(totalPercent, 100);
int rowHeight = m_rowPos[1] - m_rowPos[0];
for (unsigned r = 0; r < totalRows; ++r) {
@@ -440,56 +431,54 @@ int RenderTableSection::distributeExtraLogicalHeightToPercentRows(int extraLogic
// If toAdd is negative, then we don't want to shrink the row (this bug
// affected Outlook Web Access).
toAdd = max(0, toAdd);
- add += toAdd;
+ totalLogicalHeightAdded += toAdd;
extraLogicalHeight -= toAdd;
totalPercent -= m_grid[r].logicalHeight.percent();
}
ASSERT(totalRows >= 1);
if (r < totalRows - 1)
rowHeight = m_rowPos[r + 2] - m_rowPos[r + 1];
- m_rowPos[r + 1] += add;
+ m_rowPos[r + 1] += totalLogicalHeightAdded;
}
- return extraLogicalHeight;
}
-int RenderTableSection::distributeExtraLogicalHeightToAutoRows(int extraLogicalHeight, unsigned autoRowsCount)
+void RenderTableSection::distributeExtraLogicalHeightToAutoRows(int& extraLogicalHeight, unsigned autoRowsCount)
{
if (!autoRowsCount)
- return extraLogicalHeight;
+ return;
- int add = 0;
+ int totalLogicalHeightAdded = 0;
for (unsigned r = 0; r < m_grid.size(); ++r) {
if (autoRowsCount > 0 && m_grid[r].logicalHeight.isAuto()) {
// Recomputing |extraLogicalHeightForRow| guarantees that we properly ditribute round |extraLogicalHeight|.
int extraLogicalHeightForRow = extraLogicalHeight / autoRowsCount;
- add += extraLogicalHeightForRow;
+ totalLogicalHeightAdded += extraLogicalHeightForRow;
extraLogicalHeight -= extraLogicalHeightForRow;
--autoRowsCount;
}
- m_rowPos[r + 1] += add;
+ m_rowPos[r + 1] += totalLogicalHeightAdded;
}
- return extraLogicalHeight;
}
-int RenderTableSection::distributeRemainingExtraLogicalHeight(int extraLogicalHeight)
+void RenderTableSection::distributeRemainingExtraLogicalHeight(int& extraLogicalHeight)
{
unsigned totalRows = m_grid.size();
if (extraLogicalHeight <= 0 || !m_rowPos[totalRows])
- return extraLogicalHeight;
+ return;
// FIXME: m_rowPos[totalRows] - m_rowPos[0] is the total rows' size.
int totalRowSize = m_rowPos[totalRows];
- int add = 0;
+ int totalLogicalHeightAdded = 0;
int previousRowPosition = m_rowPos[0];
for (unsigned r = 0; r < totalRows; r++) {
// weight with the original height
- add += extraLogicalHeight * (m_rowPos[r + 1] - previousRowPosition) / totalRowSize;
+ totalLogicalHeightAdded += extraLogicalHeight * (m_rowPos[r + 1] - previousRowPosition) / totalRowSize;
previousRowPosition = m_rowPos[r + 1];
- m_rowPos[r + 1] += add;
+ m_rowPos[r + 1] += totalLogicalHeightAdded;
}
- return extraLogicalHeight;
+ extraLogicalHeight -= totalLogicalHeightAdded;
}
int RenderTableSection::distributeExtraLogicalHeightToRows(int extraLogicalHeight)
@@ -514,13 +503,13 @@ int RenderTableSection::distributeExtraLogicalHeightToRows(int extraLogicalHeigh
}
int remainingExtraLogicalHeight = extraLogicalHeight;
- remainingExtraLogicalHeight = distributeExtraLogicalHeightToPercentRows(remainingExtraLogicalHeight, totalPercent);
- remainingExtraLogicalHeight = distributeExtraLogicalHeightToAutoRows(remainingExtraLogicalHeight, autoRowsCount);
- remainingExtraLogicalHeight = distributeRemainingExtraLogicalHeight(remainingExtraLogicalHeight);
- return remainingExtraLogicalHeight;
+ distributeExtraLogicalHeightToPercentRows(remainingExtraLogicalHeight, totalPercent);
+ distributeExtraLogicalHeightToAutoRows(remainingExtraLogicalHeight, autoRowsCount);
+ distributeRemainingExtraLogicalHeight(remainingExtraLogicalHeight);
+ return extraLogicalHeight - remainingExtraLogicalHeight;
}
-int RenderTableSection::layoutRows(int extraLogicalHeight)
+void RenderTableSection::layoutRows()
{
#ifndef NDEBUG
setNeedsLayoutIsForbidden(true);
@@ -538,8 +527,6 @@ int RenderTableSection::layoutRows(int extraLogicalHeight)
m_overflowingCells.clear();
m_forceSlowPaintPathWithOverflowingCell = false;
- extraLogicalHeight = distributeExtraLogicalHeightToRows(extraLogicalHeight);
-
int hspacing = table()->hBorderSpacing();
int vspacing = table()->vBorderSpacing();
unsigned nEffCols = table()->numEffCols();
@@ -562,7 +549,7 @@ int RenderTableSection::layoutRows(int extraLogicalHeight)
if (!cell || cs.inColSpan)
continue;
- rindx = cell->row();
+ rindx = cell->rowIndex();
rHeight = m_rowPos[rindx + cell->rowSpan()] - m_rowPos[rindx] - vspacing;
// Force percent height children to lay themselves out again.
@@ -586,7 +573,7 @@ int RenderTableSection::layoutRows(int extraLogicalHeight)
if (!o->isText() && o->style()->logicalHeight().isPercent() && (flexAllChildren || o->isReplaced() || (o->isBox() && toRenderBox(o)->scrollsOverflow()))) {
// Tables with no sections do not flex.
if (!o->isTable() || toRenderTable(o)->hasSections()) {
- o->setNeedsLayout(true, false);
+ o->setNeedsLayout(true, MarkOnlyThis);
cellChildrenFlex = true;
}
}
@@ -602,7 +589,7 @@ int RenderTableSection::layoutRows(int extraLogicalHeight)
while (box != cell) {
if (box->normalChildNeedsLayout())
break;
- box->setChildNeedsLayout(true, false);
+ box->setChildNeedsLayout(true, MarkOnlyThis);
box = box->containingBlock();
ASSERT(box);
if (!box)
@@ -613,7 +600,7 @@ int RenderTableSection::layoutRows(int extraLogicalHeight)
}
if (cellChildrenFlex) {
- cell->setChildNeedsLayout(true, false);
+ cell->setChildNeedsLayout(true, MarkOnlyThis);
// Alignment within a cell is based off the calculated
// height, which becomes irrelevant once the cell has
// been resized based off its percentage.
@@ -640,7 +627,7 @@ int RenderTableSection::layoutRows(int extraLogicalHeight)
case TEXT_TOP:
case TEXT_BOTTOM:
case BASELINE: {
- int b = cell->cellBaselinePosition();
+ LayoutUnit b = cell->cellBaselinePosition();
if (b > cell->borderBefore() + cell->paddingBefore())
intrinsicPaddingBefore = getBaseline(r) - (b - oldIntrinsicPaddingBefore);
break;
@@ -672,16 +659,26 @@ int RenderTableSection::layoutRows(int extraLogicalHeight)
view()->addLayoutDelta(oldCellRect.location() - cell->location());
if (intrinsicPaddingBefore != oldIntrinsicPaddingBefore || intrinsicPaddingAfter != oldIntrinsicPaddingAfter)
- cell->setNeedsLayout(true, false);
+ cell->setNeedsLayout(true, MarkOnlyThis);
if (!cell->needsLayout() && view()->layoutState()->pageLogicalHeight() && view()->layoutState()->pageLogicalOffset(cell->logicalTop()) != cell->pageLogicalOffset())
- cell->setChildNeedsLayout(true, false);
+ cell->setChildNeedsLayout(true, MarkOnlyThis);
cell->layoutIfNeeded();
// FIXME: Make pagination work with vertical tables.
- if (style()->isHorizontalWritingMode() && view()->layoutState()->pageLogicalHeight() && cell->height() != rHeight)
- cell->setHeight(rHeight); // FIXME: Pagination might have made us change size. For now just shrink or grow the cell to fit without doing a relayout.
+ if (view()->layoutState()->pageLogicalHeight() && cell->logicalHeight() != rHeight) {
+ // FIXME: Pagination might have made us change size. For now just shrink or grow the cell to fit without doing a relayout.
+ // We'll also do a basic increase of the row height to accommodate the cell if it's bigger, but this isn't quite right
+ // either. It's at least stable though and won't result in an infinite # of relayouts that may never stabilize.
+ if (cell->logicalHeight() > rHeight) {
+ unsigned delta = cell->logicalHeight() - rHeight;
+ for (unsigned rowIndex = rindx + cell->rowSpan(); rowIndex <= totalRows; rowIndex++)
+ m_rowPos[rowIndex] += delta;
+ rHeight = cell->logicalHeight();
+ } else
+ cell->setLogicalHeight(rHeight);
+ }
LayoutSize childOffset(cell->location() - oldCellRect.location());
if (childOffset.width() || childOffset.height()) {
@@ -738,7 +735,6 @@ int RenderTableSection::layoutRows(int extraLogicalHeight)
ASSERT(hasOverflowingCell == this->hasOverflowingCell());
statePusher.pop();
- return height();
}
int RenderTableSection::calcOuterBorderBefore() const
@@ -954,7 +950,7 @@ LayoutUnit RenderTableSection::firstLineBoxBaseline() const
const CellStruct& cs = firstRow.at(i);
const RenderTableCell* cell = cs.primaryCell();
if (cell)
- firstLineBaseline = max(firstLineBaseline, cell->logicalTop() + cell->paddingBefore() + cell->borderBefore() + cell->contentLogicalHeight(IncludeIntrinsicPadding));
+ firstLineBaseline = max(firstLineBaseline, cell->logicalTop() + cell->paddingBefore() + cell->borderBefore() + cell->contentLogicalHeight());
}
return firstLineBaseline;
@@ -988,15 +984,15 @@ void RenderTableSection::paint(PaintInfo& paintInfo, const LayoutPoint& paintOff
static inline bool compareCellPositions(RenderTableCell* elem1, RenderTableCell* elem2)
{
- return elem1->row() < elem2->row();
+ return elem1->rowIndex() < elem2->rowIndex();
}
// This comparison is used only when we have overflowing cells as we have an unsorted array to sort. We thus need
// to sort both on rows and columns to properly repaint.
static inline bool compareCellPositionsWithOverflowingCells(RenderTableCell* elem1, RenderTableCell* elem2)
{
- if (elem1->row() != elem2->row())
- return elem1->row() < elem2->row();
+ if (elem1->rowIndex() != elem2->rowIndex())
+ return elem1->rowIndex() < elem2->rowIndex();
return elem1->col() < elem2->col();
}
@@ -1222,6 +1218,7 @@ void RenderTableSection::recalcCells()
RenderTableRow* tableRow = toRenderTableRow(row);
m_grid[insertionRow].rowRenderer = tableRow;
+ tableRow->setRowIndex(insertionRow);
setRowLogicalHeightToRowStyleLogicalHeightIfNotRelative(m_grid[insertionRow]);
for (RenderObject* cell = row->firstChild(); cell; cell = cell->nextSibling()) {
@@ -1388,16 +1385,6 @@ bool RenderTableSection::nodeAtPoint(const HitTestRequest& request, HitTestResul
}
-unsigned RenderTableSection::rowIndexForRenderer(const RenderTableRow* row) const
-{
- for (size_t i = 0; i < m_grid.size(); ++i) {
- if (m_grid[i].rowRenderer == row)
- return i;
- }
- ASSERT_NOT_REACHED();
- return 0;
-}
-
void RenderTableSection::removeCachedCollapsedBorders(const RenderTableCell* cell)
{
if (!table()->collapseBorders())
@@ -1421,4 +1408,12 @@ CollapsedBorderValue& RenderTableSection::cachedCollapsedBorder(const RenderTabl
return it->second;
}
+RenderTableSection* RenderTableSection::createAnonymousWithParentRenderer(const RenderObject* parent)
+{
+ RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(parent->style(), TABLE_ROW_GROUP);
+ RenderTableSection* newSection = new (parent->renderArena()) RenderTableSection(parent->document() /* is anonymous */);
+ newSection->setStyle(newStyle.release());
+ return newSection;
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/rendering/RenderTableSection.h b/Source/WebCore/rendering/RenderTableSection.h
index 8df74f06f..dcdc13490 100644
--- a/Source/WebCore/rendering/RenderTableSection.h
+++ b/Source/WebCore/rendering/RenderTableSection.h
@@ -73,7 +73,7 @@ public:
void setCellLogicalWidths();
int calcRowLogicalHeight();
- int layoutRows(int logicalHeight);
+ void layoutRows();
RenderTable* table() const { return toRenderTable(parent()); }
@@ -152,12 +152,20 @@ public:
void rowLogicalHeightChanged(unsigned rowIndex);
- unsigned rowIndexForRenderer(const RenderTableRow*) const;
-
void removeCachedCollapsedBorders(const RenderTableCell*);
void setCachedCollapsedBorder(const RenderTableCell*, CollapsedBorderSide, CollapsedBorderValue);
CollapsedBorderValue& cachedCollapsedBorder(const RenderTableCell*, CollapsedBorderSide);
+ // distributeExtraLogicalHeightToRows methods return the *consumed* extra logical height.
+ // FIXME: We may want to introduce a structure holding the in-flux layout information.
+ int distributeExtraLogicalHeightToRows(int extraLogicalHeight);
+
+ static RenderTableSection* createAnonymousWithParentRenderer(const RenderObject*);
+ virtual RenderBox* createAnonymousBoxWithSameTypeAs(const RenderObject* parent) const OVERRIDE
+ {
+ return createAnonymousWithParentRenderer(parent);
+ }
+
protected:
virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
@@ -185,12 +193,9 @@ private:
void ensureRows(unsigned);
- // Those methods return the remaining extra logical height.
- // FIXME: We may want to introduce a structure holding the in-flux layout information.
- int distributeExtraLogicalHeightToRows(int extraLogicalHeight);
- int distributeExtraLogicalHeightToPercentRows(int extraLogicalHeight, int totalPercent);
- int distributeExtraLogicalHeightToAutoRows(int extraLogicalHeight, unsigned autoRowsCount);
- int distributeRemainingExtraLogicalHeight(int extraLogicalHeight);
+ void distributeExtraLogicalHeightToPercentRows(int& extraLogicalHeight, int totalPercent);
+ void distributeExtraLogicalHeightToAutoRows(int& extraLogicalHeight, unsigned autoRowsCount);
+ void distributeRemainingExtraLogicalHeight(int& extraLogicalHeight);
bool hasOverflowingCell() const { return m_overflowingCells.size() || m_forceSlowPaintPathWithOverflowingCell; }
diff --git a/Source/WebCore/rendering/RenderText.cpp b/Source/WebCore/rendering/RenderText.cpp
index d497a33d6..063efd5b8 100644
--- a/Source/WebCore/rendering/RenderText.cpp
+++ b/Source/WebCore/rendering/RenderText.cpp
@@ -53,6 +53,15 @@ using namespace Unicode;
namespace WebCore {
+class SameSizeAsRenderText : public RenderObject {
+ uint32_t bitfields : 16;
+ float widths[4];
+ String text;
+ void* pointers[2];
+};
+
+COMPILE_ASSERT(sizeof(RenderText) == sizeof(SameSizeAsRenderText), RenderText_should_stay_small);
+
class SecureTextTimer;
typedef HashMap<RenderText*, SecureTextTimer*> SecureTextTimerMap;
static SecureTextTimerMap* gSecureTextTimers = 0;
@@ -126,22 +135,23 @@ static void makeCapitalized(String* string, UChar previous)
RenderText::RenderText(Node* node, PassRefPtr<StringImpl> str)
: RenderObject(node)
- , m_minWidth(-1)
- , m_text(str)
- , m_firstTextBox(0)
- , m_lastTextBox(0)
- , m_maxWidth(-1)
- , m_beginMinWidth(0)
- , m_endMinWidth(0)
, m_hasTab(false)
, m_linesDirty(false)
, m_containsReversedText(false)
- , m_isAllASCII(m_text.containsOnlyASCII())
, m_knownToHaveNoOverflowAndNoFallbackFonts(false)
, m_needsTranscoding(false)
+ , m_minWidth(-1)
+ , m_maxWidth(-1)
+ , m_beginMinWidth(0)
+ , m_endMinWidth(0)
+ , m_text(str)
+ , m_firstTextBox(0)
+ , m_lastTextBox(0)
{
ASSERT(m_text);
+ m_isAllASCII = m_text.containsOnlyASCII();
+ m_canUseSimpleFontCodePath = computeCanUseSimpleFontCodePath();
setIsText();
view()->frameView()->incrementVisuallyNonEmptyCharacterCount(m_text.length());
@@ -201,10 +211,8 @@ void RenderText::styleDidChange(StyleDifference diff, const RenderStyle* oldStyl
ETextTransform oldTransform = oldStyle ? oldStyle->textTransform() : TTNONE;
ETextSecurity oldSecurity = oldStyle ? oldStyle->textSecurity() : TSNONE;
- if (needsResetText || oldTransform != newStyle->textTransform() || oldSecurity != newStyle->textSecurity()) {
- if (RefPtr<StringImpl> textToTransform = originalText())
- setText(textToTransform.release(), true);
- }
+ if (needsResetText || oldTransform != newStyle->textTransform() || oldSecurity != newStyle->textSecurity())
+ transformText();
}
void RenderText::removeAndDestroyTextBoxes()
@@ -312,7 +320,7 @@ void RenderText::absoluteRects(Vector<IntRect>& rects, const LayoutPoint& accumu
static FloatRect localQuadForTextBox(InlineTextBox* box, unsigned start, unsigned end, bool useSelectionHeight)
{
unsigned realEnd = min(box->end() + 1, end);
- IntRect r = box->localSelectionRect(start, realEnd);
+ LayoutRect r = box->localSelectionRect(start, realEnd);
if (r.height()) {
if (!useSelectionHeight) {
// Change the height and y position (or width and x for vertical text)
@@ -347,7 +355,7 @@ void RenderText::absoluteRectsForRange(Vector<IntRect>& rects, unsigned start, u
if (start <= box->start() && box->end() < end) {
FloatRect r = box->calculateBoundaries();
if (useSelectionHeight) {
- IntRect selectionRect = box->localSelectionRect(start, end);
+ LayoutRect selectionRect = box->localSelectionRect(start, end);
if (box->isHorizontal()) {
r.setHeight(selectionRect.height());
r.setY(selectionRect.y());
@@ -430,8 +438,7 @@ void RenderText::absoluteQuadsForRange(Vector<FloatQuad>& quads, unsigned start,
if (start <= box->start() && box->end() < end) {
FloatRect r = box->calculateBoundaries();
if (useSelectionHeight) {
- // FIXME: localSelectionRect should switch to return FloatRect soon with the subpixellayout branch.
- IntRect selectionRect = box->localSelectionRect(start, end);
+ LayoutRect selectionRect = box->localSelectionRect(start, end);
if (box->isHorizontal()) {
r.setHeight(selectionRect.height());
r.setY(selectionRect.y());
@@ -754,6 +761,7 @@ ALWAYS_INLINE float RenderText::widthFromCache(const Font& f, int start, int len
run.setCharactersLength(textLength() - start);
ASSERT(run.charactersLength() >= run.length());
+ run.setCharacterScanForCodePath(!canUseSimpleFontCodePath());
run.setAllowTabs(allowTabs());
run.setXPos(xPos);
return f.width(run, fallbackFonts, glyphOverflow);
@@ -1239,6 +1247,12 @@ void RenderText::setTextWithOffset(PassRefPtr<StringImpl> text, unsigned offset,
setText(text, force);
}
+void RenderText::transformText()
+{
+ if (RefPtr<StringImpl> textToTransform = originalText())
+ setText(textToTransform.release(), true);
+}
+
static inline bool isInlineFlowOrEmptyText(const RenderObject* o)
{
if (o->isRenderInline())
@@ -1318,6 +1332,7 @@ void RenderText::setTextInternal(PassRefPtr<StringImpl> text)
ASSERT(!isBR() || (textLength() == 1 && m_text[0] == '\n'));
m_isAllASCII = m_text.containsOnlyASCII();
+ m_canUseSimpleFontCodePath = computeCanUseSimpleFontCodePath();
}
void RenderText::secureText(UChar mask)
@@ -1461,6 +1476,7 @@ float RenderText::width(unsigned from, unsigned len, const Font& f, float xPos,
run.setCharactersLength(textLength() - from);
ASSERT(run.charactersLength() >= run.length());
+ run.setCharacterScanForCodePath(!canUseSimpleFontCodePath());
run.setAllowTabs(allowTabs());
run.setXPos(xPos);
w = f.width(run, fallbackFonts, glyphOverflow);
@@ -1469,9 +1485,9 @@ float RenderText::width(unsigned from, unsigned len, const Font& f, float xPos,
return w;
}
-LayoutRect RenderText::linesBoundingBox() const
+IntRect RenderText::linesBoundingBox() const
{
- LayoutRect result;
+ IntRect result;
ASSERT(!firstTextBox() == !lastTextBox()); // Either both are null or both exist.
if (firstTextBox() && lastTextBox()) {
@@ -1503,8 +1519,8 @@ LayoutRect RenderText::linesVisualOverflowBoundingBox() const
return LayoutRect();
// Return the width of the minimal left side and the maximal right side.
- LayoutUnit logicalLeftSide = numeric_limits<LayoutUnit>::max();
- LayoutUnit logicalRightSide = numeric_limits<LayoutUnit>::min();
+ LayoutUnit logicalLeftSide = MAX_LAYOUT_UNIT;
+ LayoutUnit logicalRightSide = MIN_LAYOUT_UNIT;
for (InlineTextBox* curr = firstTextBox(); curr; curr = curr->nextTextBox()) {
logicalLeftSide = min(logicalLeftSide, curr->logicalLeftVisualOverflow());
logicalRightSide = max(logicalRightSide, curr->logicalRightVisualOverflow());
@@ -1548,7 +1564,7 @@ LayoutRect RenderText::selectionRectForRepaint(RenderBoxModelObject* repaintCont
// Now calculate startPos and endPos for painting selection.
// We include a selection while endPos > 0
- LayoutUnit startPos, endPos;
+ int startPos, endPos;
if (selectionState() == SelectionInside) {
// We are fully selected.
startPos = 0;
@@ -1781,6 +1797,13 @@ int RenderText::nextOffset(int current) const
return result;
}
+bool RenderText::computeCanUseSimpleFontCodePath() const
+{
+ if (isAllASCII())
+ return true;
+ return Font::characterRangeCodePath(characters(), length()) == Font::Simple;
+}
+
#ifndef NDEBUG
void RenderText::checkConsistency() const
diff --git a/Source/WebCore/rendering/RenderText.h b/Source/WebCore/rendering/RenderText.h
index e2c6a8a69..9043b0954 100644
--- a/Source/WebCore/rendering/RenderText.h
+++ b/Source/WebCore/rendering/RenderText.h
@@ -24,6 +24,7 @@
#define RenderText_h
#include "RenderObject.h"
+#include "RenderView.h"
#include <wtf/Forward.h>
namespace WebCore {
@@ -82,23 +83,25 @@ public:
float& beginMaxW, float& endMaxW,
float& minW, float& maxW, bool& stripFrontSpaces);
- virtual LayoutRect linesBoundingBox() const;
+ virtual IntRect linesBoundingBox() const;
LayoutRect linesVisualOverflowBoundingBox() const;
FloatPoint firstRunOrigin() const;
float firstRunX() const;
float firstRunY() const;
- void setText(PassRefPtr<StringImpl>, bool force = false);
+ virtual void setText(PassRefPtr<StringImpl>, bool force = false);
void setTextWithOffset(PassRefPtr<StringImpl>, unsigned offset, unsigned len, bool force = false);
+ virtual void transformText();
+
virtual bool canBeSelectionLeaf() const { return true; }
virtual void setSelectionState(SelectionState s);
virtual LayoutRect selectionRectForRepaint(RenderBoxModelObject* repaintContainer, bool clipToVisibleContent = true);
virtual LayoutRect localCaretRect(InlineBox*, int caretOffset, LayoutUnit* extraWidthToEndOfLine = 0);
- virtual LayoutUnit marginLeft() const { return style()->marginLeft().calcMinValue(0); }
- virtual LayoutUnit marginRight() const { return style()->marginRight().calcMinValue(0); }
+ virtual LayoutUnit marginLeft() const { return minimumValueForLength(style()->marginLeft(), 0, view()); }
+ virtual LayoutUnit marginRight() const { return minimumValueForLength(style()->marginRight(), 0, view()); }
virtual LayoutRect clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer) const;
@@ -126,7 +129,8 @@ public:
virtual void computePreferredLogicalWidths(float leadWidth);
bool isAllCollapsibleWhitespace();
-
+
+ bool canUseSimpleFontCodePath() const { return m_canUseSimpleFontCodePath; }
bool knownToHaveNoOverflowAndNoFallbackFonts() const { return m_knownToHaveNoOverflowAndNoFallbackFonts; }
void removeAndDestroyTextBoxes();
@@ -145,6 +149,8 @@ protected:
private:
void computePreferredLogicalWidths(float leadWidth, HashSet<const SimpleFontData*>& fallbackFonts, GlyphOverflow&);
+ bool computeCanUseSimpleFontCodePath() const;
+
// Make length() private so that callers that have a RenderText*
// will use the more efficient textLength() instead, while
// callers with a RenderObject* can continue to use length().
@@ -160,20 +166,9 @@ private:
bool isAllASCII() const { return m_isAllASCII; }
void updateNeedsTranscoding();
- inline void transformText(String&) const;
void secureText(UChar mask);
- float m_minWidth; // here to minimize padding in 64-bit.
-
- String m_text;
-
- InlineTextBox* m_firstTextBox;
- InlineTextBox* m_lastTextBox;
-
- float m_maxWidth;
- float m_beginMinWidth;
- float m_endMinWidth;
-
+ // We put the bitfield first to minimize padding on 64-bit.
bool m_hasBreakableChar : 1; // Whether or not we can be broken into multiple lines.
bool m_hasBreak : 1; // Whether or not we have a hard break (e.g., <pre> with '\n').
bool m_hasTab : 1; // Whether or not we have a variable width tab character (e.g., <pre> with '\t').
@@ -185,8 +180,19 @@ private:
// or removed).
bool m_containsReversedText : 1;
bool m_isAllASCII : 1;
+ bool m_canUseSimpleFontCodePath : 1;
mutable bool m_knownToHaveNoOverflowAndNoFallbackFonts : 1;
bool m_needsTranscoding : 1;
+
+ float m_minWidth;
+ float m_maxWidth;
+ float m_beginMinWidth;
+ float m_endMinWidth;
+
+ String m_text;
+
+ InlineTextBox* m_firstTextBox;
+ InlineTextBox* m_lastTextBox;
};
inline RenderText* toRenderText(RenderObject* object)
diff --git a/Source/WebCore/rendering/RenderTextControl.cpp b/Source/WebCore/rendering/RenderTextControl.cpp
index 2b311f18e..ddc647570 100644
--- a/Source/WebCore/rendering/RenderTextControl.cpp
+++ b/Source/WebCore/rendering/RenderTextControl.cpp
@@ -291,7 +291,7 @@ RenderObject* RenderTextControl::layoutSpecialExcludedChild(bool relayoutChildre
// The markParents arguments should be false because this function is
// called from layout() of the parent and the placeholder layout doesn't
// affect the parent layout.
- placeholderRenderer->setChildNeedsLayout(true, false);
+ placeholderRenderer->setChildNeedsLayout(true, MarkOnlyThis);
}
return placeholderRenderer;
}
diff --git a/Source/WebCore/rendering/RenderTextControlSingleLine.cpp b/Source/WebCore/rendering/RenderTextControlSingleLine.cpp
index e7ecedfa6..229fed994 100644
--- a/Source/WebCore/rendering/RenderTextControlSingleLine.cpp
+++ b/Source/WebCore/rendering/RenderTextControlSingleLine.cpp
@@ -25,7 +25,6 @@
#include "RenderTextControlSingleLine.h"
#include "CSSFontSelector.h"
-#include "CSSStyleSelector.h"
#include "CSSValueKeywords.h"
#include "Chrome.h"
#include "Frame.h"
@@ -43,6 +42,7 @@
#include "SearchPopupMenu.h"
#include "Settings.h"
#include "SimpleFontData.h"
+#include "StyleResolver.h"
#include "TextControlInnerElements.h"
using namespace std;
@@ -213,13 +213,7 @@ void RenderTextControlSingleLine::layout()
// and type=search if the text height is taller than the contentHeight()
// because of compability.
- LayoutUnit oldHeight = height();
- computeLogicalHeight();
-
- LayoutUnit oldWidth = width();
- computeLogicalWidth();
-
- bool relayoutChildren = oldHeight != height() || oldWidth != width();
+ RenderBlock::layoutBlock(false);
RenderBox* innerTextRenderer = innerTextElement()->renderBox();
ASSERT(innerTextRenderer);
@@ -234,7 +228,8 @@ void RenderTextControlSingleLine::layout()
LayoutUnit heightLimit = (inputElement()->isSearchField() || !container) ? height() : contentHeight();
if (currentHeight > heightLimit) {
if (desiredHeight != currentHeight)
- relayoutChildren = true;
+ setNeedsLayout(true, MarkOnlyThis);
+
innerTextRenderer->style()->setHeight(Length(desiredHeight, Fixed));
m_desiredInnerTextHeight = desiredHeight;
if (innerBlockRenderer)
@@ -246,15 +241,17 @@ void RenderTextControlSingleLine::layout()
LayoutUnit containerHeight = containerRenderer->height();
if (containerHeight > heightLimit) {
containerRenderer->style()->setHeight(Length(heightLimit, Fixed));
- relayoutChildren = true;
+ setNeedsLayout(true, MarkOnlyThis);
} else if (containerRenderer->height() < contentHeight()) {
containerRenderer->style()->setHeight(Length(contentHeight(), Fixed));
- relayoutChildren = true;
+ setNeedsLayout(true, MarkOnlyThis);
} else
containerRenderer->style()->setHeight(Length(containerHeight, Fixed));
}
- RenderBlock::layoutBlock(relayoutChildren);
+ // If we need another layout pass, we have changed one of children's height so we need to relayout them.
+ if (needsLayout())
+ RenderBlock::layoutBlock(true);
// Center the child block vertically
currentHeight = innerTextRenderer->height();
@@ -282,6 +279,7 @@ void RenderTextControlSingleLine::layout()
if (RenderBox* placeholderBox = placeholderElement ? placeholderElement->renderBox() : 0) {
placeholderBox->style()->setWidth(Length(innerTextRenderer->width() - placeholderBox->borderAndPaddingWidth(), Fixed));
placeholderBox->style()->setHeight(Length(innerTextRenderer->height() - placeholderBox->borderAndPaddingHeight(), Fixed));
+ bool placeholderBoxHadLayout = placeholderBox->everHadLayout();
placeholderBox->layoutIfNeeded();
LayoutPoint textOffset = innerTextRenderer->location();
if (innerBlockElement() && innerBlockElement()->renderBox())
@@ -289,6 +287,12 @@ void RenderTextControlSingleLine::layout()
if (containerRenderer)
textOffset += toLayoutSize(containerRenderer->location());
placeholderBox->setLocation(textOffset);
+
+ if (!placeholderBoxHadLayout && placeholderBox->checkForRepaintDuringLayout()) {
+ // This assumes a shadow tree without floats. If floats are added, the
+ // logic should be shared with RenderBlock::layoutBlockChild.
+ placeholderBox->repaint();
+ }
}
}
@@ -370,7 +374,7 @@ bool RenderTextControlSingleLine::hasControlClip() const
LayoutRect RenderTextControlSingleLine::controlClipRect(const LayoutPoint& additionalOffset) const
{
ASSERT(hasControlClip());
- LayoutRect clipRect = LayoutRect(containerElement()->renderBox()->frameRect());
+ LayoutRect clipRect = unionRect(contentBoxRect(), containerElement()->renderBox()->frameRect());
clipRect.moveBy(additionalOffset);
return clipRect;
}
@@ -670,7 +674,7 @@ void RenderTextControlSingleLine::setTextFromItem(unsigned listIndex)
FontSelector* RenderTextControlSingleLine::fontSelector() const
{
- return document()->styleSelector()->fontSelector();
+ return document()->styleResolver()->fontSelector();
}
HostWindow* RenderTextControlSingleLine::hostWindow() const
diff --git a/Source/WebCore/rendering/RenderTextFragment.cpp b/Source/WebCore/rendering/RenderTextFragment.cpp
index 1f267cde4..9f497d344 100644
--- a/Source/WebCore/rendering/RenderTextFragment.cpp
+++ b/Source/WebCore/rendering/RenderTextFragment.cpp
@@ -33,7 +33,6 @@ RenderTextFragment::RenderTextFragment(Node* node, StringImpl* str, int startOff
, m_start(startOffset)
, m_end(length)
, m_firstLetter(0)
- , m_allowFragmentReset(true)
{
}
@@ -43,7 +42,6 @@ RenderTextFragment::RenderTextFragment(Node* node, StringImpl* str)
, m_end(str ? str->length() : 0)
, m_contentString(str)
, m_firstLetter(0)
- , m_allowFragmentReset(true)
{
}
@@ -62,9 +60,7 @@ PassRefPtr<StringImpl> RenderTextFragment::originalText() const
void RenderTextFragment::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
- m_allowFragmentReset = false;
RenderText::styleDidChange(diff, oldStyle);
- m_allowFragmentReset = true;
if (RenderBlock* block = blockForAccompanyingFirstLetter()) {
block->style()->removeCachedPseudoStyle(FIRST_LETTER);
@@ -79,25 +75,30 @@ void RenderTextFragment::willBeDestroyed()
RenderText::willBeDestroyed();
}
-void RenderTextFragment::setTextInternal(PassRefPtr<StringImpl> text)
+void RenderTextFragment::setText(PassRefPtr<StringImpl> text, bool force)
{
- RenderText::setTextInternal(text);
-
- if (m_allowFragmentReset) {
- m_start = 0;
- m_end = textLength();
- if (m_firstLetter) {
- ASSERT(!m_contentString);
- m_firstLetter->destroy();
- m_firstLetter = 0;
- if (Node* t = node()) {
- ASSERT(!t->renderer());
- t->setRenderer(this);
- }
+ RenderText::setText(text, force);
+
+ m_start = 0;
+ m_end = textLength();
+ if (m_firstLetter) {
+ ASSERT(!m_contentString);
+ m_firstLetter->destroy();
+ m_firstLetter = 0;
+ if (Node* t = node()) {
+ ASSERT(!t->renderer());
+ t->setRenderer(this);
}
}
}
+void RenderTextFragment::transformText()
+{
+ // Don't reset first-letter here because we are only transforming the truncated fragment.
+ if (RefPtr<StringImpl> textToTransform = originalText())
+ RenderText::setText(textToTransform.release(), true);
+}
+
UChar RenderTextFragment::previousCharacter() const
{
if (start()) {
diff --git a/Source/WebCore/rendering/RenderTextFragment.h b/Source/WebCore/rendering/RenderTextFragment.h
index 426276fe0..b7f3b0e9a 100644
--- a/Source/WebCore/rendering/RenderTextFragment.h
+++ b/Source/WebCore/rendering/RenderTextFragment.h
@@ -39,6 +39,8 @@ public:
virtual bool isTextFragment() const { return true; }
+ virtual bool canBeSelectionLeaf() const OVERRIDE { return node() && node()->rendererIsEditable(); }
+
unsigned start() const { return m_start; }
unsigned end() const { return m_end; }
@@ -48,13 +50,16 @@ public:
StringImpl* contentString() const { return m_contentString.get(); }
virtual PassRefPtr<StringImpl> originalText() const;
+ virtual void setText(PassRefPtr<StringImpl>, bool force = false) OVERRIDE;
+
+ virtual void transformText() OVERRIDE;
+
protected:
virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
private:
virtual void willBeDestroyed();
- virtual void setTextInternal(PassRefPtr<StringImpl>);
virtual UChar previousCharacter() const;
RenderBlock* blockForAccompanyingFirstLetter() const;
@@ -62,7 +67,6 @@ private:
unsigned m_end;
RefPtr<StringImpl> m_contentString;
RenderObject* m_firstLetter;
- bool m_allowFragmentReset;
};
inline RenderTextFragment* toRenderTextFragment(RenderObject* object)
diff --git a/Source/WebCore/rendering/RenderTheme.cpp b/Source/WebCore/rendering/RenderTheme.cpp
index 8fd2d6c8b..585385f1b 100644
--- a/Source/WebCore/rendering/RenderTheme.cpp
+++ b/Source/WebCore/rendering/RenderTheme.cpp
@@ -24,6 +24,7 @@
#include "CSSValueKeywords.h"
#include "Document.h"
+#include "FileList.h"
#include "FileSystem.h"
#include "FloatConversion.h"
#include "FocusController.h"
@@ -71,7 +72,7 @@ RenderTheme::RenderTheme()
{
}
-void RenderTheme::adjustStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e,
+void RenderTheme::adjustStyle(StyleResolver* styleResolver, RenderStyle* style, Element* e,
bool UAHasAppearance, const BorderData& border, const FillLayer& background, const Color& backgroundColor)
{
// Force inline and table display styles to be inline-block (except for table- which is block)
@@ -100,7 +101,6 @@ void RenderTheme::adjustStyle(CSSStyleSelector* selector, RenderStyle* style, El
#if USE(NEW_THEME)
switch (part) {
- case ListButtonPart:
case CheckboxPart:
case InnerSpinButtonPart:
case RadioPart:
@@ -183,48 +183,47 @@ void RenderTheme::adjustStyle(CSSStyleSelector* selector, RenderStyle* style, El
switch (style->appearance()) {
#if !USE(NEW_THEME)
case CheckboxPart:
- return adjustCheckboxStyle(selector, style, e);
+ return adjustCheckboxStyle(styleResolver, style, e);
case RadioPart:
- return adjustRadioStyle(selector, style, e);
+ return adjustRadioStyle(styleResolver, style, e);
case PushButtonPart:
case SquareButtonPart:
- case ListButtonPart:
case DefaultButtonPart:
case ButtonPart:
- return adjustButtonStyle(selector, style, e);
+ return adjustButtonStyle(styleResolver, style, e);
case InnerSpinButtonPart:
- return adjustInnerSpinButtonStyle(selector, style, e);
+ return adjustInnerSpinButtonStyle(styleResolver, style, e);
#endif
case TextFieldPart:
- return adjustTextFieldStyle(selector, style, e);
+ return adjustTextFieldStyle(styleResolver, style, e);
case TextAreaPart:
- return adjustTextAreaStyle(selector, style, e);
+ return adjustTextAreaStyle(styleResolver, style, e);
case MenulistPart:
- return adjustMenuListStyle(selector, style, e);
+ return adjustMenuListStyle(styleResolver, style, e);
case MenulistButtonPart:
- return adjustMenuListButtonStyle(selector, style, e);
+ return adjustMenuListButtonStyle(styleResolver, style, e);
case MediaSliderPart:
case MediaVolumeSliderPart:
case MediaFullScreenVolumeSliderPart:
case SliderHorizontalPart:
case SliderVerticalPart:
- return adjustSliderTrackStyle(selector, style, e);
+ return adjustSliderTrackStyle(styleResolver, style, e);
case SliderThumbHorizontalPart:
case SliderThumbVerticalPart:
- return adjustSliderThumbStyle(selector, style, e);
+ return adjustSliderThumbStyle(styleResolver, style, e);
case SearchFieldPart:
- return adjustSearchFieldStyle(selector, style, e);
+ return adjustSearchFieldStyle(styleResolver, style, e);
case SearchFieldCancelButtonPart:
- return adjustSearchFieldCancelButtonStyle(selector, style, e);
+ return adjustSearchFieldCancelButtonStyle(styleResolver, style, e);
case SearchFieldDecorationPart:
- return adjustSearchFieldDecorationStyle(selector, style, e);
+ return adjustSearchFieldDecorationStyle(styleResolver, style, e);
case SearchFieldResultsDecorationPart:
- return adjustSearchFieldResultsDecorationStyle(selector, style, e);
+ return adjustSearchFieldResultsDecorationStyle(styleResolver, style, e);
case SearchFieldResultsButtonPart:
- return adjustSearchFieldResultsButtonStyle(selector, style, e);
+ return adjustSearchFieldResultsButtonStyle(styleResolver, style, e);
#if ENABLE(PROGRESS_TAG)
case ProgressBarPart:
- return adjustProgressBarStyle(selector, style, e);
+ return adjustProgressBarStyle(styleResolver, style, e);
#endif
#if ENABLE(METER_TAG)
case MeterPart:
@@ -232,18 +231,18 @@ void RenderTheme::adjustStyle(CSSStyleSelector* selector, RenderStyle* style, El
case ContinuousCapacityLevelIndicatorPart:
case DiscreteCapacityLevelIndicatorPart:
case RatingLevelIndicatorPart:
- return adjustMeterStyle(selector, style, e);
+ return adjustMeterStyle(styleResolver, style, e);
#endif
#if ENABLE(INPUT_SPEECH)
case InputSpeechButtonPart:
- return adjustInputFieldSpeechButtonStyle(selector, style, e);
+ return adjustInputFieldSpeechButtonStyle(styleResolver, style, e);
#endif
default:
break;
}
}
-bool RenderTheme::paint(RenderObject* o, const PaintInfo& paintInfo, const LayoutRect& r)
+bool RenderTheme::paint(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
{
// If painting is disabled, but we aren't updating control tints, then just bail.
// If we are updating control tints, just schedule a repaint if the theme supports tinting
@@ -264,7 +263,6 @@ bool RenderTheme::paint(RenderObject* o, const PaintInfo& paintInfo, const Layou
case RadioPart:
case PushButtonPart:
case SquareButtonPart:
- case ListButtonPart:
case DefaultButtonPart:
case ButtonPart:
case InnerSpinButtonPart:
@@ -284,7 +282,6 @@ bool RenderTheme::paint(RenderObject* o, const PaintInfo& paintInfo, const Layou
return paintRadio(o, paintInfo, r);
case PushButtonPart:
case SquareButtonPart:
- case ListButtonPart:
case DefaultButtonPart:
case ButtonPart:
return paintButton(o, paintInfo, r);
@@ -311,7 +308,8 @@ bool RenderTheme::paint(RenderObject* o, const PaintInfo& paintInfo, const Layou
case SliderThumbHorizontalPart:
case SliderThumbVerticalPart:
return paintSliderThumb(o, paintInfo, r);
- case MediaFullscreenButtonPart:
+ case MediaEnterFullscreenButtonPart:
+ case MediaExitFullscreenButtonPart:
return paintMediaFullscreenButton(o, paintInfo, r);
case MediaPlayButtonPart:
return paintMediaPlayButton(o, paintInfo, r);
@@ -394,7 +392,6 @@ bool RenderTheme::paintBorderOnly(RenderObject* o, const PaintInfo& paintInfo, c
case RadioPart:
case PushButtonPart:
case SquareButtonPart:
- case ListButtonPart:
case DefaultButtonPart:
case ButtonPart:
case MenulistPart:
@@ -442,7 +439,6 @@ bool RenderTheme::paintDecorations(RenderObject* o, const PaintInfo& paintInfo,
case RadioPart:
case PushButtonPart:
case SquareButtonPart:
- case ListButtonPart:
case DefaultButtonPart:
case ButtonPart:
case MenulistPart:
@@ -505,13 +501,13 @@ String RenderTheme::formatMediaControlsRemainingTime(float currentTime, float du
return formatMediaControlsTime(currentTime - duration);
}
-LayoutPoint RenderTheme::volumeSliderOffsetFromMuteButton(RenderBox* muteButtonBox, const LayoutSize& size) const
+IntPoint RenderTheme::volumeSliderOffsetFromMuteButton(RenderBox* muteButtonBox, const IntSize& size) const
{
- LayoutUnit y = -size.height();
+ int y = -size.height();
FloatPoint absPoint = muteButtonBox->localToAbsolute(FloatPoint(muteButtonBox->pixelSnappedOffsetLeft(), y), true, true);
if (absPoint.y() < 0)
y = muteButtonBox->height();
- return LayoutPoint(0, y);
+ return IntPoint(0, y);
}
#endif
@@ -617,6 +613,13 @@ Color RenderTheme::platformInactiveListBoxSelectionForegroundColor() const
return platformInactiveSelectionForegroundColor();
}
+#if ENABLE(CALENDAR_PICKER)
+CString RenderTheme::extraCalendarPickerStyleSheet()
+{
+ return CString();
+}
+#endif
+
LayoutUnit RenderTheme::baselinePosition(const RenderObject* o) const
{
if (!o->isBox())
@@ -667,7 +670,7 @@ bool RenderTheme::isControlStyled(const RenderStyle* style, const BorderData& bo
}
}
-void RenderTheme::adjustRepaintRect(const RenderObject* o, LayoutRect& r)
+void RenderTheme::adjustRepaintRect(const RenderObject* o, IntRect& r)
{
#if USE(NEW_THEME)
m_theme->inflateControlPaintRect(o->style()->appearance(), controlStatesForRenderer(o), r, o->style()->effectiveZoom());
@@ -848,7 +851,7 @@ bool RenderTheme::isDefault(const RenderObject* o) const
#if !USE(NEW_THEME)
-void RenderTheme::adjustCheckboxStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+void RenderTheme::adjustCheckboxStyle(StyleResolver*, RenderStyle* style, Element*) const
{
// A summary of the rules for checkbox designed to match WinIE:
// width/height - honored (WinIE actually scales its control for small widths, but lets it overflow for small heights.)
@@ -865,7 +868,7 @@ void RenderTheme::adjustCheckboxStyle(CSSStyleSelector*, RenderStyle* style, Ele
style->setBoxShadow(nullptr);
}
-void RenderTheme::adjustRadioStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+void RenderTheme::adjustRadioStyle(StyleResolver*, RenderStyle* style, Element*) const
{
// A summary of the rules for checkbox designed to match WinIE:
// width/height - honored (WinIE actually scales its control for small widths, but lets it overflow for small heights.)
@@ -882,34 +885,34 @@ void RenderTheme::adjustRadioStyle(CSSStyleSelector*, RenderStyle* style, Elemen
style->setBoxShadow(nullptr);
}
-void RenderTheme::adjustButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+void RenderTheme::adjustButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
{
// Most platforms will completely honor all CSS, and so we have no need to adjust the style
// at all by default. We will still allow the theme a crack at setting up a desired vertical size.
setButtonSize(style);
}
-void RenderTheme::adjustInnerSpinButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const
+void RenderTheme::adjustInnerSpinButtonStyle(StyleResolver*, RenderStyle*, Element*) const
{
}
#endif
-void RenderTheme::adjustTextFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const
+void RenderTheme::adjustTextFieldStyle(StyleResolver*, RenderStyle*, Element*) const
{
}
-void RenderTheme::adjustTextAreaStyle(CSSStyleSelector*, RenderStyle*, Element*) const
+void RenderTheme::adjustTextAreaStyle(StyleResolver*, RenderStyle*, Element*) const
{
}
-void RenderTheme::adjustMenuListStyle(CSSStyleSelector*, RenderStyle*, Element*) const
+void RenderTheme::adjustMenuListStyle(StyleResolver*, RenderStyle*, Element*) const
{
}
#if ENABLE(INPUT_SPEECH)
-void RenderTheme::adjustInputFieldSpeechButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* element) const
+void RenderTheme::adjustInputFieldSpeechButtonStyle(StyleResolver* styleResolver, RenderStyle* style, Element* element) const
{
- RenderInputSpeech::adjustInputFieldSpeechButtonStyle(selector, style, element);
+ RenderInputSpeech::adjustInputFieldSpeechButtonStyle(styleResolver, style, element);
}
bool RenderTheme::paintInputFieldSpeechButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
@@ -919,12 +922,12 @@ bool RenderTheme::paintInputFieldSpeechButton(RenderObject* object, const PaintI
#endif
#if ENABLE(METER_TAG)
-void RenderTheme::adjustMeterStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+void RenderTheme::adjustMeterStyle(StyleResolver*, RenderStyle* style, Element*) const
{
style->setBoxShadow(nullptr);
}
-LayoutSize RenderTheme::meterSizeForBounds(const RenderMeter*, const LayoutRect& bounds) const
+IntSize RenderTheme::meterSizeForBounds(const RenderMeter*, const IntRect& bounds) const
{
return bounds.size();
}
@@ -952,7 +955,7 @@ double RenderTheme::animationDurationForProgressBar(RenderProgress*) const
return 0;
}
-void RenderTheme::adjustProgressBarStyle(CSSStyleSelector*, RenderStyle*, Element*) const
+void RenderTheme::adjustProgressBarStyle(StyleResolver*, RenderStyle*, Element*) const
{
}
#endif
@@ -962,15 +965,15 @@ bool RenderTheme::shouldHaveSpinButton(HTMLInputElement* inputElement) const
return inputElement->isSteppable() && !inputElement->isRangeControl();
}
-void RenderTheme::adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const
+void RenderTheme::adjustMenuListButtonStyle(StyleResolver*, RenderStyle*, Element*) const
{
}
-void RenderTheme::adjustSliderTrackStyle(CSSStyleSelector*, RenderStyle*, Element*) const
+void RenderTheme::adjustSliderTrackStyle(StyleResolver*, RenderStyle*, Element*) const
{
}
-void RenderTheme::adjustSliderThumbStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+void RenderTheme::adjustSliderThumbStyle(StyleResolver*, RenderStyle* style, Element*) const
{
adjustSliderThumbSize(style);
}
@@ -979,23 +982,23 @@ void RenderTheme::adjustSliderThumbSize(RenderStyle*) const
{
}
-void RenderTheme::adjustSearchFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const
+void RenderTheme::adjustSearchFieldStyle(StyleResolver*, RenderStyle*, Element*) const
{
}
-void RenderTheme::adjustSearchFieldCancelButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const
+void RenderTheme::adjustSearchFieldCancelButtonStyle(StyleResolver*, RenderStyle*, Element*) const
{
}
-void RenderTheme::adjustSearchFieldDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const
+void RenderTheme::adjustSearchFieldDecorationStyle(StyleResolver*, RenderStyle*, Element*) const
{
}
-void RenderTheme::adjustSearchFieldResultsDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const
+void RenderTheme::adjustSearchFieldResultsDecorationStyle(StyleResolver*, RenderStyle*, Element*) const
{
}
-void RenderTheme::adjustSearchFieldResultsButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const
+void RenderTheme::adjustSearchFieldResultsButtonStyle(StyleResolver*, RenderStyle*, Element*) const
{
}
@@ -1137,18 +1140,18 @@ String RenderTheme::fileListDefaultLabel(bool multipleFilesAllowed) const
return fileButtonNoFileSelectedLabel();
}
-String RenderTheme::fileListNameForWidth(const Vector<String>& filenames, const Font& font, int width, bool multipleFilesAllowed) const
+String RenderTheme::fileListNameForWidth(const FileList* fileList, const Font& font, int width, bool multipleFilesAllowed) const
{
if (width <= 0)
return String();
String string;
- if (filenames.isEmpty())
+ if (fileList->isEmpty())
string = fileListDefaultLabel(multipleFilesAllowed);
- else if (filenames.size() == 1)
- string = pathGetFileName(filenames[0]);
+ else if (fileList->length() == 1)
+ string = fileList->item(0)->name();
else
- return StringTruncator::rightTruncate(multipleFileUploadText(filenames.size()), width, font, StringTruncator::EnableRoundingHacks);
+ return StringTruncator::rightTruncate(multipleFileUploadText(fileList->length()), width, font, StringTruncator::EnableRoundingHacks);
return StringTruncator::centerTruncate(string, width, font, StringTruncator::EnableRoundingHacks);
}
diff --git a/Source/WebCore/rendering/RenderTheme.h b/Source/WebCore/rendering/RenderTheme.h
index 44ef1241e..e3e71475f 100644
--- a/Source/WebCore/rendering/RenderTheme.h
+++ b/Source/WebCore/rendering/RenderTheme.h
@@ -36,6 +36,7 @@
namespace WebCore {
class Element;
+class FileList;
class HTMLInputElement;
class PopupMenu;
class RenderMenuList;
@@ -70,13 +71,13 @@ public:
// metrics and defaults given the contents of the style. This includes sophisticated operations like
// selection of control size based off the font, the disabling of appearance when certain other properties like
// "border" are set, or if the appearance is not supported by the theme.
- void adjustStyle(CSSStyleSelector*, RenderStyle*, Element*, bool UAHasAppearance,
+ void adjustStyle(StyleResolver*, RenderStyle*, Element*, bool UAHasAppearance,
const BorderData&, const FillLayer&, const Color& backgroundColor);
// This method is called to paint the widget as a background of the RenderObject. A widget's foreground, e.g., the
// text of a button, is always rendered by the engine itself. The boolean return value indicates
// whether the CSS border/background should also be painted.
- bool paint(RenderObject*, const PaintInfo&, const LayoutRect&);
+ bool paint(RenderObject*, const PaintInfo&, const IntRect&);
bool paintBorderOnly(RenderObject*, const PaintInfo&, const IntRect&);
bool paintDecorations(RenderObject*, const PaintInfo&, const IntRect&);
@@ -93,6 +94,9 @@ public:
#if ENABLE(FULLSCREEN_API)
virtual String extraFullScreenStyleSheet() { return String(); };
#endif
+#if ENABLE(CALENDAR_PICKER)
+ virtual CString extraCalendarPickerStyleSheet();
+#endif
// A method to obtain the baseline position for a "leaf" control. This will only be used if a baseline
// position cannot be determined by examining child content. Checkboxes and radio buttons are examples of
@@ -114,7 +118,7 @@ public:
// Some controls may spill out of their containers (e.g., the check on an OS X checkbox). When these controls repaint,
// the theme needs to communicate this inflated rect to the engine so that it can invalidate the whole control.
- virtual void adjustRepaintRect(const RenderObject*, LayoutRect&);
+ virtual void adjustRepaintRect(const RenderObject*, IntRect&);
// This method is called whenever a relevant state changes on a particular themed object, e.g., the mouse becomes pressed
// or a control becomes disabled.
@@ -130,6 +134,9 @@ public:
// A method asking if the theme's controls actually care about redrawing when hovered.
virtual bool supportsHover(const RenderStyle*) const { return false; }
+ // A method asking if the platform is able to show datalist suggestions for a given input type.
+ virtual bool supportsDataListUI(const AtomicString&) const { return false; }
+
// Text selection colors.
Color activeSelectionBackgroundColor() const;
Color inactiveSelectionBackgroundColor() const;
@@ -176,7 +183,7 @@ public:
virtual ScrollbarControlSize scrollbarControlSizeForPart(ControlPart) { return RegularScrollbar; }
// Method for painting the caps lock indicator
- virtual bool paintCapsLockIndicator(RenderObject*, const PaintInfo&, const LayoutRect&) { return 0; };
+ virtual bool paintCapsLockIndicator(RenderObject*, const PaintInfo&, const IntRect&) { return 0; };
#if ENABLE(PROGRESS_TAG)
// Returns the repeat interval of the animation for the progress bar.
@@ -198,11 +205,11 @@ public:
virtual String formatMediaControlsRemainingTime(float currentTime, float duration) const;
// Returns the media volume slider container's offset from the mute button.
- virtual LayoutPoint volumeSliderOffsetFromMuteButton(RenderBox*, const LayoutSize&) const;
+ virtual IntPoint volumeSliderOffsetFromMuteButton(RenderBox*, const IntSize&) const;
#endif
#if ENABLE(METER_TAG)
- virtual LayoutSize meterSizeForBounds(const RenderMeter*, const LayoutRect&) const;
+ virtual IntSize meterSizeForBounds(const RenderMeter*, const IntRect&) const;
virtual bool supportsMeter(ControlPart) const;
#endif
@@ -215,7 +222,7 @@ public:
virtual bool popsMenuBySpaceOrReturn() const { return false; }
virtual String fileListDefaultLabel(bool multipleFilesAllowed) const;
- virtual String fileListNameForWidth(const Vector<String>& filenames, const Font&, int width, bool multipleFilesAllowed) const;
+ virtual String fileListNameForWidth(const FileList*, const Font&, int width, bool multipleFilesAllowed) const;
protected:
// The platform selection color.
@@ -234,68 +241,68 @@ protected:
#if !USE(NEW_THEME)
// Methods for each appearance value.
- virtual void adjustCheckboxStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustCheckboxStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintCheckbox(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
virtual void setCheckboxSize(RenderStyle*) const { }
- virtual void adjustRadioStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustRadioStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintRadio(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
virtual void setRadioSize(RenderStyle*) const { }
- virtual void adjustButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintButton(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
virtual void setButtonSize(RenderStyle*) const { }
- virtual void adjustInnerSpinButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustInnerSpinButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintInnerSpinButton(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
#endif
- virtual void adjustTextFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustTextFieldStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintTextField(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
- virtual void adjustTextAreaStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustTextAreaStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintTextArea(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
- virtual void adjustMenuListStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustMenuListStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintMenuList(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
- virtual void adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustMenuListButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintMenuListButton(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
#if ENABLE(METER_TAG)
- virtual void adjustMeterStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustMeterStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintMeter(RenderObject*, const PaintInfo&, const IntRect&);
#endif
#if ENABLE(PROGRESS_TAG)
- virtual void adjustProgressBarStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustProgressBarStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintProgressBar(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
#endif
#if ENABLE(INPUT_SPEECH)
- virtual void adjustInputFieldSpeechButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustInputFieldSpeechButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintInputFieldSpeechButton(RenderObject*, const PaintInfo&, const IntRect&);
#endif
- virtual void adjustSliderTrackStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustSliderTrackStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintSliderTrack(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
- virtual void adjustSliderThumbStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustSliderThumbStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintSliderThumb(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
- virtual void adjustSearchFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustSearchFieldStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintSearchField(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
- virtual void adjustSearchFieldCancelButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustSearchFieldCancelButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintSearchFieldCancelButton(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
- virtual void adjustSearchFieldDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustSearchFieldDecorationStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintSearchFieldDecoration(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
- virtual void adjustSearchFieldResultsDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustSearchFieldResultsDecorationStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintSearchFieldResultsDecoration(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
- virtual void adjustSearchFieldResultsButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustSearchFieldResultsButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintSearchFieldResultsButton(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
virtual bool paintMediaFullscreenButton(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
diff --git a/Source/WebCore/rendering/RenderThemeChromiumAndroid.cpp b/Source/WebCore/rendering/RenderThemeChromiumAndroid.cpp
index 949fdfb5d..8b7123088 100644
--- a/Source/WebCore/rendering/RenderThemeChromiumAndroid.cpp
+++ b/Source/WebCore/rendering/RenderThemeChromiumAndroid.cpp
@@ -75,7 +75,7 @@ String RenderThemeChromiumAndroid::extraDefaultStyleSheet()
String(themeChromiumAndroidUserAgentStyleSheet, sizeof(themeChromiumAndroidUserAgentStyleSheet));
}
-void RenderThemeChromiumAndroid::adjustInnerSpinButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+void RenderThemeChromiumAndroid::adjustInnerSpinButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
{
if (PlatformSupport::layoutTestMode()) {
// Match Chromium Linux spin button style in layout tests.
@@ -90,7 +90,7 @@ void RenderThemeChromiumAndroid::adjustInnerSpinButtonStyle(CSSStyleSelector*, R
bool RenderThemeChromiumAndroid::paintMediaFullscreenButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
{
#if ENABLE(VIDEO)
- return RenderMediaControlsChromium::paintMediaControlsPart(MediaFullscreenButton, object, paintInfo, rect);
+ return RenderMediaControlsChromium::paintMediaControlsPart(MediaEnterFullscreenButton, object, paintInfo, rect);
#else
UNUSED_PARAM(object);
UNUSED_PARAM(paintInfo);
diff --git a/Source/WebCore/rendering/RenderThemeChromiumAndroid.h b/Source/WebCore/rendering/RenderThemeChromiumAndroid.h
index 53490135c..3dcd6df93 100644
--- a/Source/WebCore/rendering/RenderThemeChromiumAndroid.h
+++ b/Source/WebCore/rendering/RenderThemeChromiumAndroid.h
@@ -37,7 +37,7 @@ public:
virtual Color systemColor(int cssValidId) const OVERRIDE;
- virtual void adjustInnerSpinButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const OVERRIDE;
+ virtual void adjustInnerSpinButtonStyle(StyleResolver*, RenderStyle*, Element*) const OVERRIDE;
virtual bool delegatesMenuListRendering() const OVERRIDE { return true; }
diff --git a/Source/WebCore/rendering/RenderThemeChromiumCommon.cpp b/Source/WebCore/rendering/RenderThemeChromiumCommon.cpp
new file mode 100644
index 000000000..c2b747306
--- /dev/null
+++ b/Source/WebCore/rendering/RenderThemeChromiumCommon.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "RenderThemeChromiumCommon.h"
+
+#include "InputType.h"
+
+namespace WebCore {
+
+bool RenderThemeChromiumCommon::supportsDataListUI(const AtomicString& type)
+{
+ // FIXME: We still need to support email, datetime, date, month, week, time, datetime-local, range, color.
+ return type == InputTypeNames::text() || type == InputTypeNames::search() || type == InputTypeNames::url()
+ || type == InputTypeNames::telephone() || type == InputTypeNames::number();
+}
+
+}
diff --git a/Source/WebCore/rendering/RenderThemeChromiumCommon.h b/Source/WebCore/rendering/RenderThemeChromiumCommon.h
new file mode 100644
index 000000000..be099a8e2
--- /dev/null
+++ b/Source/WebCore/rendering/RenderThemeChromiumCommon.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef RenderThemeChromiumCommon_h
+#define RenderThemeChromiumCommon_h
+
+#include <wtf/text/AtomicString.h>
+
+namespace WebCore {
+
+class RenderThemeChromiumCommon {
+public:
+ static bool supportsDataListUI(const AtomicString& type);
+};
+
+}
+
+#endif // RenderThemeChromiumCommon_h
diff --git a/Source/WebCore/rendering/RenderThemeChromiumLinux.cpp b/Source/WebCore/rendering/RenderThemeChromiumLinux.cpp
index d4ed2a1e7..019694f0d 100644
--- a/Source/WebCore/rendering/RenderThemeChromiumLinux.cpp
+++ b/Source/WebCore/rendering/RenderThemeChromiumLinux.cpp
@@ -305,7 +305,7 @@ bool RenderThemeChromiumLinux::paintSliderThumb(RenderObject* o, const PaintInfo
return false;
}
-void RenderThemeChromiumLinux::adjustInnerSpinButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+void RenderThemeChromiumLinux::adjustInnerSpinButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
{
IntSize size = PlatformSupport::getThemePartSize(PlatformSupport::PartInnerSpinButton);
diff --git a/Source/WebCore/rendering/RenderThemeChromiumLinux.h b/Source/WebCore/rendering/RenderThemeChromiumLinux.h
index 33b6f5425..7e308083f 100644
--- a/Source/WebCore/rendering/RenderThemeChromiumLinux.h
+++ b/Source/WebCore/rendering/RenderThemeChromiumLinux.h
@@ -71,7 +71,7 @@ namespace WebCore {
virtual bool paintSliderTrack(RenderObject*, const PaintInfo&, const IntRect&);
virtual bool paintSliderThumb(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustInnerSpinButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustInnerSpinButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintInnerSpinButton(RenderObject*, const PaintInfo&, const IntRect&);
virtual bool popsMenuBySpaceOrReturn() const OVERRIDE { return true; }
diff --git a/Source/WebCore/rendering/RenderThemeChromiumMac.h b/Source/WebCore/rendering/RenderThemeChromiumMac.h
index 232e0f66c..2b4c8c635 100644
--- a/Source/WebCore/rendering/RenderThemeChromiumMac.h
+++ b/Source/WebCore/rendering/RenderThemeChromiumMac.h
@@ -24,6 +24,7 @@
#ifndef RenderThemeChromiumMac_h
#define RenderThemeChromiumMac_h
+#import "RenderThemeChromiumCommon.h"
#import "RenderThemeMac.h"
namespace WebCore {
@@ -32,6 +33,8 @@ class RenderThemeChromiumMac : public RenderThemeMac {
public:
static PassRefPtr<RenderTheme> create();
+ virtual bool supportsDataListUI(const AtomicString& type) const OVERRIDE;
+
protected:
virtual bool paintTextField(RenderObject*, const PaintInfo&, const IntRect&);
#if ENABLE(VIDEO)
@@ -49,7 +52,7 @@ protected:
virtual bool paintMediaVolumeSliderContainer(RenderObject*, const PaintInfo&, const IntRect&);
virtual bool paintMediaVolumeSliderTrack(RenderObject*, const PaintInfo&, const IntRect&);
virtual bool paintMediaVolumeSliderThumb(RenderObject*, const PaintInfo&, const IntRect&);
- virtual LayoutPoint volumeSliderOffsetFromMuteButton(RenderBox*, const LayoutSize&) const;
+ virtual IntPoint volumeSliderOffsetFromMuteButton(RenderBox*, const IntSize&) const OVERRIDE;
virtual bool usesMediaControlStatusDisplay() { return false; }
virtual bool hasOwnDisabledStateHandlingFor(ControlPart) const { return true; }
#endif
@@ -64,6 +67,9 @@ private:
virtual Color disabledTextColor(const Color& textColor, const Color&) const OVERRIDE { return textColor; }
virtual void updateActiveState(NSCell*, const RenderObject*);
virtual String extraDefaultStyleSheet();
+#if ENABLE(CALENDAR_PICKER)
+ virtual CString extraCalendarPickerStyleSheet() OVERRIDE;
+#endif
virtual bool shouldShowPlaceholderWhenFocused() const OVERRIDE;
};
diff --git a/Source/WebCore/rendering/RenderThemeChromiumMac.mm b/Source/WebCore/rendering/RenderThemeChromiumMac.mm
index 82f2de1c3..a778228c5 100644
--- a/Source/WebCore/rendering/RenderThemeChromiumMac.mm
+++ b/Source/WebCore/rendering/RenderThemeChromiumMac.mm
@@ -19,6 +19,8 @@
*/
#import "config.h"
+
+#import "CalendarPickerMac.h"
#import "LocalCurrentGraphicsContext.h"
#import "RenderThemeChromiumMac.h"
#import "PaintInfo.h"
@@ -71,6 +73,11 @@ PassRefPtr<RenderTheme> RenderThemeChromiumMac::create()
return adoptRef(new RenderThemeChromiumMac);
}
+bool RenderThemeChromiumMac::supportsDataListUI(const AtomicString& type) const
+{
+ return RenderThemeChromiumCommon::supportsDataListUI(type);
+}
+
bool RenderThemeChromiumMac::usesTestModeFocusRingColor() const
{
return PlatformSupport::layoutTestMode();
@@ -190,6 +197,12 @@ String RenderThemeChromiumMac::extraDefaultStyleSheet()
String(themeChromiumUserAgentStyleSheet, sizeof(themeChromiumUserAgentStyleSheet));
}
+#if ENABLE(CALENDAR_PICKER)
+CString RenderThemeChromiumMac::extraCalendarPickerStyleSheet()
+{
+ return CString(calendarPickerMacCss, WTF_ARRAY_LENGTH(calendarPickerMacCss));
+}
+#endif
bool RenderThemeChromiumMac::paintMediaVolumeSliderContainer(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
{
@@ -211,7 +224,7 @@ bool RenderThemeChromiumMac::paintMediaSliderThumb(RenderObject* object, const P
return RenderMediaControlsChromium::paintMediaControlsPart(MediaSliderThumb, object, paintInfo, rect);
}
-LayoutPoint RenderThemeChromiumMac::volumeSliderOffsetFromMuteButton(RenderBox* muteButtonBox, const LayoutSize& size) const
+IntPoint RenderThemeChromiumMac::volumeSliderOffsetFromMuteButton(RenderBox* muteButtonBox, const IntSize& size) const
{
return RenderTheme::volumeSliderOffsetFromMuteButton(muteButtonBox, size);
}
diff --git a/Source/WebCore/rendering/RenderThemeChromiumSkia.cpp b/Source/WebCore/rendering/RenderThemeChromiumSkia.cpp
index 5715b6684..902dad013 100644
--- a/Source/WebCore/rendering/RenderThemeChromiumSkia.cpp
+++ b/Source/WebCore/rendering/RenderThemeChromiumSkia.cpp
@@ -25,7 +25,6 @@
#include "RenderThemeChromiumSkia.h"
#include "CSSValueKeywords.h"
-#include "CurrentTime.h"
#include "GraphicsContext.h"
#include "HTMLMediaElement.h"
#include "HTMLNames.h"
@@ -44,6 +43,8 @@
#include "TransformationMatrix.h"
#include "UserAgentStyleSheets.h"
+#include <wtf/CurrentTime.h>
+
#include "SkShader.h"
#include "SkGradientShader.h"
@@ -124,6 +125,11 @@ bool RenderThemeChromiumSkia::supportsFocusRing(const RenderStyle* style) const
return false;
}
+bool RenderThemeChromiumSkia::supportsDataListUI(const AtomicString& type) const
+{
+ return RenderThemeChromiumCommon::supportsDataListUI(type);
+}
+
Color RenderThemeChromiumSkia::platformActiveSelectionBackgroundColor() const
{
return Color(0x1e, 0x90, 0xff);
@@ -227,7 +233,7 @@ void RenderThemeChromiumSkia::setRadioSize(RenderStyle* style) const
setCheckboxSize(style);
}
-void RenderThemeChromiumSkia::adjustButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+void RenderThemeChromiumSkia::adjustButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
{
if (style->appearance() == PushButtonPart) {
// Ignore line-height.
@@ -240,7 +246,7 @@ bool RenderThemeChromiumSkia::paintTextArea(RenderObject* o, const PaintInfo& i,
return paintTextField(o, i, r);
}
-void RenderThemeChromiumSkia::adjustSearchFieldStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+void RenderThemeChromiumSkia::adjustSearchFieldStyle(StyleResolver*, RenderStyle* style, Element*) const
{
// Ignore line-height.
style->setLineHeight(RenderStyle::initialLineHeight());
@@ -251,7 +257,7 @@ bool RenderThemeChromiumSkia::paintSearchField(RenderObject* o, const PaintInfo&
return paintTextField(o, i, r);
}
-void RenderThemeChromiumSkia::adjustSearchFieldCancelButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+void RenderThemeChromiumSkia::adjustSearchFieldCancelButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
{
// Scale the button size based on the font size
float fontScale = style->fontSize() / defaultControlFontPixelSize;
@@ -260,16 +266,16 @@ void RenderThemeChromiumSkia::adjustSearchFieldCancelButtonStyle(CSSStyleSelecto
style->setHeight(Length(cancelButtonSize, Fixed));
}
-LayoutRect RenderThemeChromiumSkia::convertToPaintingRect(RenderObject* inputRenderer, const RenderObject* partRenderer, LayoutRect partRect, const IntRect& localOffset) const
+IntRect RenderThemeChromiumSkia::convertToPaintingRect(RenderObject* inputRenderer, const RenderObject* partRenderer, LayoutRect partRect, const IntRect& localOffset) const
{
// Compute an offset between the part renderer and the input renderer.
- LayoutSize offsetFromInputRenderer = -(partRenderer->offsetFromAncestorContainer(inputRenderer));
+ LayoutSize offsetFromInputRenderer = -partRenderer->offsetFromAncestorContainer(inputRenderer);
// Move the rect into partRenderer's coords.
partRect.move(offsetFromInputRenderer);
// Account for the local drawing offset.
partRect.move(localOffset.x(), localOffset.y());
- return partRect;
+ return pixelSnappedIntRect(partRect);
}
bool RenderThemeChromiumSkia::paintSearchFieldCancelButton(RenderObject* cancelButtonObject, const PaintInfo& paintInfo, const IntRect& r)
@@ -289,7 +295,7 @@ bool RenderThemeChromiumSkia::paintSearchFieldCancelButton(RenderObject* cancelB
LayoutRect cancelButtonRect(cancelButtonObject->offsetFromAncestorContainer(inputRenderBox).width(),
inputContentBox.y() + (inputContentBox.height() - cancelButtonSize + 1) / 2,
cancelButtonSize, cancelButtonSize);
- LayoutRect paintingRect = convertToPaintingRect(inputRenderBox, cancelButtonObject, cancelButtonRect, r);
+ IntRect paintingRect = convertToPaintingRect(inputRenderBox, cancelButtonObject, cancelButtonRect, r);
static Image* cancelImage = Image::loadPlatformResource("searchCancel").leakRef();
static Image* cancelPressedImage = Image::loadPlatformResource("searchCancelPressed").leakRef();
@@ -298,14 +304,14 @@ bool RenderThemeChromiumSkia::paintSearchFieldCancelButton(RenderObject* cancelB
return false;
}
-void RenderThemeChromiumSkia::adjustSearchFieldDecorationStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+void RenderThemeChromiumSkia::adjustSearchFieldDecorationStyle(StyleResolver*, RenderStyle* style, Element*) const
{
IntSize emptySize(1, 11);
style->setWidth(Length(emptySize.width(), Fixed));
style->setHeight(Length(emptySize.height(), Fixed));
}
-void RenderThemeChromiumSkia::adjustSearchFieldResultsDecorationStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+void RenderThemeChromiumSkia::adjustSearchFieldResultsDecorationStyle(StyleResolver*, RenderStyle* style, Element*) const
{
// Scale the decoration size based on the font size
float fontScale = style->fontSize() / defaultControlFontPixelSize;
@@ -332,14 +338,14 @@ bool RenderThemeChromiumSkia::paintSearchFieldResultsDecoration(RenderObject* ma
LayoutRect magnifierRect(magnifierObject->offsetFromAncestorContainer(inputRenderBox).width(),
inputContentBox.y() + (inputContentBox.height() - magnifierSize + 1) / 2,
magnifierSize, magnifierSize);
- LayoutRect paintingRect = convertToPaintingRect(inputRenderBox, magnifierObject, magnifierRect, r);
+ IntRect paintingRect = convertToPaintingRect(inputRenderBox, magnifierObject, magnifierRect, r);
static Image* magnifierImage = Image::loadPlatformResource("searchMagnifier").leakRef();
paintInfo.context->drawImage(magnifierImage, magnifierObject->style()->colorSpace(), paintingRect);
return false;
}
-void RenderThemeChromiumSkia::adjustSearchFieldResultsButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+void RenderThemeChromiumSkia::adjustSearchFieldResultsButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
{
// Scale the button size based on the font size
float fontScale = style->fontSize() / defaultControlFontPixelSize;
@@ -365,7 +371,7 @@ bool RenderThemeChromiumSkia::paintSearchFieldResultsButton(RenderObject* magnif
LayoutRect magnifierRect(magnifierObject->offsetFromAncestorContainer(inputRenderBox).width(),
inputContentBox.y() + (inputContentBox.height() - magnifierHeight + 1) / 2,
magnifierWidth, magnifierHeight);
- LayoutRect paintingRect = convertToPaintingRect(inputRenderBox, magnifierObject, magnifierRect, r);
+ IntRect paintingRect = convertToPaintingRect(inputRenderBox, magnifierObject, magnifierRect, r);
static Image* magnifierImage = Image::loadPlatformResource("searchMagnifierResults").leakRef();
paintInfo.context->drawImage(magnifierImage, magnifierObject->style()->colorSpace(), paintingRect);
@@ -465,15 +471,15 @@ bool RenderThemeChromiumSkia::paintMediaMuteButton(RenderObject* object, const P
#endif
}
-void RenderThemeChromiumSkia::adjustMenuListStyle(CSSStyleSelector* selector, RenderStyle* style, WebCore::Element* e) const
+void RenderThemeChromiumSkia::adjustMenuListStyle(StyleResolver*, RenderStyle* style, WebCore::Element*) const
{
// Height is locked to auto on all browsers.
style->setLineHeight(RenderStyle::initialLineHeight());
}
-void RenderThemeChromiumSkia::adjustMenuListButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+void RenderThemeChromiumSkia::adjustMenuListButtonStyle(StyleResolver* styleResolver, RenderStyle* style, Element* e) const
{
- adjustMenuListStyle(selector, style, e);
+ adjustMenuListStyle(styleResolver, style, e);
}
// Used to paint styled menulists (i.e. with a non-default border)
diff --git a/Source/WebCore/rendering/RenderThemeChromiumSkia.h b/Source/WebCore/rendering/RenderThemeChromiumSkia.h
index 05b48be3b..c5306c12f 100644
--- a/Source/WebCore/rendering/RenderThemeChromiumSkia.h
+++ b/Source/WebCore/rendering/RenderThemeChromiumSkia.h
@@ -29,6 +29,7 @@
#define RenderThemeChromiumSkia_h
#include "RenderTheme.h"
+#include "RenderThemeChromiumCommon.h"
namespace WebCore {
@@ -51,6 +52,8 @@ class RenderThemeChromiumSkia : public RenderTheme {
// A method asking if the theme is able to draw the focus ring.
virtual bool supportsFocusRing(const RenderStyle*) const;
+ virtual bool supportsDataListUI(const AtomicString& type) const OVERRIDE;
+
// The platform selection color.
virtual Color platformActiveSelectionBackgroundColor() const;
virtual Color platformInactiveSelectionBackgroundColor() const;
@@ -70,22 +73,22 @@ class RenderThemeChromiumSkia : public RenderTheme {
virtual void setRadioSize(RenderStyle*) const;
- virtual void adjustButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintTextArea(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustSearchFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustSearchFieldStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintSearchField(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustSearchFieldCancelButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustSearchFieldCancelButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintSearchFieldCancelButton(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustSearchFieldDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustSearchFieldDecorationStyle(StyleResolver*, RenderStyle*, Element*) const;
- virtual void adjustSearchFieldResultsDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustSearchFieldResultsDecorationStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintSearchFieldResultsDecoration(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustSearchFieldResultsButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustSearchFieldResultsButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintSearchFieldResultsButton(RenderObject*, const PaintInfo&, const IntRect&);
virtual bool paintMediaControlsBackground(RenderObject*, const PaintInfo&, const IntRect&);
@@ -106,8 +109,8 @@ class RenderThemeChromiumSkia : public RenderTheme {
// In short, we either go down the MenuList code path or the MenuListButton
// codepath. We never go down both. And in both cases, they render the
// entire menulist.
- virtual void adjustMenuListStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
- virtual void adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustMenuListStyle(StyleResolver*, RenderStyle*, Element*) const;
+ virtual void adjustMenuListButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintMenuListButton(RenderObject*, const PaintInfo&, const IntRect&);
#if ENABLE(PROGRESS_TAG)
@@ -157,7 +160,7 @@ private:
int menuListInternalPadding(RenderStyle*, int paddingType) const;
bool paintMediaButtonInternal(GraphicsContext*, const IntRect&, Image*);
- LayoutRect convertToPaintingRect(RenderObject* inputRenderer, const RenderObject* partRenderer, LayoutRect partRect, const IntRect& localOffset) const;
+ IntRect convertToPaintingRect(RenderObject* inputRenderer, const RenderObject* partRenderer, LayoutRect partRect, const IntRect& localOffset) const;
};
} // namespace WebCore
diff --git a/Source/WebCore/rendering/RenderThemeChromiumWin.cpp b/Source/WebCore/rendering/RenderThemeChromiumWin.cpp
index 4224554ea..444212fd0 100644
--- a/Source/WebCore/rendering/RenderThemeChromiumWin.cpp
+++ b/Source/WebCore/rendering/RenderThemeChromiumWin.cpp
@@ -30,7 +30,6 @@
#include <vssym32.h>
#include "CSSValueKeywords.h"
-#include "CurrentTime.h"
#include "FontSelector.h"
#include "FontUtilsChromiumWin.h"
#include "GraphicsContext.h"
@@ -46,6 +45,8 @@
#include "ScrollbarTheme.h"
#include "SystemInfo.h"
#include "TransparencyWin.h"
+#include <wtf/CurrentTime.h>
+
// FIXME: This dependency should eventually be removed.
#include <skia/ext/skia_utils_win.h>
@@ -101,18 +102,11 @@ public:
private:
- static bool canvasHasMultipleLayers(const SkCanvas* canvas)
- {
- SkCanvas::LayerIter iter(const_cast<SkCanvas*>(canvas), false);
- iter.next(); // There is always at least one layer.
- return !iter.done(); // There is > 1 layer if the the iterator can stil advance.
- }
-
static TransparencyWin::LayerMode getLayerMode(GraphicsContext* context, TransparencyWin::TransformMode transformMode)
{
if (context->platformContext()->isDrawingToImageBuffer()) // Might have transparent background.
return TransparencyWin::WhiteLayer;
- if (canvasHasMultipleLayers(context->platformContext()->canvas())) // Needs antialiasing help.
+ if (context->platformContext()->canvas()->isDrawingToLayer()) // Needs antialiasing help.
return TransparencyWin::OpaqueCompositeLayer;
// Nothing interesting.
return transformMode == TransparencyWin::KeepTransform ? TransparencyWin::NoLayer : TransparencyWin::OpaqueCompositeLayer;
@@ -143,7 +137,7 @@ bool ThemePainter::s_hasInstance = false;
static void getNonClientMetrics(NONCLIENTMETRICS* metrics)
{
static UINT size = (windowsVersion() >= WindowsVista) ?
- (sizeof NONCLIENTMETRICS) : NONCLIENTMETRICS_SIZE_PRE_VISTA;
+ sizeof(NONCLIENTMETRICS) : NONCLIENTMETRICS_SIZE_PRE_VISTA;
metrics->cbSize = size;
bool success = !!SystemParametersInfo(SPI_GETNONCLIENTMETRICS, size, metrics, 0);
ASSERT(success);
@@ -712,7 +706,7 @@ bool RenderThemeChromiumWin::paintTextFieldInternal(RenderObject* o,
return false;
}
-void RenderThemeChromiumWin::adjustInnerSpinButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+void RenderThemeChromiumWin::adjustInnerSpinButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
{
int width = ScrollbarTheme::theme()->scrollbarThickness();
style->setWidth(Length(width, Fixed));
@@ -766,7 +760,7 @@ double RenderThemeChromiumWin::animationDurationForProgressBar(RenderProgress* r
return progressAnimationFrameRate;
}
-void RenderThemeChromiumWin::adjustProgressBarStyle(CSSStyleSelector*, RenderStyle*, Element*) const
+void RenderThemeChromiumWin::adjustProgressBarStyle(StyleResolver*, RenderStyle*, Element*) const
{
}
diff --git a/Source/WebCore/rendering/RenderThemeChromiumWin.h b/Source/WebCore/rendering/RenderThemeChromiumWin.h
index c47a67910..7856d039f 100644
--- a/Source/WebCore/rendering/RenderThemeChromiumWin.h
+++ b/Source/WebCore/rendering/RenderThemeChromiumWin.h
@@ -86,13 +86,13 @@ namespace WebCore {
// See comment in RenderThemeChromiumSkia::setDefaultFontSize() regarding ugliness of this hack.
static void setDefaultFontSize(int);
- virtual void adjustInnerSpinButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustInnerSpinButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintInnerSpinButton(RenderObject*, const PaintInfo&, const IntRect&);
#if ENABLE(PROGRESS_TAG)
virtual double animationRepeatIntervalForProgressBar(RenderProgress*) const;
virtual double animationDurationForProgressBar(RenderProgress*) const;
- virtual void adjustProgressBarStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustProgressBarStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintProgressBar(RenderObject*, const PaintInfo&, const IntRect&);
#endif
diff --git a/Source/WebCore/rendering/RenderThemeMac.h b/Source/WebCore/rendering/RenderThemeMac.h
index f8a5657ae..ebbb2352c 100644
--- a/Source/WebCore/rendering/RenderThemeMac.h
+++ b/Source/WebCore/rendering/RenderThemeMac.h
@@ -45,7 +45,7 @@ public:
// A general method asking if any control tinting is supported at all.
virtual bool supportsControlTints() const { return true; }
- virtual void adjustRepaintRect(const RenderObject*, LayoutRect&);
+ virtual void adjustRepaintRect(const RenderObject*, IntRect&) OVERRIDE;
virtual bool isControlStyled(const RenderStyle*, const BorderData&,
const FillLayer&, const Color& backgroundColor) const;
@@ -74,12 +74,12 @@ public:
virtual int popupInternalPaddingTop(RenderStyle*) const;
virtual int popupInternalPaddingBottom(RenderStyle*) const;
- virtual bool paintCapsLockIndicator(RenderObject*, const PaintInfo&, const LayoutRect&);
+ virtual bool paintCapsLockIndicator(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
virtual bool popsMenuByArrowKeys() const OVERRIDE { return true; }
#if ENABLE(METER_TAG)
- virtual LayoutSize meterSizeForBounds(const RenderMeter*, const LayoutRect&) const;
+ virtual IntSize meterSizeForBounds(const RenderMeter*, const IntRect&) const OVERRIDE;
virtual bool paintMeter(RenderObject*, const PaintInfo&, const IntRect&);
virtual bool supportsMeter(ControlPart) const;
#endif
@@ -103,41 +103,41 @@ protected:
virtual bool supportsSelectionForegroundColors() const { return false; }
virtual bool paintTextField(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustTextFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustTextFieldStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintTextArea(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustTextAreaStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustTextAreaStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintMenuList(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustMenuListStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustMenuListStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintMenuListButton(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustMenuListButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
#if ENABLE(PROGRESS_TAG)
- virtual void adjustProgressBarStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustProgressBarStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintProgressBar(RenderObject*, const PaintInfo&, const IntRect&);
#endif
virtual bool paintSliderTrack(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustSliderTrackStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustSliderTrackStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintSliderThumb(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustSliderThumbStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustSliderThumbStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintSearchField(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustSearchFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustSearchFieldStyle(StyleResolver*, RenderStyle*, Element*) const;
- virtual void adjustSearchFieldCancelButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustSearchFieldCancelButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintSearchFieldCancelButton(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustSearchFieldDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustSearchFieldDecorationStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintSearchFieldDecoration(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustSearchFieldResultsDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustSearchFieldResultsDecorationStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintSearchFieldResultsDecoration(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustSearchFieldResultsButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustSearchFieldResultsButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintSearchFieldResultsButton(RenderObject*, const PaintInfo&, const IntRect&);
#if ENABLE(VIDEO)
@@ -171,26 +171,26 @@ protected:
virtual bool usesMediaControlStatusDisplay();
virtual bool usesMediaControlVolumeSlider() const;
virtual void adjustMediaSliderThumbSize(RenderStyle*) const;
- virtual LayoutPoint volumeSliderOffsetFromMuteButton(RenderBox*, const LayoutSize&) const;
+ virtual IntPoint volumeSliderOffsetFromMuteButton(RenderBox*, const IntSize&) const OVERRIDE;
#endif
virtual bool shouldShowPlaceholderWhenFocused() const;
private:
- virtual String fileListNameForWidth(const Vector<String>& filenames, const Font&, int width, bool multipleFilesAllowed) const;
+ virtual String fileListNameForWidth(const FileList*, const Font&, int width, bool multipleFilesAllowed) const OVERRIDE;
- LayoutRect inflateRect(const LayoutRect&, const IntSize&, const int* margins, float zoomLevel = 1.0f) const;
+ IntRect inflateRect(const IntRect&, const IntSize&, const int* margins, float zoomLevel = 1.0f) const;
FloatRect convertToPaintingRect(const RenderObject* inputRenderer, const RenderObject* partRenderer, const FloatRect& inputRect, const IntRect& r) const;
// Get the control size based off the font. Used by some of the controls (like buttons).
NSControlSize controlSizeForFont(RenderStyle*) const;
NSControlSize controlSizeForSystemFont(RenderStyle*) const;
- void setControlSize(NSCell*, const IntSize* sizes, const LayoutSize& minSize, float zoomLevel = 1.0f);
+ void setControlSize(NSCell*, const IntSize* sizes, const IntSize& minSize, float zoomLevel = 1.0f);
void setSizeFromFont(RenderStyle*, const IntSize* sizes) const;
IntSize sizeForFont(RenderStyle*, const IntSize* sizes) const;
IntSize sizeForSystemFont(RenderStyle*, const IntSize* sizes) const;
- void setFontFromControlSize(CSSStyleSelector*, RenderStyle*, NSControlSize) const;
+ void setFontFromControlSize(StyleResolver*, RenderStyle*, NSControlSize) const;
void updateCheckedState(NSCell*, const RenderObject*);
void updateEnabledState(NSCell*, const RenderObject*);
@@ -201,7 +201,7 @@ private:
// Helpers for adjusting appearance and for painting
- void setPopupButtonCellState(const RenderObject*, const LayoutRect&);
+ void setPopupButtonCellState(const RenderObject*, const IntRect&);
const IntSize* popupButtonSizes() const;
const int* popupButtonMargins() const;
const int* popupButtonPadding(NSControlSize) const;
diff --git a/Source/WebCore/rendering/RenderThemeMac.mm b/Source/WebCore/rendering/RenderThemeMac.mm
index 0ae0196bc..801b235a9 100644
--- a/Source/WebCore/rendering/RenderThemeMac.mm
+++ b/Source/WebCore/rendering/RenderThemeMac.mm
@@ -22,10 +22,11 @@
#import "BitmapImage.h"
#import "ColorMac.h"
-#import "CSSStyleSelector.h"
+#import "CSSValueList.h"
#import "CSSValueKeywords.h"
#import "Document.h"
#import "Element.h"
+#import "FileList.h"
#import "FrameView.h"
#import "GraphicsContextCG.h"
#import "HTMLInputElement.h"
@@ -43,6 +44,7 @@
#import "RenderView.h"
#import "SharedBuffer.h"
#import "StringTruncator.h"
+#import "StyleResolver.h"
#import "TimeRanges.h"
#import "ThemeMac.h"
#import "WebCoreSystemInterface.h"
@@ -487,7 +489,7 @@ NSView* RenderThemeMac::documentViewFor(RenderObject* o) const
bool RenderThemeMac::isControlStyled(const RenderStyle* style, const BorderData& border,
const FillLayer& background, const Color& backgroundColor) const
{
- if (style->appearance() == TextFieldPart || style->appearance() == TextAreaPart || style->appearance() == ListboxPart)
+ if (style->appearance() == TextAreaPart || style->appearance() == ListboxPart)
return style->border() != border;
// FIXME: This is horrible, but there is not much else that can be done. Menu lists cannot draw properly when
@@ -500,7 +502,7 @@ bool RenderThemeMac::isControlStyled(const RenderStyle* style, const BorderData&
return RenderTheme::isControlStyled(style, border, background, backgroundColor);
}
-void RenderThemeMac::adjustRepaintRect(const RenderObject* o, LayoutRect& r)
+void RenderThemeMac::adjustRepaintRect(const RenderObject* o, IntRect& r)
{
ControlPart part = o->style()->appearance();
@@ -510,7 +512,6 @@ void RenderThemeMac::adjustRepaintRect(const RenderObject* o, LayoutRect& r)
case RadioPart:
case PushButtonPart:
case SquareButtonPart:
- case ListButtonPart:
case DefaultButtonPart:
case ButtonPart:
case InnerSpinButtonPart:
@@ -531,13 +532,13 @@ void RenderThemeMac::adjustRepaintRect(const RenderObject* o, LayoutRect& r)
}
}
-LayoutRect RenderThemeMac::inflateRect(const LayoutRect& r, const IntSize& size, const int* margins, float zoomLevel) const
+IntRect RenderThemeMac::inflateRect(const IntRect& r, const IntSize& size, const int* margins, float zoomLevel) const
{
// Only do the inflation if the available width/height are too small. Otherwise try to
// fit the glow/check space into the available box's width/height.
- LayoutUnit widthDelta = r.width() - (size.width() + margins[leftMargin] * zoomLevel + margins[rightMargin] * zoomLevel);
- LayoutUnit heightDelta = r.height() - (size.height() + margins[topMargin] * zoomLevel + margins[bottomMargin] * zoomLevel);
- LayoutRect result(r);
+ int widthDelta = r.width() - (size.width() + margins[leftMargin] * zoomLevel + margins[rightMargin] * zoomLevel);
+ int heightDelta = r.height() - (size.height() + margins[topMargin] * zoomLevel + margins[bottomMargin] * zoomLevel);
+ IntRect result(r);
if (widthDelta < 0) {
result.setX(result.x() - margins[leftMargin] * zoomLevel);
result.setWidth(result.width() - widthDelta);
@@ -558,7 +559,7 @@ FloatRect RenderThemeMac::convertToPaintingRect(const RenderObject* inputRendere
const RenderObject* renderer = partRenderer;
while (renderer && renderer != inputRenderer) {
RenderObject* containingRenderer = renderer->container();
- offsetFromInputRenderer -= renderer->offsetFromContainer(containingRenderer, LayoutPoint());
+ offsetFromInputRenderer -= roundedIntSize(renderer->offsetFromContainer(containingRenderer, LayoutPoint()));
renderer = containingRenderer;
}
// If the input renderer was not a container, something went wrong
@@ -639,14 +640,14 @@ NSControlSize RenderThemeMac::controlSizeForFont(RenderStyle* style) const
return NSMiniControlSize;
}
-void RenderThemeMac::setControlSize(NSCell* cell, const IntSize* sizes, const LayoutSize& minSize, float zoomLevel)
+void RenderThemeMac::setControlSize(NSCell* cell, const IntSize* sizes, const IntSize& minSize, float zoomLevel)
{
NSControlSize size;
- if (minSize.width() >= static_cast<LayoutUnit>(sizes[NSRegularControlSize].width() * zoomLevel) &&
- minSize.height() >= static_cast<LayoutUnit>(sizes[NSRegularControlSize].height() * zoomLevel))
+ if (minSize.width() >= static_cast<int>(sizes[NSRegularControlSize].width() * zoomLevel) &&
+ minSize.height() >= static_cast<int>(sizes[NSRegularControlSize].height() * zoomLevel))
size = NSRegularControlSize;
- else if (minSize.width() >= static_cast<LayoutUnit>(sizes[NSSmallControlSize].width() * zoomLevel) &&
- minSize.height() >= static_cast<LayoutUnit>(sizes[NSSmallControlSize].height() * zoomLevel))
+ else if (minSize.width() >= static_cast<int>(sizes[NSSmallControlSize].width() * zoomLevel) &&
+ minSize.height() >= static_cast<int>(sizes[NSSmallControlSize].height() * zoomLevel))
size = NSSmallControlSize;
else
size = NSMiniControlSize;
@@ -682,7 +683,7 @@ void RenderThemeMac::setSizeFromFont(RenderStyle* style, const IntSize* sizes) c
style->setHeight(Length(size.height(), Fixed));
}
-void RenderThemeMac::setFontFromControlSize(CSSStyleSelector*, RenderStyle* style, NSControlSize controlSize) const
+void RenderThemeMac::setFontFromControlSize(StyleResolver*, RenderStyle* style, NSControlSize controlSize) const
{
FontDescription fontDescription;
fontDescription.setIsAbsoluteSize(true);
@@ -725,11 +726,11 @@ bool RenderThemeMac::paintTextField(RenderObject* o, const PaintInfo& paintInfo,
return false;
}
-void RenderThemeMac::adjustTextFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const
+void RenderThemeMac::adjustTextFieldStyle(StyleResolver*, RenderStyle*, Element*) const
{
}
-bool RenderThemeMac::paintCapsLockIndicator(RenderObject*, const PaintInfo& paintInfo, const LayoutRect& r)
+bool RenderThemeMac::paintCapsLockIndicator(RenderObject*, const PaintInfo& paintInfo, const IntRect& r)
{
if (paintInfo.context->paintingDisabled())
return true;
@@ -747,7 +748,7 @@ bool RenderThemeMac::paintTextArea(RenderObject* o, const PaintInfo& paintInfo,
return false;
}
-void RenderThemeMac::adjustTextAreaStyle(CSSStyleSelector*, RenderStyle*, Element*) const
+void RenderThemeMac::adjustTextAreaStyle(StyleResolver*, RenderStyle*, Element*) const
{
}
@@ -792,7 +793,7 @@ bool RenderThemeMac::paintMenuList(RenderObject* o, const PaintInfo& paintInfo,
size.setWidth(r.width());
// Now inflate it to account for the shadow.
- LayoutRect inflatedRect = r;
+ IntRect inflatedRect = r;
if (r.width() >= minimumMenuListSize(o->style()))
inflatedRect = inflateRect(inflatedRect, size, popupButtonMargins(), zoomLevel);
@@ -817,16 +818,16 @@ bool RenderThemeMac::paintMenuList(RenderObject* o, const PaintInfo& paintInfo,
#if ENABLE(METER_TAG)
-LayoutSize RenderThemeMac::meterSizeForBounds(const RenderMeter* renderMeter, const LayoutRect& bounds) const
+IntSize RenderThemeMac::meterSizeForBounds(const RenderMeter* renderMeter, const IntRect& bounds) const
{
if (NoControlPart == renderMeter->style()->appearance())
return bounds.size();
NSLevelIndicatorCell* cell = levelIndicatorFor(renderMeter);
// Makes enough room for cell's intrinsic size.
- NSSize cellSize = [cell cellSizeForBounds:LayoutRect(LayoutPoint(), bounds.size())];
- return LayoutSize(bounds.width() < cellSize.width ? cellSize.width : bounds.width(),
- bounds.height() < cellSize.height ? cellSize.height : bounds.height());
+ NSSize cellSize = [cell cellSizeForBounds:IntRect(IntPoint(), bounds.size())];
+ return IntSize(bounds.width() < cellSize.width ? cellSize.width : bounds.width(),
+ bounds.height() < cellSize.height ? cellSize.height : bounds.height());
}
bool RenderThemeMac::paintMeter(RenderObject* renderObject, const PaintInfo& paintInfo, const IntRect& rect)
@@ -952,7 +953,7 @@ double RenderThemeMac::animationDurationForProgressBar(RenderProgress*) const
return progressAnimationNumFrames * progressAnimationFrameRate;
}
-void RenderThemeMac::adjustProgressBarStyle(CSSStyleSelector*, RenderStyle*, Element*) const
+void RenderThemeMac::adjustProgressBarStyle(StyleResolver*, RenderStyle*, Element*) const
{
}
@@ -1072,7 +1073,7 @@ void RenderThemeMac::paintMenuListButtonGradients(RenderObject* o, const PaintIn
GraphicsContextStateSaver stateSaver(*paintInfo.context);
- RoundedRect border = o->style()->getRoundedBorderFor(r);
+ RoundedRect border = o->style()->getRoundedBorderFor(r, o->view());
int radius = border.radii().topLeft().width();
CGColorSpaceRef cspace = deviceRGBColorSpaceRef();
@@ -1196,7 +1197,7 @@ static const IntSize* menuListButtonSizes()
return sizes;
}
-void RenderThemeMac::adjustMenuListStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+void RenderThemeMac::adjustMenuListStyle(StyleResolver* styleResolver, RenderStyle* style, Element* e) const
{
NSControlSize controlSize = controlSizeForFont(style);
@@ -1219,7 +1220,7 @@ void RenderThemeMac::adjustMenuListStyle(CSSStyleSelector* selector, RenderStyle
// Our font is locked to the appropriate system font size for the control. To clarify, we first use the CSS-specified font to figure out
// a reasonable control size, but once that control size is determined, we throw that font away and use the appropriate
// system font for the control size instead.
- setFontFromControlSize(selector, style, controlSize);
+ setFontFromControlSize(styleResolver, style, controlSize);
style->setBoxShadow(nullptr);
}
@@ -1263,7 +1264,7 @@ int RenderThemeMac::popupInternalPaddingBottom(RenderStyle* style) const
return 0;
}
-void RenderThemeMac::adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+void RenderThemeMac::adjustMenuListButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
{
float fontScale = style->fontSize() / baseFontSize;
@@ -1276,7 +1277,7 @@ void RenderThemeMac::adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle* s
style->setLineHeight(RenderStyle::initialLineHeight());
}
-void RenderThemeMac::setPopupButtonCellState(const RenderObject* o, const LayoutRect& r)
+void RenderThemeMac::setPopupButtonCellState(const RenderObject* o, const IntRect& r)
{
NSPopUpButtonCell* popupButton = this->popupButton();
@@ -1305,7 +1306,7 @@ int RenderThemeMac::minimumMenuListSize(RenderStyle* style) const
const int trackWidth = 5;
const int trackRadius = 2;
-void RenderThemeMac::adjustSliderTrackStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+void RenderThemeMac::adjustSliderTrackStyle(StyleResolver*, RenderStyle* style, Element*) const
{
style->setBoxShadow(nullptr);
}
@@ -1347,9 +1348,9 @@ bool RenderThemeMac::paintSliderTrack(RenderObject* o, const PaintInfo& paintInf
return false;
}
-void RenderThemeMac::adjustSliderThumbStyle(CSSStyleSelector* selector, RenderStyle* style, Element* element) const
+void RenderThemeMac::adjustSliderThumbStyle(StyleResolver* styleResolver, RenderStyle* style, Element* element) const
{
- RenderTheme::adjustSliderThumbStyle(selector, style, element);
+ RenderTheme::adjustSliderThumbStyle(styleResolver, style, element);
style->setBoxShadow(nullptr);
}
@@ -1478,7 +1479,7 @@ void RenderThemeMac::setSearchFieldSize(RenderStyle* style) const
setSizeFromFont(style, searchFieldSizes());
}
-void RenderThemeMac::adjustSearchFieldStyle(CSSStyleSelector* selector, RenderStyle* style, Element*) const
+void RenderThemeMac::adjustSearchFieldStyle(StyleResolver* styleResolver, RenderStyle* style, Element*) const
{
// Override border.
style->resetBorder();
@@ -1504,7 +1505,7 @@ void RenderThemeMac::adjustSearchFieldStyle(CSSStyleSelector* selector, RenderSt
style->setPaddingBottom(Length(padding, Fixed));
NSControlSize controlSize = controlSizeForFont(style);
- setFontFromControlSize(selector, style, controlSize);
+ setFontFromControlSize(styleResolver, style, controlSize);
style->setBoxShadow(nullptr);
}
@@ -1533,14 +1534,14 @@ bool RenderThemeMac::paintSearchFieldCancelButton(RenderObject* o, const PaintIn
float zoomLevel = o->style()->effectiveZoom();
- FloatRect localBounds = [search cancelButtonRectForBounds:NSRect(input->renderBox()->borderBoxRect())];
+ FloatRect localBounds = [search cancelButtonRectForBounds:NSRect(input->renderBox()->pixelSnappedBorderBoxRect())];
#if ENABLE(INPUT_SPEECH)
// Take care of cases where the cancel button was not aligned with the right border of the input element (for e.g.
// when speech input is enabled for the input element.
- LayoutRect absBoundingBox = input->renderer()->absoluteBoundingBoxRect();
- LayoutUnit absRight = absBoundingBox.x() + absBoundingBox.width() - input->renderBox()->paddingRight() - input->renderBox()->borderRight();
- LayoutUnit spaceToRightOfCancelButton = absRight - (r.x() + r.width());
+ IntRect absBoundingBox = input->renderer()->absoluteBoundingBoxRect();
+ int absRight = absBoundingBox.x() + absBoundingBox.width() - input->renderBox()->paddingRight() - input->renderBox()->borderRight();
+ int spaceToRightOfCancelButton = absRight - (r.x() + r.width());
localBounds.setX(localBounds.x() - spaceToRightOfCancelButton);
#endif
@@ -1566,7 +1567,7 @@ const IntSize* RenderThemeMac::cancelButtonSizes() const
return sizes;
}
-void RenderThemeMac::adjustSearchFieldCancelButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+void RenderThemeMac::adjustSearchFieldCancelButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
{
IntSize size = sizeForSystemFont(style, cancelButtonSizes());
style->setWidth(Length(size.width(), Fixed));
@@ -1581,7 +1582,7 @@ const IntSize* RenderThemeMac::resultsButtonSizes() const
}
const int emptyResultsOffset = 9;
-void RenderThemeMac::adjustSearchFieldDecorationStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+void RenderThemeMac::adjustSearchFieldDecorationStyle(StyleResolver*, RenderStyle* style, Element*) const
{
IntSize size = sizeForSystemFont(style, resultsButtonSizes());
style->setWidth(Length(size.width() - emptyResultsOffset, Fixed));
@@ -1594,7 +1595,7 @@ bool RenderThemeMac::paintSearchFieldDecoration(RenderObject*, const PaintInfo&,
return false;
}
-void RenderThemeMac::adjustSearchFieldResultsDecorationStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+void RenderThemeMac::adjustSearchFieldResultsDecorationStyle(StyleResolver*, RenderStyle* style, Element*) const
{
IntSize size = sizeForSystemFont(style, resultsButtonSizes());
style->setWidth(Length(size.width(), Fixed));
@@ -1618,7 +1619,7 @@ bool RenderThemeMac::paintSearchFieldResultsDecoration(RenderObject* o, const Pa
updateActiveState([search searchButtonCell], o);
- FloatRect localBounds = [search searchButtonRectForBounds:NSRect(input->renderBox()->borderBoxRect())];
+ FloatRect localBounds = [search searchButtonRectForBounds:NSRect(input->renderBox()->pixelSnappedBorderBoxRect())];
localBounds = convertToPaintingRect(input->renderer(), o, localBounds, r);
[[search searchButtonCell] drawWithFrame:localBounds inView:documentViewFor(o)];
@@ -1627,7 +1628,7 @@ bool RenderThemeMac::paintSearchFieldResultsDecoration(RenderObject* o, const Pa
}
const int resultsArrowWidth = 5;
-void RenderThemeMac::adjustSearchFieldResultsButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+void RenderThemeMac::adjustSearchFieldResultsButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
{
IntSize size = sizeForSystemFont(style, resultsButtonSizes());
style->setWidth(Length(size.width() + resultsArrowWidth, Fixed));
@@ -1654,7 +1655,7 @@ bool RenderThemeMac::paintSearchFieldResultsButton(RenderObject* o, const PaintI
GraphicsContextStateSaver stateSaver(*paintInfo.context);
float zoomLevel = o->style()->effectiveZoom();
- FloatRect localBounds = [search searchButtonRectForBounds:NSRect(input->renderBox()->borderBoxRect())];
+ FloatRect localBounds = [search searchButtonRectForBounds:NSRect(input->renderBox()->pixelSnappedBorderBoxRect())];
localBounds = convertToPaintingRect(input->renderer(), o, localBounds, r);
IntRect unzoomedRect(localBounds);
@@ -1789,8 +1790,10 @@ bool RenderThemeMac::paintMediaFullscreenButton(RenderObject* o, const PaintInfo
if (!node)
return false;
- LocalCurrentGraphicsContext localContext(paintInfo.context);
- wkDrawMediaUIPart(MediaFullscreenButton, mediaControllerTheme(), localContext.cgContext(), r, getMediaUIPartStateFlags(node));
+ if (MediaControlFullscreenButtonElement* btn = static_cast<MediaControlFullscreenButtonElement*>(o->node())) {
+ LocalCurrentGraphicsContext localContext(paintInfo.context);
+ wkDrawMediaUIPart(btn->displayType(), mediaControllerTheme(), localContext.cgContext(), r, getMediaUIPartStateFlags(node));
+ }
return false;
}
@@ -2056,7 +2059,7 @@ bool RenderThemeMac::usesMediaControlVolumeSlider() const
return mediaControllerTheme() == MediaControllerThemeQuickTime;
}
-LayoutPoint RenderThemeMac::volumeSliderOffsetFromMuteButton(RenderBox* muteButtonBox, const LayoutSize& size) const
+IntPoint RenderThemeMac::volumeSliderOffsetFromMuteButton(RenderBox* muteButtonBox, const IntSize& size) const
{
return RenderMediaControls::volumeSliderOffsetFromMuteButton(muteButtonBox, size);
}
@@ -2137,28 +2140,23 @@ NSTextFieldCell* RenderThemeMac::textField() const
[m_textField.get() setBezeled:YES];
[m_textField.get() setEditable:YES];
[m_textField.get() setFocusRingType:NSFocusRingTypeExterior];
-
- // Setting a clear background on the cell is necessary for CSS-styled backgrounds
- // to show through. Ideally, there would be a better way to do this.
- [m_textField.get() setDrawsBackground:YES];
- [m_textField.get() setBackgroundColor:[NSColor clearColor]];
}
return m_textField.get();
}
-String RenderThemeMac::fileListNameForWidth(const Vector<String>& filenames, const Font& font, int width, bool multipleFilesAllowed) const
+String RenderThemeMac::fileListNameForWidth(const FileList* fileList, const Font& font, int width, bool multipleFilesAllowed) const
{
if (width <= 0)
return String();
String strToTruncate;
- if (filenames.isEmpty())
+ if (fileList->isEmpty())
strToTruncate = fileListDefaultLabel(multipleFilesAllowed);
- else if (filenames.size() == 1)
- strToTruncate = [[NSFileManager defaultManager] displayNameAtPath:(filenames[0])];
+ else if (fileList->length() == 1)
+ strToTruncate = [[NSFileManager defaultManager] displayNameAtPath:(fileList->item(0)->path())];
else
- return StringTruncator::rightTruncate(multipleFileUploadText(filenames.size()), width, font, StringTruncator::EnableRoundingHacks);
+ return StringTruncator::rightTruncate(multipleFileUploadText(fileList->length()), width, font, StringTruncator::EnableRoundingHacks);
return StringTruncator::centerTruncate(strToTruncate, width, font, StringTruncator::EnableRoundingHacks);
}
diff --git a/Source/WebCore/rendering/RenderThemeSafari.cpp b/Source/WebCore/rendering/RenderThemeSafari.cpp
index 771f19426..00a5d7e66 100644
--- a/Source/WebCore/rendering/RenderThemeSafari.cpp
+++ b/Source/WebCore/rendering/RenderThemeSafari.cpp
@@ -40,10 +40,10 @@
#include "RenderMediaControls.h"
#include "RenderSlider.h"
#include "RenderView.h"
-#include "RetainPtr.h"
#include "SoftLinking.h"
-#include "cssstyleselector.h"
+#include "StyleResolver.h"
#include <CoreGraphics/CoreGraphics.h>
+#include <wtf/RetainPtr.h>
using std::min;
@@ -383,7 +383,7 @@ void RenderThemeSafari::setSizeFromFont(RenderStyle* style, const IntSize* sizes
style->setHeight(Length(size.height(), Fixed));
}
-void RenderThemeSafari::setFontFromControlSize(CSSStyleSelector* selector, RenderStyle* style, NSControlSize controlSize) const
+void RenderThemeSafari::setFontFromControlSize(StyleResolver* styleResolver, RenderStyle* style, NSControlSize controlSize) const
{
FontDescription fontDescription;
fontDescription.setIsAbsoluteSize(true);
@@ -398,7 +398,7 @@ void RenderThemeSafari::setFontFromControlSize(CSSStyleSelector* selector, Rende
style->setLineHeight(RenderStyle::initialLineHeight());
if (style->setFontDescription(fontDescription))
- style->font().update(selector->fontSelector());
+ style->font().update(styleResolver->fontSelector());
}
NSControlSize RenderThemeSafari::controlSizeForSystemFont(RenderStyle* style) const
@@ -503,7 +503,7 @@ void RenderThemeSafari::setButtonPaddingFromControlSize(RenderStyle* style, NSCo
style->setPaddingBottom(Length(0, Fixed));
}
-void RenderThemeSafari::adjustButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+void RenderThemeSafari::adjustButtonStyle(StyleResolver* styleResolver, RenderStyle* style, Element* e) const
{
// There are three appearance constants for buttons.
// (1) Push-button is the constant for the default Aqua system button. Push buttons will not scale vertically and will not allow
@@ -536,7 +536,7 @@ void RenderThemeSafari::adjustButtonStyle(CSSStyleSelector* selector, RenderStyl
// Our font is locked to the appropriate system font size for the control. To clarify, we first use the CSS-specified font to figure out
// a reasonable control size, but once that control size is determined, we throw that font away and use the appropriate
// system font for the control size instead.
- setFontFromControlSize(selector, style, controlSize);
+ setFontFromControlSize(styleResolver, style, controlSize);
} else {
// Set a min-height so that we can't get smaller than the mini button.
style->setMinHeight(Length(15, Fixed));
@@ -615,7 +615,7 @@ bool RenderThemeSafari::paintTextField(RenderObject* o, const PaintInfo& paintIn
return false;
}
-void RenderThemeSafari::adjustTextFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const
+void RenderThemeSafari::adjustTextFieldStyle(StyleResolver*, RenderStyle*, Element*) const
{
}
@@ -643,7 +643,7 @@ bool RenderThemeSafari::paintTextArea(RenderObject* o, const PaintInfo& paintInf
return false;
}
-void RenderThemeSafari::adjustTextAreaStyle(CSSStyleSelector*, RenderStyle*, Element*) const
+void RenderThemeSafari::adjustTextAreaStyle(StyleResolver*, RenderStyle*, Element*) const
{
}
@@ -859,7 +859,7 @@ bool RenderThemeSafari::paintMenuListButton(RenderObject* o, const PaintInfo& pa
return false;
}
-void RenderThemeSafari::adjustMenuListStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+void RenderThemeSafari::adjustMenuListStyle(StyleResolver* styleResolver, RenderStyle* style, Element* e) const
{
NSControlSize controlSize = controlSizeForFont(style);
@@ -882,7 +882,7 @@ void RenderThemeSafari::adjustMenuListStyle(CSSStyleSelector* selector, RenderSt
// Our font is locked to the appropriate system font size for the control. To clarify, we first use the CSS-specified font to figure out
// a reasonable control size, but once that control size is determined, we throw that font away and use the appropriate
// system font for the control size instead.
- setFontFromControlSize(selector, style, controlSize);
+ setFontFromControlSize(styleResolver, style, controlSize);
}
int RenderThemeSafari::popupInternalPaddingLeft(RenderStyle* style) const
@@ -924,7 +924,7 @@ int RenderThemeSafari::popupInternalPaddingBottom(RenderStyle* style) const
return 0;
}
-void RenderThemeSafari::adjustMenuListButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+void RenderThemeSafari::adjustMenuListButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
{
float fontScale = style->fontSize() / baseFontSize;
@@ -988,9 +988,9 @@ bool RenderThemeSafari::paintSliderTrack(RenderObject* o, const PaintInfo& paint
return false;
}
-void RenderThemeSafari::adjustSliderThumbStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+void RenderThemeSafari::adjustSliderThumbStyle(StyleResolver* styleResolver, RenderStyle* style, Element* e) const
{
- RenderTheme::adjustSliderThumbStyle(selector, style, e);
+ RenderTheme::adjustSliderThumbStyle(styleResolver, style, e);
style->setBoxShadow(nullptr);
}
@@ -1042,7 +1042,7 @@ void RenderThemeSafari::setSearchFieldSize(RenderStyle* style) const
setSizeFromFont(style, searchFieldSizes());
}
-void RenderThemeSafari::adjustSearchFieldStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+void RenderThemeSafari::adjustSearchFieldStyle(StyleResolver* styleResolver, RenderStyle* style, Element* e) const
{
// Override border.
style->resetBorder();
@@ -1068,7 +1068,7 @@ void RenderThemeSafari::adjustSearchFieldStyle(CSSStyleSelector* selector, Rende
style->setPaddingBottom(Length(padding, Fixed));
NSControlSize controlSize = controlSizeForFont(style);
- setFontFromControlSize(selector, style, controlSize);
+ setFontFromControlSize(styleResolver, style, controlSize);
}
bool RenderThemeSafari::paintSearchFieldCancelButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect&)
@@ -1092,7 +1092,7 @@ const IntSize* RenderThemeSafari::cancelButtonSizes() const
return sizes;
}
-void RenderThemeSafari::adjustSearchFieldCancelButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+void RenderThemeSafari::adjustSearchFieldCancelButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
{
IntSize size = sizeForSystemFont(style, cancelButtonSizes());
style->setWidth(Length(size.width(), Fixed));
@@ -1106,7 +1106,7 @@ const IntSize* RenderThemeSafari::resultsButtonSizes() const
}
const int emptyResultsOffset = 9;
-void RenderThemeSafari::adjustSearchFieldDecorationStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+void RenderThemeSafari::adjustSearchFieldDecorationStyle(StyleResolver*, RenderStyle* style, Element*) const
{
IntSize size = sizeForSystemFont(style, resultsButtonSizes());
style->setWidth(Length(size.width() - emptyResultsOffset, Fixed));
@@ -1118,7 +1118,7 @@ bool RenderThemeSafari::paintSearchFieldDecoration(RenderObject*, const PaintInf
return false;
}
-void RenderThemeSafari::adjustSearchFieldResultsDecorationStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+void RenderThemeSafari::adjustSearchFieldResultsDecorationStyle(StyleResolver*, RenderStyle* style, Element*) const
{
IntSize size = sizeForSystemFont(style, resultsButtonSizes());
style->setWidth(Length(size.width(), Fixed));
@@ -1141,7 +1141,7 @@ bool RenderThemeSafari::paintSearchFieldResultsDecoration(RenderObject* o, const
}
const int resultsArrowWidth = 5;
-void RenderThemeSafari::adjustSearchFieldResultsButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+void RenderThemeSafari::adjustSearchFieldResultsButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
{
IntSize size = sizeForSystemFont(style, resultsButtonSizes());
style->setWidth(Length(size.width() + resultsArrowWidth, Fixed));
@@ -1165,7 +1165,7 @@ bool RenderThemeSafari::paintSearchFieldResultsButton(RenderObject* o, const Pai
#if ENABLE(VIDEO)
bool RenderThemeSafari::paintMediaFullscreenButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
{
- return RenderMediaControls::paintMediaControlsPart(MediaFullscreenButton, o, paintInfo, r);
+ return RenderMediaControls::paintMediaControlsPart(MediaEnterFullscreenButton, o, paintInfo, r);
}
bool RenderThemeSafari::paintMediaMuteButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
diff --git a/Source/WebCore/rendering/RenderThemeSafari.h b/Source/WebCore/rendering/RenderThemeSafari.h
index 85ddb4d50..05b1fb5ea 100644
--- a/Source/WebCore/rendering/RenderThemeSafari.h
+++ b/Source/WebCore/rendering/RenderThemeSafari.h
@@ -77,7 +77,7 @@ public:
virtual int minimumMenuListSize(RenderStyle*) const;
virtual void adjustSliderThumbSize(RenderStyle*) const;
- virtual void adjustSliderThumbStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustSliderThumbStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual int popupInternalPaddingLeft(RenderStyle*) const;
virtual int popupInternalPaddingRight(RenderStyle*) const;
@@ -92,38 +92,38 @@ protected:
virtual bool paintRadio(RenderObject*, const PaintInfo&, const IntRect&);
virtual void setRadioSize(RenderStyle*) const;
- virtual void adjustButtonStyle(CSSStyleSelector*, RenderStyle*, WebCore::Element*) const;
+ virtual void adjustButtonStyle(StyleResolver*, RenderStyle*, WebCore::Element*) const;
virtual bool paintButton(RenderObject*, const PaintInfo&, const IntRect&);
virtual void setButtonSize(RenderStyle*) const;
virtual bool paintTextField(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustTextFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustTextFieldStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintTextArea(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustTextAreaStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustTextAreaStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintMenuList(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustMenuListStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustMenuListStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintMenuListButton(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustMenuListButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintSliderTrack(RenderObject*, const PaintInfo&, const IntRect&);
virtual bool paintSliderThumb(RenderObject*, const PaintInfo&, const IntRect&);
virtual bool paintSearchField(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustSearchFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustSearchFieldStyle(StyleResolver*, RenderStyle*, Element*) const;
- virtual void adjustSearchFieldCancelButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustSearchFieldCancelButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintSearchFieldCancelButton(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustSearchFieldDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustSearchFieldDecorationStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintSearchFieldDecoration(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustSearchFieldResultsDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustSearchFieldResultsDecorationStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintSearchFieldResultsDecoration(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustSearchFieldResultsButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustSearchFieldResultsButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintSearchFieldResultsButton(RenderObject*, const PaintInfo&, const IntRect&);
virtual bool paintCapsLockIndicator(RenderObject*, const PaintInfo&, const IntRect&);
@@ -154,7 +154,7 @@ private:
void setSizeFromFont(RenderStyle*, const IntSize* sizes) const;
IntSize sizeForFont(RenderStyle*, const IntSize* sizes) const;
IntSize sizeForSystemFont(RenderStyle*, const IntSize* sizes) const;
- void setFontFromControlSize(CSSStyleSelector*, RenderStyle*, NSControlSize) const;
+ void setFontFromControlSize(StyleResolver*, RenderStyle*, NSControlSize) const;
// Helpers for adjusting appearance and for painting
const IntSize* checkboxSizes() const;
diff --git a/Source/WebCore/rendering/RenderThemeWin.cpp b/Source/WebCore/rendering/RenderThemeWin.cpp
index 16795c3b7..e58bad9e1 100644
--- a/Source/WebCore/rendering/RenderThemeWin.cpp
+++ b/Source/WebCore/rendering/RenderThemeWin.cpp
@@ -687,7 +687,7 @@ bool RenderThemeWin::paintButton(RenderObject* o, const PaintInfo& i, const IntR
return false;
}
-void RenderThemeWin::adjustInnerSpinButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+void RenderThemeWin::adjustInnerSpinButtonStyle(StyleResolver* styleResolver, RenderStyle* style, Element* e) const
{
int width = ::GetSystemMetrics(SM_CXVSCROLL);
if (width <= 0)
@@ -754,13 +754,13 @@ bool RenderThemeWin::paintMenuList(RenderObject* o, const PaintInfo& i, const In
return paintMenuListButton(o, i, r);
}
-void RenderThemeWin::adjustMenuListStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+void RenderThemeWin::adjustMenuListStyle(StyleResolver* styleResolver, RenderStyle* style, Element* e) const
{
style->resetBorder();
- adjustMenuListButtonStyle(selector, style, e);
+ adjustMenuListButtonStyle(styleResolver, style, e);
}
-void RenderThemeWin::adjustMenuListButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+void RenderThemeWin::adjustMenuListButtonStyle(StyleResolver* styleResolver, RenderStyle* style, Element* e) const
{
// These are the paddings needed to place the text correctly in the <select> box
const int dropDownBoxPaddingTop = 2;
@@ -862,7 +862,7 @@ bool RenderThemeWin::paintSearchField(RenderObject* o, const PaintInfo& i, const
return paintTextField(o, i, r);
}
-void RenderThemeWin::adjustSearchFieldStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+void RenderThemeWin::adjustSearchFieldStyle(StyleResolver* styleResolver, RenderStyle* style, Element* e) const
{
// Override paddingSize to match AppKit text positioning.
const int padding = 1;
@@ -876,14 +876,14 @@ void RenderThemeWin::adjustSearchFieldStyle(CSSStyleSelector* selector, RenderSt
bool RenderThemeWin::paintSearchFieldCancelButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
{
- LayoutRect bounds = r;
+ IntRect bounds = r;
ASSERT(o->parent());
if (!o->parent() || !o->parent()->isBox())
return false;
RenderBox* parentRenderBox = toRenderBox(o->parent());
- LayoutRect parentBox = parentRenderBox->absoluteContentBox();
+ IntRect parentBox = parentRenderBox->absoluteContentBox();
// Make sure the scaled button stays square and will fit in its parent's box
bounds.setHeight(min(parentBox.width(), min(parentBox.height(), bounds.height())));
@@ -899,7 +899,7 @@ bool RenderThemeWin::paintSearchFieldCancelButton(RenderObject* o, const PaintIn
return false;
}
-void RenderThemeWin::adjustSearchFieldCancelButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+void RenderThemeWin::adjustSearchFieldCancelButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
{
// Scale the button size based on the font size
float fontScale = style->fontSize() / defaultControlFontPixelSize;
@@ -908,14 +908,14 @@ void RenderThemeWin::adjustSearchFieldCancelButtonStyle(CSSStyleSelector* select
style->setHeight(Length(cancelButtonSize, Fixed));
}
-void RenderThemeWin::adjustSearchFieldDecorationStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+void RenderThemeWin::adjustSearchFieldDecorationStyle(StyleResolver*, RenderStyle* style, Element*) const
{
IntSize emptySize(1, 11);
style->setWidth(Length(emptySize.width(), Fixed));
style->setHeight(Length(emptySize.height(), Fixed));
}
-void RenderThemeWin::adjustSearchFieldResultsDecorationStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+void RenderThemeWin::adjustSearchFieldResultsDecorationStyle(StyleResolver*, RenderStyle* style, Element*) const
{
// Scale the decoration size based on the font size
float fontScale = style->fontSize() / defaultControlFontPixelSize;
@@ -927,13 +927,13 @@ void RenderThemeWin::adjustSearchFieldResultsDecorationStyle(CSSStyleSelector* s
bool RenderThemeWin::paintSearchFieldResultsDecoration(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
{
- LayoutRect bounds = r;
+ IntRect bounds = r;
ASSERT(o->parent());
if (!o->parent() || !o->parent()->isBox())
return false;
RenderBox* parentRenderBox = toRenderBox(o->parent());
- LayoutRect parentBox = parentRenderBox->absoluteContentBox();
+ IntRect parentBox = parentRenderBox->absoluteContentBox();
// Make sure the scaled decoration stays square and will fit in its parent's box
bounds.setHeight(min(parentBox.width(), min(parentBox.height(), bounds.height())));
@@ -948,7 +948,7 @@ bool RenderThemeWin::paintSearchFieldResultsDecoration(RenderObject* o, const Pa
return false;
}
-void RenderThemeWin::adjustSearchFieldResultsButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+void RenderThemeWin::adjustSearchFieldResultsButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
{
// Scale the button size based on the font size
float fontScale = style->fontSize() / defaultControlFontPixelSize;
@@ -961,7 +961,7 @@ void RenderThemeWin::adjustSearchFieldResultsButtonStyle(CSSStyleSelector* selec
bool RenderThemeWin::paintSearchFieldResultsButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
{
- LayoutRect bounds = r;
+ IntRect bounds = r;
ASSERT(o->parent());
if (!o->parent())
return false;
@@ -969,11 +969,11 @@ bool RenderThemeWin::paintSearchFieldResultsButton(RenderObject* o, const PaintI
return false;
RenderBox* parentRenderBox = toRenderBox(o->parent());
- LayoutRect parentBox = parentRenderBox->absoluteContentBox();
+ IntRect parentBox = parentRenderBox->absoluteContentBox();
// Make sure the scaled decoration will fit in its parent's box
bounds.setHeight(min(parentBox.height(), bounds.height()));
- bounds.setWidth(min<LayoutUnit>(parentBox.width(), bounds.height() * defaultSearchFieldResultsButtonWidth / defaultSearchFieldResultsDecorationSize));
+ bounds.setWidth(min<int>(parentBox.width(), bounds.height() * defaultSearchFieldResultsButtonWidth / defaultSearchFieldResultsDecorationSize));
// Center the button vertically. Round up though, so if it has to be one pixel off-center, it will
// be one pixel closer to the bottom of the field. This tends to look better with the text.
@@ -1056,7 +1056,7 @@ bool RenderThemeWin::supportsClosedCaptioning() const
bool RenderThemeWin::paintMediaFullscreenButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
{
- return RenderMediaControls::paintMediaControlsPart(MediaFullscreenButton, o, paintInfo, r);
+ return RenderMediaControls::paintMediaControlsPart(MediaEnterFullscreenButton, o, paintInfo, r);
}
bool RenderThemeWin::paintMediaMuteButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
@@ -1119,7 +1119,7 @@ bool RenderThemeWin::paintMediaVolumeSliderThumb(RenderObject* o, const PaintInf
return RenderMediaControls::paintMediaControlsPart(MediaVolumeSliderThumb, o, paintInfo, r);
}
-LayoutPoint RenderThemeWin::volumeSliderOffsetFromMuteButton(RenderBox* muteButtonBox, const LayoutSize& size) const
+IntPoint RenderThemeWin::volumeSliderOffsetFromMuteButton(RenderBox* muteButtonBox, const IntSize& size) const
{
return RenderMediaControls::volumeSliderOffsetFromMuteButton(muteButtonBox, size);
}
diff --git a/Source/WebCore/rendering/RenderThemeWin.h b/Source/WebCore/rendering/RenderThemeWin.h
index 293796c90..d2337c361 100644
--- a/Source/WebCore/rendering/RenderThemeWin.h
+++ b/Source/WebCore/rendering/RenderThemeWin.h
@@ -77,7 +77,7 @@ public:
virtual bool paintButton(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustInnerSpinButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustInnerSpinButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintInnerSpinButton(RenderObject*, const PaintInfo&, const IntRect&);
virtual bool paintTextField(RenderObject*, const PaintInfo&, const IntRect&);
@@ -85,9 +85,9 @@ public:
virtual bool paintTextArea(RenderObject* o, const PaintInfo& i, const IntRect& r)
{ return paintTextField(o, i, r); }
- virtual void adjustMenuListStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const;
+ virtual void adjustMenuListStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintMenuList(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustMenuListButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const;
+ virtual void adjustMenuListButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintMenuListButton(RenderObject*, const PaintInfo&, const IntRect&);
@@ -97,26 +97,26 @@ public:
virtual bool popupOptionSupportsTextIndent() const { return true; }
- virtual void adjustSearchFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustSearchFieldStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintSearchField(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustSearchFieldCancelButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustSearchFieldCancelButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintSearchFieldCancelButton(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustSearchFieldDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustSearchFieldDecorationStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintSearchFieldDecoration(RenderObject*, const PaintInfo&, const IntRect&) { return false; }
- virtual void adjustSearchFieldResultsDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustSearchFieldResultsDecorationStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintSearchFieldResultsDecoration(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustSearchFieldResultsButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustSearchFieldResultsButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintSearchFieldResultsButton(RenderObject*, const PaintInfo&, const IntRect&);
virtual void themeChanged();
- virtual void adjustButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const {}
- virtual void adjustTextFieldStyle(CSSStyleSelector*, RenderStyle* style, Element*) const {}
- virtual void adjustTextAreaStyle(CSSStyleSelector*, RenderStyle* style, Element*) const {}
+ virtual void adjustButtonStyle(StyleResolver*, RenderStyle* style, Element*) const { }
+ virtual void adjustTextFieldStyle(StyleResolver*, RenderStyle* style, Element*) const { }
+ virtual void adjustTextAreaStyle(StyleResolver*, RenderStyle* style, Element*) const { }
static void setWebKitIsBeingUnloaded();
@@ -141,7 +141,7 @@ public:
virtual bool paintMediaVolumeSliderContainer(RenderObject*, const PaintInfo&, const IntRect&);
virtual bool paintMediaVolumeSliderTrack(RenderObject*, const PaintInfo&, const IntRect&);
virtual bool paintMediaVolumeSliderThumb(RenderObject*, const PaintInfo&, const IntRect&);
- virtual LayoutPoint volumeSliderOffsetFromMuteButton(RenderBox*, const LayoutSize&) const;
+ virtual IntPoint volumeSliderOffsetFromMuteButton(RenderBox*, const IntSize&) const OVERRIDE;
#endif
virtual bool shouldShowPlaceholderWhenFocused() const { return true; }
diff --git a/Source/WebCore/rendering/RenderThemeWinCE.cpp b/Source/WebCore/rendering/RenderThemeWinCE.cpp
index 4a7bb2546..d89257d04 100644
--- a/Source/WebCore/rendering/RenderThemeWinCE.cpp
+++ b/Source/WebCore/rendering/RenderThemeWinCE.cpp
@@ -235,10 +235,10 @@ bool RenderThemeWinCE::paintTextField(RenderObject* o, const PaintInfo& i, const
return false;
}
-void RenderThemeWinCE::adjustMenuListStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+void RenderThemeWinCE::adjustMenuListStyle(StyleResolver* styleResolver, RenderStyle* style, Element* e) const
{
style->resetBorder();
- adjustMenuListButtonStyle(selector, style, e);
+ adjustMenuListButtonStyle(styleResolver, style, e);
}
bool RenderThemeWinCE::paintMenuList(RenderObject* o, const PaintInfo& i, const IntRect& r)
@@ -352,7 +352,7 @@ void RenderThemeWinCE::adjustButtonInnerStyle(RenderStyle* style) const
style->setPaddingLeft(Length(3, Fixed));
}
-void RenderThemeWinCE::adjustSearchFieldStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+void RenderThemeWinCE::adjustSearchFieldStyle(StyleResolver* styleResolver, RenderStyle* style, Element* e) const
{
// Override padding size to match AppKit text positioning.
const int padding = 1;
@@ -392,21 +392,21 @@ bool RenderThemeWinCE::paintSearchFieldCancelButton(RenderObject* o, const Paint
return false;
}
-void RenderThemeWinCE::adjustSearchFieldCancelButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+void RenderThemeWinCE::adjustSearchFieldCancelButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
{
IntSize cancelSize(13, 11);
style->setWidth(Length(cancelSize.width(), Fixed));
style->setHeight(Length(cancelSize.height(), Fixed));
}
-void RenderThemeWinCE::adjustSearchFieldDecorationStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+void RenderThemeWinCE::adjustSearchFieldDecorationStyle(StyleResolver*, RenderStyle* style, Element*) const
{
IntSize emptySize(1, 11);
style->setWidth(Length(emptySize.width(), Fixed));
style->setHeight(Length(emptySize.height(), Fixed));
}
-void RenderThemeWinCE::adjustSearchFieldResultsDecorationStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+void RenderThemeWinCE::adjustSearchFieldResultsDecorationStyle(StyleResolver*, RenderStyle* style, Element*) const
{
IntSize magnifierSize(15, 11);
style->setWidth(Length(magnifierSize.width(), Fixed));
@@ -419,7 +419,7 @@ bool RenderThemeWinCE::paintSearchFieldResultsDecoration(RenderObject* o, const
return false;
}
-void RenderThemeWinCE::adjustSearchFieldResultsButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+void RenderThemeWinCE::adjustSearchFieldResultsButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
{
IntSize magnifierSize(15, 11);
style->setWidth(Length(magnifierSize.width(), Fixed));
@@ -432,7 +432,7 @@ bool RenderThemeWinCE::paintSearchFieldResultsButton(RenderObject* o, const Pain
return false;
}
-void RenderThemeWinCE::adjustMenuListButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+void RenderThemeWinCE::adjustMenuListButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
{
// These are the paddings needed to place the text correctly in the <select> box
const int dropDownBoxPaddingTop = 2;
@@ -529,7 +529,7 @@ bool RenderThemeWinCE::paintSliderThumb(RenderObject* o, const PaintInfo& i, con
return rc;
}
-void RenderThemeWinCE::adjustSearchFieldStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+void RenderThemeWinCE::adjustSearchFieldStyle(StyleResolver*, RenderStyle* style, Element*) const
{
const int padding = 1;
style->setPaddingLeft(Length(padding, Fixed));
diff --git a/Source/WebCore/rendering/RenderThemeWinCE.h b/Source/WebCore/rendering/RenderThemeWinCE.h
index a7df48967..dee237eaf 100644
--- a/Source/WebCore/rendering/RenderThemeWinCE.h
+++ b/Source/WebCore/rendering/RenderThemeWinCE.h
@@ -81,9 +81,9 @@ namespace WebCore {
virtual bool paintTextArea(RenderObject* o, const PaintInfo& i, const IntRect& r)
{ return paintTextField(o, i, r); }
- virtual void adjustMenuListStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const;
+ virtual void adjustMenuListStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintMenuList(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustMenuListButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const;
+ virtual void adjustMenuListButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintMenuListButton(RenderObject*, const PaintInfo&, const IntRect&);
@@ -93,26 +93,26 @@ namespace WebCore {
virtual bool popupOptionSupportsTextIndent() const { return true; }
- virtual void adjustSearchFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustSearchFieldStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintSearchField(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustSearchFieldCancelButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustSearchFieldCancelButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintSearchFieldCancelButton(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustSearchFieldDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustSearchFieldDecorationStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintSearchFieldDecoration(RenderObject*, const PaintInfo&, const IntRect&) { return false; }
- virtual void adjustSearchFieldResultsDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustSearchFieldResultsDecorationStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintSearchFieldResultsDecoration(RenderObject*, const PaintInfo&, const IntRect&);
- virtual void adjustSearchFieldResultsButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual void adjustSearchFieldResultsButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
virtual bool paintSearchFieldResultsButton(RenderObject*, const PaintInfo&, const IntRect&);
virtual void themeChanged();
- virtual void adjustButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const {}
- virtual void adjustTextFieldStyle(CSSStyleSelector*, RenderStyle* style, Element*) const {}
- virtual void adjustTextAreaStyle(CSSStyleSelector*, RenderStyle* style, Element*) const {}
+ virtual void adjustButtonStyle(StyleResolver*, RenderStyle* style, Element*) const { }
+ virtual void adjustTextFieldStyle(StyleResolver*, RenderStyle* style, Element*) const { }
+ virtual void adjustTextAreaStyle(StyleResolver*, RenderStyle* style, Element*) const { }
static void setWebKitIsBeingUnloaded();
diff --git a/Source/WebCore/rendering/RenderTreeAsText.cpp b/Source/WebCore/rendering/RenderTreeAsText.cpp
index 79751ba5f..bc6bf26e3 100644
--- a/Source/WebCore/rendering/RenderTreeAsText.cpp
+++ b/Source/WebCore/rendering/RenderTreeAsText.cpp
@@ -27,6 +27,7 @@
#include "RenderTreeAsText.h"
#include "Document.h"
+#include "FlowThreadController.h"
#include "Frame.h"
#include "FrameSelection.h"
#include "FrameView.h"
@@ -37,11 +38,11 @@
#include "RenderBR.h"
#include "RenderDetailsMarker.h"
#include "RenderFileUploadControl.h"
-#include "RenderFlowThread.h"
#include "RenderInline.h"
#include "RenderLayer.h"
#include "RenderListItem.h"
#include "RenderListMarker.h"
+#include "RenderNamedFlowThread.h"
#include "RenderPart.h"
#include "RenderRegion.h"
#include "RenderTableCell.h"
@@ -76,7 +77,7 @@ namespace WebCore {
using namespace HTMLNames;
-static void writeLayers(TextStream&, const RenderLayer* rootLayer, RenderLayer*, const IntRect& paintDirtyRect, int indent = 0, RenderAsTextBehavior behavior = RenderAsTextBehaviorNormal);
+static void writeLayers(TextStream&, const RenderLayer* rootLayer, RenderLayer*, const LayoutRect& paintDirtyRect, int indent = 0, RenderAsTextBehavior = RenderAsTextBehaviorNormal);
static inline bool hasFractions(double val)
{
@@ -103,6 +104,12 @@ TextStream& operator<<(TextStream& ts, const IntPoint& p)
return ts << "(" << p.x() << "," << p.y() << ")";
}
+TextStream& operator<<(TextStream& ts, const FractionalLayoutPoint& p)
+{
+ // FIXME: These should be printed as floats. Keeping them ints for consistency with pervious test expectations.
+ return ts << "(" << p.x().toInt() << "," << p.y().toInt() << ")";
+}
+
TextStream& operator<<(TextStream& ts, const FloatPoint& p)
{
ts << "(" << formatNumberRespectingIntegers(p.x());
@@ -166,7 +173,7 @@ static String getTagName(Node* n)
{
if (n->isDocumentNode())
return "";
- if (n->isCommentNode())
+ if (n->nodeType() == Node::COMMENT_NODE)
return "COMMENT";
return n->nodeName();
}
@@ -241,7 +248,7 @@ void RenderTreeAsText::writeRenderObject(TextStream& ts, const RenderObject& o,
RenderBlock* cb = o.containingBlock();
bool adjustForTableCells = cb ? cb->isTableCell() : false;
- IntRect r;
+ LayoutRect r;
if (o.isText()) {
// FIXME: Would be better to dump the bounding box x and y rather than the first run's x and y, but that would involve updating
// many test results.
@@ -260,7 +267,7 @@ void RenderTreeAsText::writeRenderObject(TextStream& ts, const RenderObject& o,
// to clean up the results to dump both the outer box and the intrinsic padding so that both bits of information are
// captured by the results.
const RenderTableCell& cell = *toRenderTableCell(&o);
- r = IntRect(cell.x(), cell.y() + cell.intrinsicPaddingBefore(), cell.width(), cell.height() - cell.intrinsicPaddingBefore() - cell.intrinsicPaddingAfter());
+ r = LayoutRect(cell.x(), cell.y() + cell.intrinsicPaddingBefore(), cell.width(), cell.height() - cell.intrinsicPaddingBefore() - cell.intrinsicPaddingAfter());
} else if (o.isBox())
r = toRenderBox(&o)->frameRect();
@@ -268,7 +275,9 @@ void RenderTreeAsText::writeRenderObject(TextStream& ts, const RenderObject& o,
if (adjustForTableCells)
r.move(0, -toRenderTableCell(o.containingBlock())->intrinsicPaddingBefore());
- ts << " " << r;
+ // FIXME: Convert layout test results to report sub-pixel values, in the meantime using enclosingIntRect
+ // for consistency with old results.
+ ts << " " << enclosingIntRect(r);
if (!(o.isText() && !o.isBR())) {
if (o.isFileUploadControl())
@@ -369,7 +378,7 @@ void RenderTreeAsText::writeRenderObject(TextStream& ts, const RenderObject& o,
if (o.isTableCell()) {
const RenderTableCell& c = *toRenderTableCell(&o);
- ts << " [r=" << c.row() << " c=" << c.col() << " rs=" << c.rowSpan() << " cs=" << c.colSpan() << "]";
+ ts << " [r=" << c.rowIndex() << " c=" << c.col() << " rs=" << c.rowSpan() << " cs=" << c.colSpan() << "]";
}
#if ENABLE(DETAILS)
@@ -500,9 +509,9 @@ static void writeTextRun(TextStream& ts, const RenderText& o, const InlineTextBo
y -= toRenderTableCell(o.containingBlock())->intrinsicPaddingBefore();
ts << "text run at (" << x << "," << y << ") width " << logicalWidth;
- if (!run.isLeftToRightDirection() || run.m_dirOverride) {
+ if (!run.isLeftToRightDirection() || run.dirOverride()) {
ts << (!run.isLeftToRightDirection() ? " RTL" : " LTR");
- if (run.m_dirOverride)
+ if (run.dirOverride())
ts << " override";
}
ts << ": "
@@ -590,9 +599,14 @@ enum LayerPaintPhase {
};
static void write(TextStream& ts, RenderLayer& l,
- const IntRect& layerBounds, const IntRect& backgroundClipRect, const IntRect& clipRect, const IntRect& outlineClipRect,
+ const LayoutRect& layerBounds, const LayoutRect& backgroundClipRect, const LayoutRect& clipRect, const LayoutRect& outlineClipRect,
LayerPaintPhase paintPhase = LayerPaintPhaseAll, int indent = 0, RenderAsTextBehavior behavior = RenderAsTextBehaviorNormal)
{
+ IntRect adjustedLayoutBounds = pixelSnappedIntRect(layerBounds);
+ IntRect adjustedBackgroundClipRect = pixelSnappedIntRect(backgroundClipRect);
+ IntRect adjustedClipRect = pixelSnappedIntRect(clipRect);
+ IntRect adjustedOutlineClipRect = pixelSnappedIntRect(outlineClipRect);
+
writeIndent(ts, indent);
ts << "layer ";
@@ -600,15 +614,15 @@ static void write(TextStream& ts, RenderLayer& l,
if (behavior & RenderAsTextShowAddresses)
ts << static_cast<const void*>(&l) << " ";
- ts << layerBounds;
+ ts << adjustedLayoutBounds;
- if (!layerBounds.isEmpty()) {
- if (!backgroundClipRect.contains(layerBounds))
- ts << " backgroundClip " << backgroundClipRect;
- if (!clipRect.contains(layerBounds))
- ts << " clip " << clipRect;
- if (!outlineClipRect.contains(layerBounds))
- ts << " outlineClip " << outlineClipRect;
+ if (!adjustedLayoutBounds.isEmpty()) {
+ if (!adjustedBackgroundClipRect.contains(adjustedLayoutBounds))
+ ts << " backgroundClip " << adjustedBackgroundClipRect;
+ if (!adjustedClipRect.contains(adjustedLayoutBounds))
+ ts << " clip " << adjustedClipRect;
+ if (!adjustedOutlineClipRect.contains(adjustedLayoutBounds))
+ ts << " outlineClip " << adjustedOutlineClipRect;
}
if (l.renderer()->hasOverflowClip()) {
@@ -630,7 +644,7 @@ static void write(TextStream& ts, RenderLayer& l,
#if USE(ACCELERATED_COMPOSITING)
if (behavior & RenderAsTextShowCompositedLayers) {
if (l.isComposited())
- ts << " (composited, bounds " << l.backing()->compositedBounds() << ")";
+ ts << " (composited, bounds=" << l.backing()->compositedBounds() << ", drawsContent=" << l.backing()->graphicsLayer()->drawsContent() << ", paints into ancestor=" << l.backing()->paintsIntoCompositedAncestor() << ")";
}
#else
UNUSED_PARAM(behavior);
@@ -642,21 +656,22 @@ static void write(TextStream& ts, RenderLayer& l,
write(ts, *l.renderer(), indent + 1, behavior);
}
-static void writeRenderFlowThreads(TextStream& ts, RenderView* renderView, const RenderLayer* rootLayer,
- const IntRect& paintRect, int indent, RenderAsTextBehavior behavior)
+static void writeRenderNamedFlowThreads(TextStream& ts, RenderView* renderView, const RenderLayer* rootLayer,
+ const LayoutRect& paintRect, int indent, RenderAsTextBehavior behavior)
{
- const RenderFlowThreadList* list = renderView->renderFlowThreadList();
- if (!list || list->isEmpty())
+ if (!renderView->hasRenderNamedFlowThreads())
return;
+ const RenderNamedFlowThreadList* list = renderView->flowThreadController()->renderNamedFlowThreadList();
+
writeIndent(ts, indent);
ts << "Flow Threads\n";
- for (RenderFlowThreadList::const_iterator iter = list->begin(); iter != list->end(); ++iter) {
- const RenderFlowThread* renderFlowThread = *iter;
+ for (RenderNamedFlowThreadList::const_iterator iter = list->begin(); iter != list->end(); ++iter) {
+ const RenderNamedFlowThread* renderFlowThread = *iter;
writeIndent(ts, indent + 1);
- ts << "Thread with flow-name '" << renderFlowThread->flowThread() << "'\n";
+ ts << "Thread with flow-name '" << renderFlowThread->flowThreadName() << "'\n";
RenderLayer* layer = renderFlowThread->layer();
writeLayers(ts, rootLayer, layer, paintRect, indent + 2, behavior);
@@ -665,7 +680,7 @@ static void writeRenderFlowThreads(TextStream& ts, RenderView* renderView, const
const RenderRegionList& flowThreadRegionList = renderFlowThread->renderRegionList();
if (!flowThreadRegionList.isEmpty()) {
writeIndent(ts, indent + 1);
- ts << "Regions for flow '"<< renderFlowThread->flowThread() << "'\n";
+ ts << "Regions for flow '"<< renderFlowThread->flowThreadName() << "'\n";
for (RenderRegionList::const_iterator itRR = flowThreadRegionList.begin(); itRR != flowThreadRegionList.end(); ++itRR) {
RenderRegion* renderRegion = *itRR;
writeIndent(ts, indent + 2);
@@ -690,24 +705,23 @@ static void writeRenderFlowThreads(TextStream& ts, RenderView* renderView, const
}
static void writeLayers(TextStream& ts, const RenderLayer* rootLayer, RenderLayer* l,
- const IntRect& paintRect, int indent, RenderAsTextBehavior behavior)
+ const LayoutRect& paintRect, int indent, RenderAsTextBehavior behavior)
{
// FIXME: Apply overflow to the root layer to not break every test. Complete hack. Sigh.
- IntRect paintDirtyRect(paintRect);
+ LayoutRect paintDirtyRect(paintRect);
if (rootLayer == l) {
- paintDirtyRect.setWidth(max(paintDirtyRect.width(), rootLayer->renderBox()->maxXLayoutOverflow()));
- paintDirtyRect.setHeight(max(paintDirtyRect.height(), rootLayer->renderBox()->maxYLayoutOverflow()));
- l->setSize(l->size().expandedTo(l->renderBox()->maxLayoutOverflow()));
+ paintDirtyRect.setWidth(max<LayoutUnit>(paintDirtyRect.width(), rootLayer->renderBox()->maxXLayoutOverflow()));
+ paintDirtyRect.setHeight(max<LayoutUnit>(paintDirtyRect.height(), rootLayer->renderBox()->maxYLayoutOverflow()));
+ l->setSize(l->size().expandedTo(pixelSnappedIntSize(l->renderBox()->maxLayoutOverflow(), LayoutPoint(0, 0))));
}
// Calculate the clip rects we should use.
- IntRect layerBounds;
+ LayoutRect layerBounds;
ClipRect damageRect, clipRectToApply, outlineRect;
l->calculateRects(rootLayer, 0, paintDirtyRect, layerBounds, damageRect, clipRectToApply, outlineRect, true);
// Ensure our lists are up-to-date.
- l->updateZOrderLists();
- l->updateNormalFlowList();
+ l->updateLayerListsIfNeeded();
bool shouldPaint = (behavior & RenderAsTextShowAllLayers) ? true : l->intersectsDamageRect(layerBounds, damageRect.rect(), rootLayer);
Vector<RenderLayer*>* negList = l->negZOrderList();
@@ -755,7 +769,7 @@ static void writeLayers(TextStream& ts, const RenderLayer* rootLayer, RenderLaye
// so we have to treat it as a special case.
if (l->renderer()->isRenderView()) {
RenderView* renderView = toRenderView(l->renderer());
- writeRenderFlowThreads(ts, renderView, rootLayer, paintDirtyRect, indent, behavior);
+ writeRenderNamedFlowThreads(ts, renderView, rootLayer, paintDirtyRect, indent, behavior);
}
}
diff --git a/Source/WebCore/rendering/RenderTreeAsText.h b/Source/WebCore/rendering/RenderTreeAsText.h
index 26cc065cc..849943068 100644
--- a/Source/WebCore/rendering/RenderTreeAsText.h
+++ b/Source/WebCore/rendering/RenderTreeAsText.h
@@ -33,6 +33,7 @@
namespace WebCore {
class Element;
+class FractionalLayoutPoint;
class FloatPoint;
class FloatSize;
class Frame;
@@ -70,6 +71,7 @@ static void writeRenderObject(TextStream& ts, const RenderObject& o, RenderAsTex
TextStream& operator<<(TextStream&, const IntPoint&);
TextStream& operator<<(TextStream&, const IntRect&);
+TextStream& operator<<(TextStream&, const FractionalLayoutPoint&);
TextStream& operator<<(TextStream&, const FloatPoint&);
TextStream& operator<<(TextStream&, const FloatSize&);
diff --git a/Source/WebCore/rendering/RenderVideo.cpp b/Source/WebCore/rendering/RenderVideo.cpp
index 1fc87a7d2..37f2f0844 100644
--- a/Source/WebCore/rendering/RenderVideo.cpp
+++ b/Source/WebCore/rendering/RenderVideo.cpp
@@ -43,13 +43,6 @@
#include "RenderFullScreen.h"
#endif
-#if USE(ACCELERATED_COMPOSITING)
-#include "RenderLayer.h"
-#include "RenderLayerBacking.h"
-#endif
-
-using namespace std;
-
namespace WebCore {
using namespace HTMLNames;
@@ -166,7 +159,7 @@ IntRect RenderVideo::videoBox() const
else
elementSize = intrinsicSize();
- IntRect contentRect = contentBoxRect();
+ IntRect contentRect = pixelSnappedIntRect(contentBoxRect());
if (elementSize.isEmpty() || contentRect.isEmpty())
return IntRect();
@@ -225,9 +218,9 @@ void RenderVideo::paintReplaced(PaintInfo& paintInfo, const LayoutPoint& paintOf
if (displayingPoster)
paintIntoRect(paintInfo.context, rect);
else if (document()->view() && document()->view()->paintBehavior() & PaintBehaviorFlattenCompositingLayers)
- mediaPlayer->paintCurrentFrameInContext(paintInfo.context, rect);
+ mediaPlayer->paintCurrentFrameInContext(paintInfo.context, pixelSnappedIntRect(rect));
else
- mediaPlayer->paint(paintInfo.context, rect);
+ mediaPlayer->paint(paintInfo.context, pixelSnappedIntRect(rect));
}
void RenderVideo::layout()
@@ -262,7 +255,7 @@ void RenderVideo::updatePlayer()
}
#if USE(ACCELERATED_COMPOSITING)
- layer()->contentChanged(RenderLayer::VideoChanged);
+ contentChanged(VideoChanged);
#endif
IntRect videoBounds = videoBox();
diff --git a/Source/WebCore/rendering/RenderView.cpp b/Source/WebCore/rendering/RenderView.cpp
index cd3893a55..4a3a2bc83 100644
--- a/Source/WebCore/rendering/RenderView.cpp
+++ b/Source/WebCore/rendering/RenderView.cpp
@@ -25,14 +25,15 @@
#include "Document.h"
#include "Element.h"
#include "FloatQuad.h"
+#include "FlowThreadController.h"
#include "Frame.h"
#include "FrameView.h"
#include "GraphicsContext.h"
#include "HTMLFrameOwnerElement.h"
#include "HitTestResult.h"
#include "Page.h"
-#include "RenderFlowThread.h"
#include "RenderLayer.h"
+#include "RenderNamedFlowThread.h"
#include "RenderSelectionInfo.h"
#include "RenderWidget.h"
#include "RenderWidgetProtector.h"
@@ -54,10 +55,8 @@ RenderView::RenderView(Node* node, FrameView* view)
, m_maximalOutlineSize(0)
, m_pageLogicalHeight(0)
, m_pageLogicalHeightChanged(false)
- , m_isRenderFlowThreadOrderDirty(false)
, m_layoutState(0)
, m_layoutStateDisableCount(0)
- , m_currentRenderFlowThread(0)
{
// Clear our anonymous bit, set because RenderObject assumes
// any renderer with document as the node is anonymous.
@@ -69,7 +68,7 @@ RenderView::RenderView(Node* node, FrameView* view)
m_minPreferredLogicalWidth = 0;
m_maxPreferredLogicalWidth = 0;
- setPreferredLogicalWidthsDirty(true, false);
+ setPreferredLogicalWidthsDirty(true, MarkOnlyThis);
setPositioned(true); // to 0,0 :)
}
@@ -78,6 +77,11 @@ RenderView::~RenderView()
{
}
+bool RenderView::hitTest(const HitTestRequest& request, HitTestResult& result)
+{
+ return layer()->hitTest(request, result);
+}
+
void RenderView::computeLogicalHeight()
{
if (!printing() && m_frameView)
@@ -95,8 +99,6 @@ void RenderView::computePreferredLogicalWidths()
ASSERT(preferredLogicalWidthsDirty());
RenderBlock::computePreferredLogicalWidths();
-
- m_maxPreferredLogicalWidth = m_minPreferredLogicalWidth;
}
bool RenderView::isChildAllowed(RenderObject* child, RenderStyle*) const
@@ -115,10 +117,13 @@ void RenderView::layout()
// Use calcWidth/Height to get the new width/height, since this will take the full page zoom factor into account.
bool relayoutChildren = !printing() && (!m_frameView || width() != viewWidth() || height() != viewHeight());
if (relayoutChildren) {
- setChildNeedsLayout(true, false);
+ setChildNeedsLayout(true, MarkOnlyThis);
for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
- if (child->style()->logicalHeight().isPercent() || child->style()->logicalMinHeight().isPercent() || child->style()->logicalMaxHeight().isPercent())
- child->setChildNeedsLayout(true, false);
+ if ((child->isBox() && toRenderBox(child)->hasRelativeLogicalHeight())
+ || child->style()->logicalHeight().isPercent()
+ || child->style()->logicalMinHeight().isPercent()
+ || child->style()->logicalMaxHeight().isPercent())
+ child->setChildNeedsLayout(true, MarkOnlyThis);
}
}
@@ -134,8 +139,8 @@ void RenderView::layout()
if (needsLayout()) {
RenderBlock::layout();
- if (hasRenderFlowThreads())
- layoutRenderFlowThreads();
+ if (hasRenderNamedFlowThreads())
+ flowThreadController()->layoutRenderNamedFlowThreads();
}
ASSERT(layoutDelta() == LayoutSize());
@@ -145,7 +150,7 @@ void RenderView::layout()
setNeedsLayout(false);
}
-void RenderView::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed, bool useTransforms, TransformState& transformState, bool* wasFixed) const
+void RenderView::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed, bool useTransforms, TransformState& transformState, ApplyContainerFlipOrNot, bool* wasFixed) const
{
// If a container was specified, and was not 0 or the RenderView,
// then we should have found it by now.
@@ -214,6 +219,8 @@ void RenderView::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
// If we ever require layout but receive a paint anyway, something has gone horribly wrong.
ASSERT(!needsLayout());
+ // RenderViews should never be called to paint with an offset not on device pixels.
+ ASSERT(LayoutPoint(IntPoint(paintOffset.x(), paintOffset.y())) == paintOffset);
paintObject(paintInfo, paintOffset);
}
@@ -246,8 +253,8 @@ void RenderView::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint&)
}
#if USE(ACCELERATED_COMPOSITING)
- if (RenderLayer* compositingLayer = layer->enclosingCompositingLayer()) {
- if (!compositingLayer->backing()->paintingGoesToWindow()) {
+ if (RenderLayer* compositingLayer = layer->enclosingCompositingLayerForRepaint()) {
+ if (!compositingLayer->backing()->paintsIntoWindow()) {
frameView()->setCannotBlitToWindow();
break;
}
@@ -291,18 +298,21 @@ void RenderView::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint&)
}
}
-bool RenderView::shouldRepaint(const IntRect& r) const
+bool RenderView::shouldRepaint(const LayoutRect& r) const
{
if (printing() || r.width() == 0 || r.height() == 0)
return false;
if (!m_frameView)
return false;
-
+
+ if (m_frameView->repaintsDisabled())
+ return false;
+
return true;
}
-void RenderView::repaintViewRectangle(const IntRect& ur, bool immediate)
+void RenderView::repaintViewRectangle(const LayoutRect& ur, bool immediate)
{
if (!shouldRepaint(ur))
return;
@@ -311,23 +321,22 @@ void RenderView::repaintViewRectangle(const IntRect& ur, bool immediate)
// or even invisible.
Element* elt = document()->ownerElement();
if (!elt)
- m_frameView->repaintContentRectangle(ur, immediate);
+ m_frameView->repaintContentRectangle(pixelSnappedIntRect(ur), immediate);
else if (RenderBox* obj = elt->renderBox()) {
- IntRect vr = viewRect();
- IntRect r = intersection(ur, vr);
+ LayoutRect vr = viewRect();
+ LayoutRect r = intersection(ur, vr);
// Subtract out the contentsX and contentsY offsets to get our coords within the viewing
// rectangle.
r.moveBy(-vr.location());
-
+
// FIXME: Hardcoded offsets here are not good.
- r.move(obj->borderLeft() + obj->paddingLeft(),
- obj->borderTop() + obj->paddingTop());
+ r.moveBy(obj->contentBoxRect().location());
obj->repaintRectangle(r, immediate);
}
}
-void RenderView::repaintRectangleInViewAndCompositedLayers(const IntRect& ur, bool immediate)
+void RenderView::repaintRectangleInViewAndCompositedLayers(const LayoutRect& ur, bool immediate)
{
if (!shouldRepaint(ur))
return;
@@ -336,11 +345,11 @@ void RenderView::repaintRectangleInViewAndCompositedLayers(const IntRect& ur, bo
#if USE(ACCELERATED_COMPOSITING)
if (compositor()->inCompositingMode())
- compositor()->repaintCompositedLayersAbsoluteRect(ur);
+ compositor()->repaintCompositedLayersAbsoluteRect(pixelSnappedIntRect(ur));
#endif
}
-void RenderView::computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect& rect, bool fixed) const
+void RenderView::computeRectForRepaint(RenderBoxModelObject* repaintContainer, LayoutRect& rect, bool fixed) const
{
// If a container was specified, and was not 0 or the RenderView,
// then we should have found it by now.
@@ -414,12 +423,12 @@ IntRect RenderView::selectionBounds(bool clipToVisibleContent) const
}
// Now create a single bounding box rect that encloses the whole selection.
- IntRect selRect;
+ LayoutRect selRect;
SelectionMap::iterator end = selectedObjects.end();
for (SelectionMap::iterator i = selectedObjects.begin(); i != end; ++i) {
RenderSelectionInfo* info = i->second;
// RenderSelectionInfo::rect() is in the coordinates of the repaintContainer, so map to page coordinates.
- IntRect currRect = info->rect();
+ LayoutRect currRect = info->rect();
if (RenderBoxModelObject* repaintContainer = info->repaintContainer()) {
FloatQuad absQuad = repaintContainer->localToAbsoluteQuad(FloatRect(currRect));
currRect = absQuad.enclosingBoundingBox();
@@ -427,7 +436,7 @@ IntRect RenderView::selectionBounds(bool clipToVisibleContent) const
selRect.unite(currRect);
delete info;
}
- return selRect;
+ return pixelSnappedIntRect(selRect);
}
#if USE(ACCELERATED_COMPOSITING)
@@ -700,21 +709,21 @@ void RenderView::notifyWidgets(WidgetNotification notification)
releaseWidgets(renderWidgets);
}
-IntRect RenderView::viewRect() const
+LayoutRect RenderView::viewRect() const
{
if (printing())
- return IntRect(IntPoint(), size());
+ return LayoutRect(LayoutPoint(), size());
if (m_frameView)
return m_frameView->visibleContentRect();
- return IntRect();
+ return LayoutRect();
}
IntRect RenderView::unscaledDocumentRect() const
{
- IntRect overflowRect(layoutOverflowRect());
+ LayoutRect overflowRect(layoutOverflowRect());
flipForWritingMode(overflowRect);
- return overflowRect;
+ return pixelSnappedIntRect(overflowRect);
}
LayoutRect RenderView::backgroundRect(RenderBox* backgroundRenderer) const
@@ -882,64 +891,62 @@ void RenderView::styleDidChange(StyleDifference diff, const RenderStyle* oldStyl
RenderBlock::styleDidChange(diff, oldStyle);
for (RenderObject* renderer = firstChild(); renderer; renderer = renderer->nextSibling()) {
- if (renderer->isRenderFlowThread()) {
- RenderFlowThread* flowRenderer = toRenderFlowThread(renderer);
+ if (renderer->isRenderNamedFlowThread()) {
+ RenderNamedFlowThread* flowRenderer = toRenderNamedFlowThread(renderer);
flowRenderer->setStyle(RenderFlowThread::createFlowThreadStyle(style()));
}
}
}
-RenderFlowThread* RenderView::ensureRenderFlowThreadWithName(const AtomicString& flowThread)
+bool RenderView::hasRenderNamedFlowThreads() const
{
- if (!m_renderFlowThreadList)
- m_renderFlowThreadList = adoptPtr(new RenderFlowThreadList());
- else {
- for (RenderFlowThreadList::iterator iter = m_renderFlowThreadList->begin(); iter != m_renderFlowThreadList->end(); ++iter) {
- RenderFlowThread* flowRenderer = *iter;
- if (flowRenderer->flowThread() == flowThread)
- return flowRenderer;
- }
- }
+ return m_flowThreadController && m_flowThreadController->hasRenderNamedFlowThreads();
+}
- RenderFlowThread* flowRenderer = new (renderArena()) RenderFlowThread(document(), flowThread);
- flowRenderer->setStyle(RenderFlowThread::createFlowThreadStyle(style()));
- addChild(flowRenderer);
+FlowThreadController* RenderView::flowThreadController()
+{
+ if (!m_flowThreadController)
+ m_flowThreadController = FlowThreadController::create(this);
- m_renderFlowThreadList->add(flowRenderer);
- setIsRenderFlowThreadOrderDirty(true);
+ return m_flowThreadController.get();
+}
- return flowRenderer;
+RenderBlock::IntervalArena* RenderView::intervalArena()
+{
+ if (!m_intervalArena)
+ m_intervalArena = IntervalArena::create();
+ return m_intervalArena.get();
}
-void RenderView::layoutRenderFlowThreads()
+void RenderView::setFixedPositionedObjectsNeedLayout()
{
- ASSERT(m_renderFlowThreadList);
+ ASSERT(m_frameView);
- if (isRenderFlowThreadOrderDirty()) {
- // Arrange the thread list according to dependencies.
- RenderFlowThreadList sortedList;
- for (RenderFlowThreadList::iterator iter = m_renderFlowThreadList->begin(); iter != m_renderFlowThreadList->end(); ++iter) {
- RenderFlowThread* flowRenderer = *iter;
- if (sortedList.contains(flowRenderer))
- continue;
- flowRenderer->pushDependencies(sortedList);
- sortedList.add(flowRenderer);
- }
- m_renderFlowThreadList->swap(sortedList);
- setIsRenderFlowThreadOrderDirty(false);
- }
+ PositionedObjectsListHashSet* positionedObjects = this->positionedObjects();
+ if (!positionedObjects)
+ return;
- for (RenderFlowThreadList::iterator iter = m_renderFlowThreadList->begin(); iter != m_renderFlowThreadList->end(); ++iter) {
- RenderFlowThread* flowRenderer = *iter;
- flowRenderer->layoutIfNeeded();
+ PositionedObjectsListHashSet::const_iterator end = positionedObjects->end();
+ for (PositionedObjectsListHashSet::const_iterator it = positionedObjects->begin(); it != end; ++it) {
+ RenderBox* currBox = *it;
+ currBox->setNeedsLayout(true);
}
}
-RenderBlock::IntervalArena* RenderView::intervalArena()
+void RenderView::insertFixedPositionedObject(RenderBox* object)
{
- if (!m_intervalArena)
- m_intervalArena = IntervalArena::create();
- return m_intervalArena.get();
+ if (!m_positionedObjects)
+ m_positionedObjects = adoptPtr(new PositionedObjectsListHashSet);
+
+ m_positionedObjects->add(object);
+}
+
+void RenderView::removeFixedPositionedObject(RenderBox* object)
+{
+ if (!m_positionedObjects)
+ return;
+
+ m_positionedObjects->remove(object);
}
} // namespace WebCore
diff --git a/Source/WebCore/rendering/RenderView.h b/Source/WebCore/rendering/RenderView.h
index 66000942e..1371e136e 100644
--- a/Source/WebCore/rendering/RenderView.h
+++ b/Source/WebCore/rendering/RenderView.h
@@ -26,37 +26,38 @@
#include "LayoutState.h"
#include "PODFreeListArena.h"
#include "RenderBlock.h"
-#include <wtf/ListHashSet.h>
#include <wtf/OwnPtr.h>
namespace WebCore {
-class RenderFlowThread;
+class FlowThreadController;
class RenderWidget;
#if USE(ACCELERATED_COMPOSITING)
class RenderLayerCompositor;
#endif
-typedef ListHashSet<RenderFlowThread*> RenderFlowThreadList;
-
class RenderView : public RenderBlock {
public:
RenderView(Node*, FrameView*);
virtual ~RenderView();
- virtual const char* renderName() const { return "RenderView"; }
+ bool hitTest(const HitTestRequest&, HitTestResult&);
+
+ virtual const char* renderName() const OVERRIDE { return "RenderView"; }
- virtual bool isRenderView() const { return true; }
+ virtual bool isRenderView() const OVERRIDE { return true; }
- virtual bool requiresLayer() const { return true; }
+ virtual bool requiresLayer() const OVERRIDE { return true; }
- virtual bool isChildAllowed(RenderObject*, RenderStyle*) const;
+ virtual bool isChildAllowed(RenderObject*, RenderStyle*) const OVERRIDE;
- virtual void layout();
- virtual void computeLogicalWidth();
- virtual void computeLogicalHeight();
- virtual void computePreferredLogicalWidths();
+ virtual void layout() OVERRIDE;
+ virtual void computeLogicalWidth() OVERRIDE;
+ virtual void computeLogicalHeight() OVERRIDE;
+ // FIXME: This override is not needed and should be removed
+ // it only exists to make computePreferredLogicalWidths public.
+ virtual void computePreferredLogicalWidths() OVERRIDE;
// The same as the FrameView's layoutHeight/layoutWidth but with null check guards.
int viewHeight() const;
@@ -68,14 +69,14 @@ public:
FrameView* frameView() const { return m_frameView; }
- virtual void computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect&, bool fixed = false) const;
- virtual void repaintViewRectangle(const IntRect&, bool immediate = false);
+ virtual void computeRectForRepaint(RenderBoxModelObject* repaintContainer, LayoutRect&, bool fixed = false) const;
+ virtual void repaintViewRectangle(const LayoutRect&, bool immediate = false);
// Repaint the view, and all composited layers that intersect the given absolute rectangle.
// FIXME: ideally we'd never have to do this, if all repaints are container-relative.
- virtual void repaintRectangleInViewAndCompositedLayers(const IntRect&, bool immediate = false);
+ virtual void repaintRectangleInViewAndCompositedLayers(const LayoutRect&, bool immediate = false);
virtual void paint(PaintInfo&, const LayoutPoint&);
- virtual void paintBoxDecorations(PaintInfo&, const IntPoint&);
+ virtual void paintBoxDecorations(PaintInfo&, const LayoutPoint&) OVERRIDE;
enum SelectionRepaintMode { RepaintNewXOROld, RepaintNewMinusOld, RepaintNothing };
void setSelection(RenderObject* start, int startPos, RenderObject* end, int endPos, SelectionRepaintMode = RepaintNewXOROld);
@@ -98,7 +99,7 @@ public:
#endif
int maximalOutlineSize() const { return m_maximalOutlineSize; }
- virtual IntRect viewRect() const;
+ virtual LayoutRect viewRect() const OVERRIDE;
void updateWidgetPositions();
void addWidget(RenderWidget*);
@@ -172,27 +173,21 @@ public:
IntRect documentRect() const;
- RenderFlowThread* ensureRenderFlowThreadWithName(const AtomicString& flowThread);
- bool hasRenderFlowThreads() const { return m_renderFlowThreadList && !m_renderFlowThreadList->isEmpty(); }
- void layoutRenderFlowThreads();
- bool isRenderFlowThreadOrderDirty() const { return m_isRenderFlowThreadOrderDirty; }
- void setIsRenderFlowThreadOrderDirty(bool dirty)
- {
- m_isRenderFlowThreadOrderDirty = dirty;
- if (dirty)
- setNeedsLayout(true);
- }
- const RenderFlowThreadList* renderFlowThreadList() const { return m_renderFlowThreadList.get(); }
-
- RenderFlowThread* currentRenderFlowThread() const { return m_currentRenderFlowThread; }
- void setCurrentRenderFlowThread(RenderFlowThread* flowThread) { m_currentRenderFlowThread = flowThread; }
+ bool hasRenderNamedFlowThreads() const;
+ FlowThreadController* flowThreadController();
void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
IntervalArena* intervalArena();
+ IntSize viewportSize() const { return document()->viewportSize(); }
+
+ void setFixedPositionedObjectsNeedLayout();
+ void insertFixedPositionedObject(RenderBox*);
+ void removeFixedPositionedObject(RenderBox*);
+
protected:
- virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool useTransforms, bool fixed, TransformState&, bool* wasFixed = 0) const;
+ virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool useTransforms, bool fixed, TransformState&, ApplyContainerFlipOrNot = ApplyContainerFlip, bool* wasFixed = 0) const;
virtual void mapAbsoluteToLocalPoint(bool fixed, bool useTransforms, TransformState&) const;
virtual bool requiresColumns(int desiredColumnCount) const OVERRIDE;
@@ -200,7 +195,7 @@ private:
virtual void calcColumnWidth() OVERRIDE;
virtual ColumnInfo::PaginationUnit paginationUnit() const OVERRIDE;
- bool shouldRepaint(const IntRect& r) const;
+ bool shouldRepaint(const LayoutRect&) const;
// These functions may only be accessed by LayoutStateMaintainer.
void pushLayoutState(RenderFlowThread*, bool regionsChanged);
@@ -266,18 +261,19 @@ protected:
typedef HashSet<RenderWidget*> RenderWidgetSet;
RenderWidgetSet m_widgets;
-
+
+ typedef HashSet<RenderBox*> RenderBoxSet;
+ OwnPtr<RenderBoxSet> m_fixedPositionedElements;
+
private:
unsigned m_pageLogicalHeight;
bool m_pageLogicalHeightChanged;
- bool m_isRenderFlowThreadOrderDirty;
LayoutState* m_layoutState;
unsigned m_layoutStateDisableCount;
#if USE(ACCELERATED_COMPOSITING)
OwnPtr<RenderLayerCompositor> m_compositor;
#endif
- OwnPtr<RenderFlowThreadList> m_renderFlowThreadList;
- RenderFlowThread* m_currentRenderFlowThread;
+ OwnPtr<FlowThreadController> m_flowThreadController;
RefPtr<IntervalArena> m_intervalArena;
};
diff --git a/Source/WebCore/rendering/RenderWidget.cpp b/Source/WebCore/rendering/RenderWidget.cpp
index 55802c4c2..c49d8f201 100644
--- a/Source/WebCore/rendering/RenderWidget.cpp
+++ b/Source/WebCore/rendering/RenderWidget.cpp
@@ -140,12 +140,20 @@ RenderWidget::~RenderWidget()
clearWidget();
}
-bool RenderWidget::setWidgetGeometry(const IntRect& frame)
+// Widgets are always placed on integer boundaries, so rounding the size is actually
+// the desired behavior. This function is here because it's otherwise seldom what we
+// want to do with a LayoutRect.
+static inline IntRect roundedIntRect(const LayoutRect& rect)
+{
+ return IntRect(roundedIntPoint(rect.location()), roundedIntSize(rect.size()));
+}
+
+bool RenderWidget::setWidgetGeometry(const LayoutRect& frame)
{
if (!node())
return false;
- IntRect clipRect = enclosingLayer()->childrenClipRect();
+ IntRect clipRect = roundedIntRect(enclosingLayer()->childrenClipRect());
bool clipChanged = m_clipRect != clipRect;
bool boundsChanged = m_widget->frameRect() != frame;
@@ -156,7 +164,7 @@ bool RenderWidget::setWidgetGeometry(const IntRect& frame)
RenderWidgetProtector protector(this);
RefPtr<Node> protectedNode(node());
- m_widget->setFrameRect(frame);
+ m_widget->setFrameRect(roundedIntRect(frame));
#if USE(ACCELERATED_COMPOSITING)
if (hasLayer() && layer()->isComposited())
@@ -168,11 +176,11 @@ bool RenderWidget::setWidgetGeometry(const IntRect& frame)
bool RenderWidget::updateWidgetGeometry()
{
- IntRect contentBox = contentBoxRect();
+ IntRect contentBox = pixelSnappedIntRect(contentBoxRect());
if (!m_widget->transformsAffectFrameRect())
return setWidgetGeometry(absoluteContentBox());
- IntRect absoluteContentBox = IntRect(localToAbsoluteQuad(FloatQuad(contentBox)).boundingBox());
+ IntRect absoluteContentBox(localToAbsoluteQuad(FloatQuad(contentBox)).boundingBox());
if (m_widget->isFrameView()) {
contentBox.setLocation(absoluteContentBox.location());
return setWidgetGeometry(contentBox);
@@ -270,17 +278,18 @@ void RenderWidget::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
// Push a clip if we have a border radius, since we want to round the foreground content that gets painted.
paintInfo.context->save();
- paintInfo.context->addRoundedRectClip(style()->getRoundedBorderFor(borderRect));
+ paintInfo.context->addRoundedRectClip(style()->getRoundedBorderFor(borderRect, view()));
}
if (m_widget) {
// Tell the widget to paint now. This is the only time the widget is allowed
// to paint itself. That way it will composite properly with z-indexed layers.
- LayoutPoint widgetLocation = m_widget->frameRect().location();
- LayoutPoint paintLocation(adjustedPaintOffset.x() + borderLeft() + paddingLeft(), adjustedPaintOffset.y() + borderTop() + paddingTop());
- LayoutRect paintRect = paintInfo.rect;
+ IntPoint widgetLocation = m_widget->frameRect().location();
+ IntPoint paintLocation(roundToInt(adjustedPaintOffset.x() + borderLeft() + paddingLeft()),
+ roundToInt(adjustedPaintOffset.y() + borderTop() + paddingTop()));
+ IntRect paintRect = paintInfo.rect;
- LayoutSize widgetPaintOffset = paintLocation - widgetLocation;
+ IntSize widgetPaintOffset = paintLocation - widgetLocation;
// When painting widgets into compositing layers, tx and ty are relative to the enclosing compositing layer,
// not the root. In this case, shift the CTM and adjust the paintRect to be root-relative to fix plug-in drawing.
if (!widgetPaintOffset.isZero()) {
diff --git a/Source/WebCore/rendering/RenderWidget.h b/Source/WebCore/rendering/RenderWidget.h
index 8bfa30ba4..54a7a771c 100644
--- a/Source/WebCore/rendering/RenderWidget.h
+++ b/Source/WebCore/rendering/RenderWidget.h
@@ -70,7 +70,7 @@ private:
virtual void setSelectionState(SelectionState);
virtual void setOverlapTestResult(bool);
- bool setWidgetGeometry(const IntRect&);
+ bool setWidgetGeometry(const LayoutRect&);
bool updateWidgetGeometry();
RefPtr<Widget> m_widget;
diff --git a/Source/WebCore/rendering/RenderingAllInOne.cpp b/Source/WebCore/rendering/RenderingAllInOne.cpp
index b52e2908a..ff8e0731e 100644
--- a/Source/WebCore/rendering/RenderingAllInOne.cpp
+++ b/Source/WebCore/rendering/RenderingAllInOne.cpp
@@ -74,6 +74,7 @@
#include "RenderMediaControls.cpp"
#include "RenderMenuList.cpp"
#include "RenderMeter.cpp"
+#include "RenderMultiColumnBlock.cpp"
#include "RenderObject.cpp"
#include "RenderObjectChildList.cpp"
#include "RenderPart.cpp"
diff --git a/Source/WebCore/rendering/RootInlineBox.cpp b/Source/WebCore/rendering/RootInlineBox.cpp
index c56560065..9b973b3b2 100644
--- a/Source/WebCore/rendering/RootInlineBox.cpp
+++ b/Source/WebCore/rendering/RootInlineBox.cpp
@@ -100,6 +100,16 @@ bool RootInlineBox::isHyphenated() const
return false;
}
+LayoutUnit RootInlineBox::baselinePosition(FontBaseline baselineType) const
+{
+ return boxModelObject()->baselinePosition(baselineType, isFirstLineStyle(), isHorizontal() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes);
+}
+
+LayoutUnit RootInlineBox::lineHeight() const
+{
+ return boxModelObject()->lineHeight(isFirstLineStyle(), isHorizontal() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes);
+}
+
bool RootInlineBox::lineCanAccommodateEllipsis(bool ltr, int blockEdge, int lineBoxEdge, int ellipsisWidth)
{
// First sanity-check the unoverflowed width of the whole line to see if there is sufficient room.
@@ -196,7 +206,7 @@ void RootInlineBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset,
InlineFlowBox::paint(paintInfo, paintOffset, lineTop, lineBottom);
paintEllipsisBox(paintInfo, paintOffset, lineTop, lineBottom);
#if PLATFORM(MAC)
- RenderStyle* styleToUse = renderer()->style(m_firstLine);
+ RenderStyle* styleToUse = renderer()->style(isFirstLineStyle());
if (styleToUse->highlight() != nullAtom && !paintInfo.context->paintingDisabled())
paintCustomHighlight(paintInfo, paintOffset, styleToUse->highlight());
#endif
@@ -278,7 +288,7 @@ LayoutUnit RootInlineBox::alignBoxesInBlockDirection(LayoutUnit heightOfBlock, G
setLineTopBottomPositions(lineTop, lineBottom, heightOfBlock, heightOfBlock + maxHeight);
setPaginatedLineWidth(block()->availableLogicalWidthForContent(heightOfBlock));
- int annotationsAdjustment = beforeAnnotationsAdjustment();
+ LayoutUnit annotationsAdjustment = beforeAnnotationsAdjustment();
if (annotationsAdjustment) {
// FIXME: Need to handle pagination here. We might have to move to the next page/column as a result of the
// ruby expansion.
@@ -295,9 +305,9 @@ LayoutUnit RootInlineBox::alignBoxesInBlockDirection(LayoutUnit heightOfBlock, G
return heightOfBlock + maxHeight;
}
-int RootInlineBox::beforeAnnotationsAdjustment() const
+LayoutUnit RootInlineBox::beforeAnnotationsAdjustment() const
{
- int result = 0;
+ LayoutUnit result = 0;
if (!renderer()->style()->isFlippedLinesWritingMode()) {
// Annotations under the previous line may push us down.
@@ -308,18 +318,18 @@ int RootInlineBox::beforeAnnotationsAdjustment() const
return result;
// Annotations over this line may push us further down.
- int highestAllowedPosition = prevRootBox() ? min(prevRootBox()->lineBottom(), lineTop()) + result : block()->borderBefore();
+ LayoutUnit highestAllowedPosition = prevRootBox() ? min(prevRootBox()->lineBottom(), lineTop()) + result : static_cast<LayoutUnit>(block()->borderBefore());
result = computeOverAnnotationAdjustment(highestAllowedPosition);
} else {
// Annotations under this line may push us up.
if (hasAnnotationsBefore())
- result = computeUnderAnnotationAdjustment(prevRootBox() ? prevRootBox()->lineBottom() : block()->borderBefore());
+ result = computeUnderAnnotationAdjustment(prevRootBox() ? prevRootBox()->lineBottom() : static_cast<LayoutUnit>(block()->borderBefore()));
if (!prevRootBox() || !prevRootBox()->hasAnnotationsAfter())
return result;
// We have to compute the expansion for annotations over the previous line to see how much we should move.
- int lowestAllowedPosition = max(prevRootBox()->lineBottom(), lineTop()) - result;
+ LayoutUnit lowestAllowedPosition = max(prevRootBox()->lineBottom(), lineTop()) - result;
result = prevRootBox()->computeOverAnnotationAdjustment(lowestAllowedPosition);
}
@@ -399,7 +409,7 @@ LayoutUnit RootInlineBox::lineSnapAdjustment(LayoutUnit delta) const
// Otherwise we're in the middle of the grid somewhere. Just push to the next line.
LayoutUnit baselineOffset = currentBaselinePosition - firstBaselinePosition;
- LayoutUnit remainder = baselineOffset % gridLineHeight;
+ LayoutUnit remainder = roundToInt(baselineOffset) % roundToInt(gridLineHeight);
LayoutUnit result = delta;
if (remainder)
result += gridLineHeight - remainder;
@@ -535,6 +545,29 @@ LayoutUnit RootInlineBox::selectionTop() const
return prevBottom;
}
+LayoutUnit RootInlineBox::selectionTopAdjustedForPrecedingBlock() const
+{
+ LayoutUnit top = selectionTop();
+
+ RenderObject::SelectionState blockSelectionState = root()->block()->selectionState();
+ if (blockSelectionState != RenderObject::SelectionInside && blockSelectionState != RenderObject::SelectionEnd)
+ return top;
+
+ LayoutSize offsetToBlockBefore;
+ if (RenderBlock* block = root()->block()->blockBeforeWithinSelectionRoot(offsetToBlockBefore)) {
+ if (RootInlineBox* lastLine = block->lastRootBox()) {
+ RenderObject::SelectionState lastLineSelectionState = lastLine->selectionState();
+ if (lastLineSelectionState != RenderObject::SelectionInside && lastLineSelectionState != RenderObject::SelectionStart)
+ return top;
+
+ LayoutUnit lastLineSelectionBottom = lastLine->selectionBottom() + offsetToBlockBefore.height();
+ top = max(top, lastLineSelectionBottom);
+ }
+ }
+
+ return top;
+}
+
LayoutUnit RootInlineBox::selectionBottom() const
{
LayoutUnit selectionBottom = m_lineBottom;
@@ -695,7 +728,7 @@ void RootInlineBox::ascentAndDescentForBox(InlineBox* box, GlyphOverflowAndFallb
// Replaced boxes will return 0 for the line-height if line-box-contain says they are
// not to be included.
if (box->renderer()->isReplaced()) {
- if (renderer()->style(m_firstLine)->lineBoxContain() & LineBoxContainReplaced) {
+ if (renderer()->style(isFirstLineStyle())->lineBoxContain() & LineBoxContainReplaced) {
ascent = box->baselinePosition(baselineType());
descent = box->lineHeight() - ascent;
@@ -720,8 +753,8 @@ void RootInlineBox::ascentAndDescentForBox(InlineBox* box, GlyphOverflowAndFallb
bool setUsedFont = false;
bool setUsedFontWithLeading = false;
- if (usedFonts && !usedFonts->isEmpty() && (includeFont || (box->renderer()->style(m_firstLine)->lineHeight().isNegative() && includeLeading))) {
- usedFonts->append(box->renderer()->style(m_firstLine)->font().primaryFont());
+ if (usedFonts && !usedFonts->isEmpty() && (includeFont || (box->renderer()->style(isFirstLineStyle())->lineHeight().isNegative() && includeLeading))) {
+ 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());
@@ -746,8 +779,8 @@ void RootInlineBox::ascentAndDescentForBox(InlineBox* box, GlyphOverflowAndFallb
// If leading is included for the box, then we compute that box.
if (includeLeading && !setUsedFontWithLeading) {
- int ascentWithLeading = box->baselinePosition(baselineType());
- int descentWithLeading = box->lineHeight() - ascentWithLeading;
+ LayoutUnit ascentWithLeading = box->baselinePosition(baselineType());
+ LayoutUnit 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.
@@ -759,8 +792,8 @@ void RootInlineBox::ascentAndDescentForBox(InlineBox* box, GlyphOverflowAndFallb
}
if (includeFontForBox(box) && !setUsedFont) {
- int fontAscent = box->renderer()->style(m_firstLine)->fontMetrics().ascent();
- int fontDescent = box->renderer()->style(m_firstLine)->fontMetrics().descent();
+ LayoutUnit fontAscent = box->renderer()->style(isFirstLineStyle())->fontMetrics().ascent();
+ LayoutUnit fontDescent = box->renderer()->style(isFirstLineStyle())->fontMetrics().descent();
setAscentAndDescent(ascent, descent, fontAscent, fontDescent, ascentDescentSet);
affectsAscent = fontAscent - box->logicalTop() > 0;
affectsDescent = fontDescent + box->logicalTop() > 0;
@@ -770,13 +803,13 @@ void RootInlineBox::ascentAndDescentForBox(InlineBox* box, GlyphOverflowAndFallb
setAscentAndDescent(ascent, descent, glyphOverflow->top, glyphOverflow->bottom, ascentDescentSet);
affectsAscent = glyphOverflow->top - box->logicalTop() > 0;
affectsDescent = glyphOverflow->bottom + box->logicalTop() > 0;
- glyphOverflow->top = min(glyphOverflow->top, max(0, glyphOverflow->top - box->renderer()->style(m_firstLine)->fontMetrics().ascent()));
- glyphOverflow->bottom = min(glyphOverflow->bottom, max(0, glyphOverflow->bottom - box->renderer()->style(m_firstLine)->fontMetrics().descent()));
+ glyphOverflow->top = min(glyphOverflow->top, max(0, glyphOverflow->top - box->renderer()->style(isFirstLineStyle())->fontMetrics().ascent()));
+ glyphOverflow->bottom = min(glyphOverflow->bottom, max(0, glyphOverflow->bottom - box->renderer()->style(isFirstLineStyle())->fontMetrics().descent()));
}
if (includeMarginForBox(box)) {
- int ascentWithMargin = box->renderer()->style(m_firstLine)->fontMetrics().ascent();
- int descentWithMargin = box->renderer()->style(m_firstLine)->fontMetrics().descent();
+ LayoutUnit ascentWithMargin = box->renderer()->style(isFirstLineStyle())->fontMetrics().ascent();
+ LayoutUnit descentWithMargin = box->renderer()->style(isFirstLineStyle())->fontMetrics().descent();
if (box->parent() && !box->renderer()->isText()) {
ascentWithMargin += box->boxModelObject()->borderBefore() + box->boxModelObject()->paddingBefore() + box->boxModelObject()->marginBefore();
descentWithMargin += box->boxModelObject()->borderAfter() + box->boxModelObject()->paddingAfter() + box->boxModelObject()->marginAfter();
@@ -800,7 +833,7 @@ LayoutUnit RootInlineBox::verticalPositionForBox(InlineBox* box, VerticalPositio
return 0;
// This method determines the vertical position for inline elements.
- bool firstLine = m_firstLine;
+ bool firstLine = isFirstLineStyle();
if (firstLine && !renderer->document()->usesFirstLineRules())
firstLine = false;
@@ -812,7 +845,7 @@ LayoutUnit RootInlineBox::verticalPositionForBox(InlineBox* box, VerticalPositio
return verticalPosition;
}
- int verticalPosition = 0;
+ LayoutUnit verticalPosition = 0;
EVerticalAlign verticalAlign = renderer->style()->verticalAlign();
if (verticalAlign == TOP || verticalAlign == BOTTOM)
return 0;
@@ -844,7 +877,7 @@ LayoutUnit RootInlineBox::verticalPositionForBox(InlineBox* box, VerticalPositio
} else if (verticalAlign == BASELINE_MIDDLE)
verticalPosition += -renderer->lineHeight(firstLine, lineDirection) / 2 + renderer->baselinePosition(baselineType(), firstLine, lineDirection);
else if (verticalAlign == LENGTH)
- verticalPosition -= renderer->style()->verticalAlignLength().calcValue(renderer->lineHeight(firstLine, lineDirection));
+ verticalPosition -= valueForLength(renderer->style()->verticalAlignLength(), renderer->lineHeight(firstLine, lineDirection), renderer->view());
}
// Store the cached value.
diff --git a/Source/WebCore/rendering/RootInlineBox.h b/Source/WebCore/rendering/RootInlineBox.h
index 901bcff24..49aed00da 100644
--- a/Source/WebCore/rendering/RootInlineBox.h
+++ b/Source/WebCore/rendering/RootInlineBox.h
@@ -63,6 +63,9 @@ public:
LayoutUnit selectionBottom() const;
LayoutUnit selectionHeight() const { return max<LayoutUnit>(0, selectionBottom() - selectionTop()); }
+ LayoutUnit selectionTopAdjustedForPrecedingBlock() const;
+ LayoutUnit selectionHeightAdjustedForPrecedingBlock() const { return max<LayoutUnit>(0, selectionBottom() - selectionTopAdjustedForPrecedingBlock()); }
+
int blockDirectionPointInLine() const { return max(lineTop(), selectionTop()); }
LayoutUnit alignBoxesInBlockDirection(LayoutUnit heightOfBlock, GlyphOverflowAndFallbackFontsMap&, VerticalPositionCache&);
@@ -83,8 +86,8 @@ public:
unsigned lineBreakPos() const { return m_lineBreakPos; }
void setLineBreakPos(unsigned p) { m_lineBreakPos = p; }
- bool endsWithBreak() const { return m_endsWithBreak; }
- void setEndsWithBreak(bool b) { m_endsWithBreak = b; }
+ using InlineBox::endsWithBreak;
+ using InlineBox::setEndsWithBreak;
void childRemoved(InlineBox* box);
@@ -92,7 +95,7 @@ public:
void placeEllipsis(const AtomicString& ellipsisStr, bool ltr, float blockLeftEdge, float blockRightEdge, float ellipsisWidth, InlineBox* markupBox = 0);
virtual float placeEllipsisBox(bool ltr, float blockLeftEdge, float blockRightEdge, float ellipsisWidth, bool& foundBox);
- bool hasEllipsisBox() const { return m_hasEllipsisBoxOrHyphen; }
+ using InlineBox::hasEllipsisBox;
EllipsisBox* ellipsisBox() const;
void paintEllipsisBox(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom) const;
@@ -101,8 +104,8 @@ public:
bool isHyphenated() const;
- virtual LayoutUnit baselinePosition(FontBaseline baselineType) const { return boxModelObject()->baselinePosition(baselineType, m_firstLine, isHorizontal() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes); }
- virtual LayoutUnit lineHeight() const { return boxModelObject()->lineHeight(m_firstLine, isHorizontal() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes); }
+ virtual LayoutUnit baselinePosition(FontBaseline baselineType) const;
+ virtual LayoutUnit lineHeight() const;
#if PLATFORM(MAC)
void addHighlightOverflow();
@@ -112,8 +115,8 @@ public:
virtual void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom);
virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const LayoutPoint& pointInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom);
- bool hasSelectedChildren() const { return m_hasSelectedChildrenOrCanHaveLeadingExpansion; }
- void setHasSelectedChildren(bool hasSelectedChildren) { m_hasSelectedChildrenOrCanHaveLeadingExpansion = hasSelectedChildren; }
+ using InlineBox::hasSelectedChildren;
+ using InlineBox::setHasSelectedChildren;
virtual RenderObject::SelectionState selectionState();
InlineBox* firstSelectedBox();
@@ -181,11 +184,10 @@ public:
virtual const char* boxName() const;
#endif
private:
- void setHasEllipsisBox(bool hasEllipsisBox) { m_hasEllipsisBoxOrHyphen = hasEllipsisBox; }
-
+
LayoutUnit lineSnapAdjustment(LayoutUnit delta = 0) const;
- int beforeAnnotationsAdjustment() const;
+ LayoutUnit beforeAnnotationsAdjustment() const;
// This folds into the padding at the end of InlineFlowBox on 64-bit.
unsigned m_lineBreakPos;
diff --git a/Source/WebCore/rendering/mathml/RenderMathMLBlock.cpp b/Source/WebCore/rendering/mathml/RenderMathMLBlock.cpp
index 167eeb21a..d944eda2f 100644
--- a/Source/WebCore/rendering/mathml/RenderMathMLBlock.cpp
+++ b/Source/WebCore/rendering/mathml/RenderMathMLBlock.cpp
@@ -29,18 +29,24 @@
#include "RenderMathMLBlock.h"
-#include "FontSelector.h"
#include "GraphicsContext.h"
#include "MathMLNames.h"
-#include "RenderInline.h"
-#include "RenderText.h"
+
+#if ENABLE(DEBUG_MATH_LAYOUT)
+#include "PaintInfo.h"
+#endif
namespace WebCore {
using namespace MathMLNames;
RenderMathMLBlock::RenderMathMLBlock(Node* container)
- : RenderBlock(container)
+ : RenderBlock(container)
+ , m_intrinsicPaddingBefore(0)
+ , m_intrinsicPaddingAfter(0)
+ , m_intrinsicPaddingStart(0)
+ , m_intrinsicPaddingEnd(0)
+ , m_preferredLogicalHeight(preferredLogicalHeightUnset)
{
}
@@ -49,21 +55,145 @@ bool RenderMathMLBlock::isChildAllowed(RenderObject* child, RenderStyle*) const
return child->node() && child->node()->nodeType() == Node::ELEMENT_NODE;
}
-PassRefPtr<RenderStyle> RenderMathMLBlock::createBlockStyle()
+LayoutUnit RenderMathMLBlock::paddingTop() const
+{
+ LayoutUnit result = computedCSSPaddingTop();
+ switch (style()->writingMode()) {
+ case TopToBottomWritingMode:
+ return result + m_intrinsicPaddingBefore;
+ case BottomToTopWritingMode:
+ return result + m_intrinsicPaddingAfter;
+ case LeftToRightWritingMode:
+ case RightToLeftWritingMode:
+ return result + (style()->isLeftToRightDirection() ? m_intrinsicPaddingStart : m_intrinsicPaddingEnd);
+ }
+ ASSERT_NOT_REACHED();
+ return result;
+}
+
+LayoutUnit RenderMathMLBlock::paddingBottom() const
{
- RefPtr<RenderStyle> newStyle = RenderStyle::create();
- newStyle->inheritFrom(style());
- newStyle->setDisplay(BLOCK);
- return newStyle;
+ LayoutUnit result = computedCSSPaddingBottom();
+ switch (style()->writingMode()) {
+ case TopToBottomWritingMode:
+ return result + m_intrinsicPaddingAfter;
+ case BottomToTopWritingMode:
+ return result + m_intrinsicPaddingBefore;
+ case LeftToRightWritingMode:
+ case RightToLeftWritingMode:
+ return result + (style()->isLeftToRightDirection() ? m_intrinsicPaddingEnd : m_intrinsicPaddingStart);
+ }
+ ASSERT_NOT_REACHED();
+ return result;
+}
+
+LayoutUnit RenderMathMLBlock::paddingLeft() const
+{
+ LayoutUnit result = computedCSSPaddingLeft();
+ switch (style()->writingMode()) {
+ case LeftToRightWritingMode:
+ return result + m_intrinsicPaddingBefore;
+ case RightToLeftWritingMode:
+ return result + m_intrinsicPaddingAfter;
+ case TopToBottomWritingMode:
+ case BottomToTopWritingMode:
+ return result + (style()->isLeftToRightDirection() ? m_intrinsicPaddingStart : m_intrinsicPaddingEnd);
+ }
+ ASSERT_NOT_REACHED();
+ return result;
+}
+
+LayoutUnit RenderMathMLBlock::paddingRight() const
+{
+ LayoutUnit result = computedCSSPaddingRight();
+ switch (style()->writingMode()) {
+ case RightToLeftWritingMode:
+ return result + m_intrinsicPaddingBefore;
+ case LeftToRightWritingMode:
+ return result + m_intrinsicPaddingAfter;
+ case TopToBottomWritingMode:
+ case BottomToTopWritingMode:
+ return result + (style()->isLeftToRightDirection() ? m_intrinsicPaddingEnd : m_intrinsicPaddingStart);
+ }
+ ASSERT_NOT_REACHED();
+ return result;
+}
+
+LayoutUnit RenderMathMLBlock::paddingBefore() const
+{
+ return computedCSSPaddingBefore() + m_intrinsicPaddingBefore;
+}
+
+LayoutUnit RenderMathMLBlock::paddingAfter() const
+{
+ return computedCSSPaddingAfter() + m_intrinsicPaddingAfter;
+}
+
+LayoutUnit RenderMathMLBlock::paddingStart() const
+{
+ return computedCSSPaddingStart() + m_intrinsicPaddingStart;
+}
+
+LayoutUnit RenderMathMLBlock::paddingEnd() const
+{
+ return computedCSSPaddingEnd() + m_intrinsicPaddingEnd;
+}
+
+void RenderMathMLBlock::computePreferredLogicalWidths()
+{
+ ASSERT(preferredLogicalWidthsDirty());
+ m_preferredLogicalHeight = preferredLogicalHeightUnset;
+ RenderBlock::computePreferredLogicalWidths();
+}
+
+RenderMathMLBlock* RenderMathMLBlock::createAlmostAnonymousBlock(EDisplay display)
+{
+ RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(style(), display);
+ RenderMathMLBlock* newBlock = new (renderArena()) RenderMathMLBlock(node() /* "almost" anonymous block */);
+ newBlock->setStyle(newStyle.release());
+ return newBlock;
+}
+
+// An arbitrary large value, like RenderBlock.cpp BLOCK_MAX_WIDTH or FixedTableLayout.cpp TABLE_MAX_WIDTH.
+static const int cLargeLogicalWidth = 15000;
+
+void RenderMathMLBlock::computeChildrenPreferredLogicalHeights()
+{
+ ASSERT(needsLayout());
+
+ // Ensure a full repaint will happen after layout finishes.
+ setNeedsLayout(true, MarkOnlyThis);
+
+ LayoutUnit oldAvailableLogicalWidth = availableLogicalWidth();
+ setLogicalWidth(cLargeLogicalWidth);
+
+ for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
+ if (!child->isBox())
+ continue;
+
+ // Because our width changed, |child| may need layout.
+ if (child->maxPreferredLogicalWidth() > oldAvailableLogicalWidth)
+ child->setNeedsLayout(true, MarkOnlyThis);
+
+ RenderMathMLBlock* childMathMLBlock = child->isRenderMathMLBlock() ? toRenderMathMLBlock(child) : 0;
+ if (childMathMLBlock && !childMathMLBlock->isPreferredLogicalHeightDirty())
+ continue;
+ // Layout our child to compute its preferred logical height.
+ child->layoutIfNeeded();
+ if (childMathMLBlock)
+ childMathMLBlock->setPreferredLogicalHeight(childMathMLBlock->logicalHeight());
+ }
}
-void RenderMathMLBlock::stretchToHeight(int height)
+LayoutUnit RenderMathMLBlock::preferredLogicalHeightAfterSizing(RenderObject* child)
{
- for (RenderObject* current = firstChild(); current; current = current->nextSibling())
- if (current->isRenderMathMLBlock()) {
- RenderMathMLBlock* block = toRenderMathMLBlock(current);
- block->stretchToHeight(height);
- }
+ if (child->isRenderMathMLBlock())
+ return toRenderMathMLBlock(child)->preferredLogicalHeight();
+ if (child->isBox()) {
+ ASSERT(!child->needsLayout());
+ return toRenderBox(child)->logicalHeight();
+ }
+ return child->style()->fontSize();
}
#if ENABLE(DEBUG_MATH_LAYOUT)
@@ -82,22 +212,22 @@ void RenderMathMLBlock::paint(PaintInfo& info, const LayoutPoint& paintOffset)
info.context->setStrokeStyle(SolidStroke);
info.context->setStrokeColor(Color(0, 0, 255), ColorSpaceSRGB);
- info.context->drawLine(adjustedPaintOffset, LayoutPoint(adjustedPaintOffset.x() + offsetWidth(), adjustedPaintOffset.y()));
- info.context->drawLine(LayoutPoint(adjustedPaintOffset.x() + offsetWidth(), adjustedPaintOffset.y()), LayoutPoint(adjustedPaintOffset.x() + offsetWidth(), adjustedPaintOffset.y() + offsetHeight()));
- info.context->drawLine(LayoutPoint(adjustedPaintOffset.x(), adjustedPaintOffset.y() + offsetHeight()), LayoutPoint(adjustedPaintOffset.x() + offsetWidth(), adjustedPaintOffset.y() + offsetHeight()));
- info.context->drawLine(adjustedPaintOffset, LayoutPoint(adjustedPaintOffset.x(), adjustedPaintOffset.y() + offsetHeight()));
+ info.context->drawLine(adjustedPaintOffset, IntPoint(adjustedPaintOffset.x() + pixelSnappedOffsetWidth(), adjustedPaintOffset.y()));
+ info.context->drawLine(IntPoint(adjustedPaintOffset.x() + pixelSnappedOffsetWidth(), adjustedPaintOffset.y()), IntPoint(adjustedPaintOffset.x() + pixelSnappedOffsetWidth(), adjustedPaintOffset.y() + pixelSnappedOffsetHeight()));
+ info.context->drawLine(IntPoint(adjustedPaintOffset.x(), adjustedPaintOffset.y() + pixelSnappedOffsetHeight()), IntPoint(adjustedPaintOffset.x() + pixelSnappedOffsetWidth(), adjustedPaintOffset.y() + pixelSnappedOffsetHeight()));
+ info.context->drawLine(adjustedPaintOffset, IntPoint(adjustedPaintOffset.x(), adjustedPaintOffset.y() + pixelSnappedOffsetHeight()));
int topStart = paddingTop();
info.context->setStrokeColor(Color(0, 255, 0), ColorSpaceSRGB);
- info.context->drawLine(LayoutPoint(adjustedPaintOffset.x(), adjustedPaintOffset.y() + topStart), LayoutPoint(adjustedPaintOffset.x() + offsetWidth(), adjustedPaintOffset.y() + topStart));
+ info.context->drawLine(IntPoint(adjustedPaintOffset.x(), adjustedPaintOffset.y() + topStart), IntPoint(adjustedPaintOffset.x() + pixelSnappedOffsetWidth(), adjustedPaintOffset.y() + topStart));
- int baseline = baselinePosition(AlphabeticBaseline, true, HorizontalLine);
+ int baseline = roundToInt(baselinePosition(AlphabeticBaseline, true, HorizontalLine));
info.context->setStrokeColor(Color(255, 0, 0), ColorSpaceSRGB);
- info.context->drawLine(LayoutPoint(adjustedPaintOffset.x(), adjustedPaintOffset.y() + baseline), LayoutPoint(adjustedPaintOffset.x() + offsetWidth(), adjustedPaintOffset.y() + baseline));
+ info.context->drawLine(IntPoint(adjustedPaintOffset.x(), adjustedPaintOffset.y() + baseline), IntPoint(adjustedPaintOffset.x() + pixelSnappedOffsetWidth(), adjustedPaintOffset.y() + baseline));
}
#endif // ENABLE(DEBUG_MATH_LAYOUT)
diff --git a/Source/WebCore/rendering/mathml/RenderMathMLBlock.h b/Source/WebCore/rendering/mathml/RenderMathMLBlock.h
index 5d4d780ed..634d0a6dc 100644
--- a/Source/WebCore/rendering/mathml/RenderMathMLBlock.h
+++ b/Source/WebCore/rendering/mathml/RenderMathMLBlock.h
@@ -54,12 +54,35 @@ public:
// FIXME: We don't yet handle all the cases in the MathML spec. See
// https://bugs.webkit.org/show_bug.cgi?id=78617.
virtual RenderMathMLOperator* unembellishedOperator() { return 0; }
- virtual void stretchToHeight(int height);
+ virtual LayoutUnit paddingTop() const OVERRIDE;
+ virtual LayoutUnit paddingBottom() const OVERRIDE;
+ virtual LayoutUnit paddingLeft() const OVERRIDE;
+ virtual LayoutUnit paddingRight() const OVERRIDE;
+ virtual LayoutUnit paddingBefore() const OVERRIDE;
+ virtual LayoutUnit paddingAfter() const OVERRIDE;
+ virtual LayoutUnit paddingStart() const OVERRIDE;
+ virtual LayoutUnit paddingEnd() const OVERRIDE;
+
+ // A MathML element's preferred logical widths often depend on its children's preferred heights, not just their widths.
+ // This is due to operator stretching and other layout fine tuning. We define an element's preferred height to be its
+ // actual height after layout inside a very wide parent.
+ bool isPreferredLogicalHeightDirty() const { return preferredLogicalWidthsDirty() || m_preferredLogicalHeight < 0; }
+ // The caller must ensure !isPreferredLogicalHeightDirty().
+ LayoutUnit preferredLogicalHeight() const { ASSERT(!isPreferredLogicalHeightDirty()); return m_preferredLogicalHeight; }
+ static const int preferredLogicalHeightUnset = -1;
+ void setPreferredLogicalHeight(LayoutUnit logicalHeight) { m_preferredLogicalHeight = logicalHeight; }
+ // computePreferredLogicalWidths() in derived classes must ensure m_preferredLogicalHeight is set to < 0 or its correct value.
+ virtual void computePreferredLogicalWidths() OVERRIDE;
+
#if ENABLE(DEBUG_MATH_LAYOUT)
virtual void paint(PaintInfo&, const LayoutPoint&);
#endif
+ // Create a new RenderBlock, with a new style inheriting from this->style().
+ // FIXME: Create a true anonymous block, like RenderBlock::createAnonymousBlock().
+ RenderMathMLBlock* createAlmostAnonymousBlock(EDisplay = BLOCK);
+
protected:
static LayoutUnit getBoxModelObjectHeight(const RenderObject* object)
{
@@ -79,10 +102,23 @@ protected:
return 0;
}
- virtual PassRefPtr<RenderStyle> createBlockStyle();
private:
virtual const char* renderName() const { return isAnonymous() ? "RenderMathMLBlock (anonymous)" : "RenderMathMLBlock"; }
+
+protected:
+ // Set our logical width to a large value, and compute our children's preferred logical heights.
+ void computeChildrenPreferredLogicalHeights();
+ // This can only be called after children have been sized by computeChildrenPreferredLogicalHeights().
+ static LayoutUnit preferredLogicalHeightAfterSizing(RenderObject* child);
+
+ int m_intrinsicPaddingBefore;
+ int m_intrinsicPaddingAfter;
+ int m_intrinsicPaddingStart;
+ int m_intrinsicPaddingEnd;
+
+ // m_preferredLogicalHeight is dirty if it's < 0 or preferredLogicalWidthsDirty().
+ LayoutUnit m_preferredLogicalHeight;
};
inline RenderMathMLBlock* toRenderMathMLBlock(RenderObject* object)
diff --git a/Source/WebCore/rendering/mathml/RenderMathMLFenced.cpp b/Source/WebCore/rendering/mathml/RenderMathMLFenced.cpp
index c2f67ea93..4297dd7ff 100644
--- a/Source/WebCore/rendering/mathml/RenderMathMLFenced.cpp
+++ b/Source/WebCore/rendering/mathml/RenderMathMLFenced.cpp
@@ -131,11 +131,7 @@ void RenderMathMLFenced::addChild(RenderObject* child, RenderObject*)
if (child->isBlockFlow() && child->style()->display() != INLINE_BLOCK) {
// Block objects wrapper.
- RenderBlock* block = new (renderArena()) RenderBlock(node());
- RefPtr<RenderStyle> newStyle = RenderStyle::create();
- newStyle->inheritFrom(style());
- newStyle->setDisplay(INLINE_BLOCK);
- block->setStyle(newStyle.release());
+ RenderBlock* block = createAlmostAnonymousBlock(INLINE_BLOCK);
RenderBlock::addChild(block, lastChild());
block->addChild(child);
diff --git a/Source/WebCore/rendering/mathml/RenderMathMLFraction.cpp b/Source/WebCore/rendering/mathml/RenderMathMLFraction.cpp
index dd59bb998..296548a2e 100644
--- a/Source/WebCore/rendering/mathml/RenderMathMLFraction.cpp
+++ b/Source/WebCore/rendering/mathml/RenderMathMLFraction.cpp
@@ -61,26 +61,26 @@ void RenderMathMLFraction::updateFromElement()
Element* fraction = static_cast<Element*>(node());
- RenderObject* numerator = firstChild();
+ RenderObject* numeratorWrapper = firstChild();
String nalign = fraction->getAttribute(MathMLNames::numalignAttr);
if (equalIgnoringCase(nalign, "left"))
- numerator->style()->setTextAlign(LEFT);
+ numeratorWrapper->style()->setTextAlign(LEFT);
else if (equalIgnoringCase(nalign, "right"))
- numerator->style()->setTextAlign(RIGHT);
+ numeratorWrapper->style()->setTextAlign(RIGHT);
else
- numerator->style()->setTextAlign(CENTER);
+ numeratorWrapper->style()->setTextAlign(CENTER);
- RenderObject* denominator = numerator->nextSibling();
- if (!denominator)
+ RenderObject* denominatorWrapper = numeratorWrapper->nextSibling();
+ if (!denominatorWrapper)
return;
String dalign = fraction->getAttribute(MathMLNames::denomalignAttr);
if (equalIgnoringCase(dalign, "left"))
- denominator->style()->setTextAlign(LEFT);
+ denominatorWrapper->style()->setTextAlign(LEFT);
else if (equalIgnoringCase(dalign, "right"))
- denominator->style()->setTextAlign(RIGHT);
+ denominatorWrapper->style()->setTextAlign(RIGHT);
else
- denominator->style()->setTextAlign(CENTER);
+ denominatorWrapper->style()->setTextAlign(CENTER);
// FIXME: parse units
String thickness = fraction->getAttribute(MathMLNames::linethicknessAttr);
@@ -100,20 +100,18 @@ void RenderMathMLFraction::updateFromElement()
void RenderMathMLFraction::addChild(RenderObject* child, RenderObject* beforeChild)
{
- RenderBlock* row = new (renderArena()) RenderMathMLBlock(node());
- RefPtr<RenderStyle> rowStyle = createBlockStyle();
+ RenderBlock* row = createAlmostAnonymousBlock();
- rowStyle->setTextAlign(CENTER);
- Length pad(static_cast<int>(rowStyle->fontSize() * gHorizontalPad), Fixed);
- rowStyle->setPaddingLeft(pad);
- rowStyle->setPaddingRight(pad);
+ row->style()->setTextAlign(CENTER);
+ Length pad(static_cast<int>(style()->fontSize() * gHorizontalPad), Fixed);
+ row->style()->setPaddingLeft(pad);
+ row->style()->setPaddingRight(pad);
// Only add padding for rows as denominators
bool isNumerator = isEmpty();
if (!isNumerator)
- rowStyle->setPaddingTop(Length(2, Fixed));
+ row->style()->setPaddingTop(Length(2, Fixed));
- row->setStyle(rowStyle.release());
RenderBlock::addChild(row, beforeChild);
row->addChild(child);
updateFromElement();
@@ -139,7 +137,6 @@ void RenderMathMLFraction::layout()
m_lineThickness *= ceilf(gFractionBarWidth * style()->fontSize());
RenderBlock::layout();
-
}
void RenderMathMLFraction::paint(PaintInfo& info, const LayoutPoint& paintOffset)
@@ -151,17 +148,18 @@ void RenderMathMLFraction::paint(PaintInfo& info, const LayoutPoint& paintOffset
if (!firstChild() ||!m_lineThickness)
return;
- LayoutUnit verticalOffset = 0;
+ int verticalOffset = 0;
// The children are always RenderMathMLBlock instances
if (firstChild()->isRenderMathMLBlock()) {
int adjustForThickness = m_lineThickness > 1 ? int(m_lineThickness / 2) : 1;
if (int(m_lineThickness) % 2 == 1)
adjustForThickness++;
+ // FIXME: This is numeratorWrapper, not numerator.
RenderMathMLBlock* numerator = toRenderMathMLBlock(firstChild());
if (numerator->isRenderMathMLRow())
- verticalOffset = numerator->offsetHeight() + adjustForThickness;
+ verticalOffset = numerator->pixelSnappedOffsetHeight() + adjustForThickness;
else
- verticalOffset = numerator->offsetHeight();
+ verticalOffset = numerator->pixelSnappedOffsetHeight();
}
IntPoint adjustedPaintOffset = roundedIntPoint(paintOffset + location());
@@ -173,20 +171,20 @@ void RenderMathMLFraction::paint(PaintInfo& info, const LayoutPoint& paintOffset
info.context->setStrokeStyle(SolidStroke);
info.context->setStrokeColor(style()->visitedDependentColor(CSSPropertyColor), ColorSpaceSRGB);
- info.context->drawLine(adjustedPaintOffset, IntPoint(adjustedPaintOffset.x() + offsetWidth(), adjustedPaintOffset.y()));
+ info.context->drawLine(adjustedPaintOffset, IntPoint(adjustedPaintOffset.x() + pixelSnappedOffsetWidth(), adjustedPaintOffset.y()));
}
LayoutUnit RenderMathMLFraction::baselinePosition(FontBaseline, bool firstLine, LineDirectionMode lineDirection, LinePositionMode linePositionMode) const
{
if (firstChild() && firstChild()->isRenderMathMLBlock()) {
- RenderMathMLBlock* numerator = toRenderMathMLBlock(firstChild());
+ RenderMathMLBlock* numeratorWrapper = toRenderMathMLBlock(firstChild());
RenderStyle* refStyle = style();
if (previousSibling())
refStyle = previousSibling()->style();
else if (nextSibling())
refStyle = nextSibling()->style();
int shift = int(ceil((refStyle->fontMetrics().xHeight() + 1) / 2));
- return numerator->offsetHeight() + shift;
+ return numeratorWrapper->pixelSnappedOffsetHeight() + shift;
}
return RenderBlock::baselinePosition(AlphabeticBaseline, firstLine, lineDirection, linePositionMode);
}
diff --git a/Source/WebCore/rendering/mathml/RenderMathMLOperator.cpp b/Source/WebCore/rendering/mathml/RenderMathMLOperator.cpp
index ad11d8bac..50f02be59 100644
--- a/Source/WebCore/rendering/mathml/RenderMathMLOperator.cpp
+++ b/Source/WebCore/rendering/mathml/RenderMathMLOperator.cpp
@@ -62,20 +62,23 @@ static const float gOperatorExpansion = 1.2f;
void RenderMathMLOperator::stretchToHeight(int height)
{
- if (height == m_stretchHeight)
+ height *= gOperatorExpansion;
+ if (m_stretchHeight == height)
return;
- m_stretchHeight = static_cast<int>(height * gOperatorExpansion);
+ m_stretchHeight = height;
- updateBoxModelInfoFromStyle();
- setNeedsLayout(true);
+ updateFromElement();
}
-void RenderMathMLOperator::layout()
+void RenderMathMLOperator::computePreferredLogicalWidths()
{
- // FIXME: This probably shouldn't be called here but when the operator
- // isn't stretched (e.g. outside of a mrow), it needs to be called somehow
- updateFromElement();
- RenderBlock::layout();
+ ASSERT(preferredLogicalWidthsDirty());
+
+ // Check for an uninitialized operator.
+ if (!firstChild())
+ updateFromElement();
+
+ RenderMathMLBlock::computePreferredLogicalWidths();
}
// This is a table of stretchy characters.
@@ -113,6 +116,12 @@ static struct StretchyCharacter {
// All of these settings are represented in the constants below.
// FIXME: use fractions of style()->fontSize() for proper zooming/resizing.
+// FIXME: None of this should be hard-coded. Not only does this cause problems
+// with zooming, but it also sets up assumptions that break when a font contains
+// a glyph that is smaller than expected. For example, the STIX vertical bar
+// glyph is smaller than expected, and glyphHeightForCharacter() and
+// lineHeightForCharacter() were added to make smaller glyphs work in this system.
+// Really, the system should just be reconsidered.
static const int gGlyphFontSize = 14;
static const int gGlyphLineHeight = 11;
static const int gMinimumStretchHeight = 24;
@@ -122,6 +131,25 @@ static const int gMiddleGlyphTopAdjust = -1;
static const int gBottomGlyphTopAdjust = -3;
static const float gMinimumRatioForStretch = 0.10f;
+// This should always be called instead of accessing gGlyphHeight directly.
+int RenderMathMLOperator::glyphHeightForCharacter(UChar character)
+{
+ GlyphData data = style()->font().glyphDataForCharacter(character, false);
+ FloatRect glyphBounds = data.fontData->boundsForGlyph(data.glyph);
+ if (glyphBounds.height() && glyphBounds.height() < gGlyphHeight)
+ return glyphBounds.height();
+ return gGlyphHeight;
+}
+
+// This should always be called instead of accessing gGlyphLineHeight directly.
+int RenderMathMLOperator::lineHeightForCharacter(UChar character)
+{
+ int glyphHeight = glyphHeightForCharacter(character);
+ if (glyphHeight < gGlyphHeight)
+ return (glyphHeight - 1) > 0 ? glyphHeight - 1 : 1;
+ return gGlyphLineHeight;
+}
+
void RenderMathMLOperator::updateFromElement()
{
RenderObject* savedRenderer = node()->renderer();
@@ -190,12 +218,12 @@ void RenderMathMLOperator::updateFromElement()
// font size to adjust the glyph size.
int currentFontSize = style()->fontSize();
if (!stretchDisabled && isStretchy && m_stretchHeight > 0 && m_stretchHeight <= gMinimumStretchHeight && m_stretchHeight > currentFontSize) {
- FontDescription desc;
+ FontDescription desc = style()->fontDescription();
desc.setIsAbsoluteSize(true);
desc.setSpecifiedSize(m_stretchHeight);
desc.setComputedSize(m_stretchHeight);
newStyle->setFontDescription(desc);
- newStyle->font().update(newStyle->font().fontSelector());
+ newStyle->font().update(style()->font().fontSelector());
}
container->setStyle(newStyle.release());
@@ -218,87 +246,96 @@ void RenderMathMLOperator::updateFromElement()
} else {
// Build stretchable characters as a stack of glyphs.
m_isStacked = true;
+
+ int extensionGlyphLineHeight = lineHeightForCharacter(stretchyCharacters[index].extensionGlyph);
+ int topGlyphLineHeight = lineHeightForCharacter(stretchyCharacters[index].topGlyph);
+ int bottomGlyphLineHeight = lineHeightForCharacter(stretchyCharacters[index].bottomGlyph);
if (stretchyCharacters[index].middleGlyph) {
// We have a middle glyph (e.g. a curly bracket) that requires special processing.
- int half = (m_stretchHeight - gGlyphHeight) / 2;
- if (half <= gGlyphHeight) {
+ int glyphHeight = glyphHeightForCharacter(stretchyCharacters[index].middleGlyph);
+ int middleGlyphLineHeight = lineHeightForCharacter(stretchyCharacters[index].middleGlyph);
+ int half = (m_stretchHeight - glyphHeight) / 2;
+ if (half <= glyphHeight) {
// We only have enough space for a single middle glyph.
- createGlyph(stretchyCharacters[index].topGlyph, half, gTopGlyphTopAdjust);
- createGlyph(stretchyCharacters[index].middleGlyph, gGlyphHeight, gMiddleGlyphTopAdjust);
- createGlyph(stretchyCharacters[index].bottomGlyph, 0, gBottomGlyphTopAdjust);
+ createGlyph(stretchyCharacters[index].topGlyph, topGlyphLineHeight, half, gTopGlyphTopAdjust);
+ createGlyph(stretchyCharacters[index].middleGlyph, middleGlyphLineHeight, glyphHeight, gMiddleGlyphTopAdjust);
+ createGlyph(stretchyCharacters[index].bottomGlyph, bottomGlyphLineHeight, 0, gBottomGlyphTopAdjust);
} else {
// We have to extend both the top and bottom to the middle.
- createGlyph(stretchyCharacters[index].topGlyph, gGlyphHeight, gTopGlyphTopAdjust);
- int remaining = half - gGlyphHeight;
+ createGlyph(stretchyCharacters[index].topGlyph, topGlyphLineHeight, glyphHeight, gTopGlyphTopAdjust);
+ int remaining = half - glyphHeight;
while (remaining > 0) {
- if (remaining < gGlyphHeight) {
- createGlyph(stretchyCharacters[index].extensionGlyph, remaining);
+ if (remaining < glyphHeight) {
+ createGlyph(stretchyCharacters[index].extensionGlyph, extensionGlyphLineHeight, remaining);
remaining = 0;
} else {
- createGlyph(stretchyCharacters[index].extensionGlyph, gGlyphHeight);
- remaining -= gGlyphHeight;
+ createGlyph(stretchyCharacters[index].extensionGlyph, extensionGlyphLineHeight, glyphHeight);
+ remaining -= glyphHeight;
}
}
// The middle glyph in the stack.
- createGlyph(stretchyCharacters[index].middleGlyph, gGlyphHeight, gMiddleGlyphTopAdjust);
+ createGlyph(stretchyCharacters[index].middleGlyph, middleGlyphLineHeight, glyphHeight, gMiddleGlyphTopAdjust);
// The remaining is the top half minus the middle glyph height.
- remaining = half - gGlyphHeight;
+ remaining = half - glyphHeight;
// We need to make sure we have the full height in case the height is odd.
if (m_stretchHeight % 2 == 1)
remaining++;
// Extend to the bottom glyph.
while (remaining > 0) {
- if (remaining < gGlyphHeight) {
- createGlyph(stretchyCharacters[index].extensionGlyph, remaining);
+ if (remaining < glyphHeight) {
+ createGlyph(stretchyCharacters[index].extensionGlyph, extensionGlyphLineHeight, remaining);
remaining = 0;
} else {
- createGlyph(stretchyCharacters[index].extensionGlyph, gGlyphHeight);
- remaining -= gGlyphHeight;
+ createGlyph(stretchyCharacters[index].extensionGlyph, extensionGlyphLineHeight, glyphHeight);
+ remaining -= glyphHeight;
}
}
// The bottom glyph in the stack.
- createGlyph(stretchyCharacters[index].bottomGlyph, 0, gBottomGlyphTopAdjust);
+ createGlyph(stretchyCharacters[index].bottomGlyph, bottomGlyphLineHeight, 0, gBottomGlyphTopAdjust);
}
} else {
// We do not have a middle glyph and so we just extend from the top to the bottom glyph.
- int remaining = m_stretchHeight - 2 * gGlyphHeight;
- createGlyph(stretchyCharacters[index].topGlyph, gGlyphHeight, gTopGlyphTopAdjust);
+ int glyphHeight = glyphHeightForCharacter(stretchyCharacters[index].extensionGlyph);
+ int remaining = m_stretchHeight - 2 * glyphHeight;
+ createGlyph(stretchyCharacters[index].topGlyph, topGlyphLineHeight, glyphHeight, gTopGlyphTopAdjust);
while (remaining > 0) {
- if (remaining < gGlyphHeight) {
- createGlyph(stretchyCharacters[index].extensionGlyph, remaining);
+ if (remaining < glyphHeight) {
+ createGlyph(stretchyCharacters[index].extensionGlyph, extensionGlyphLineHeight, remaining);
remaining = 0;
} else {
- createGlyph(stretchyCharacters[index].extensionGlyph, gGlyphHeight);
- remaining -= gGlyphHeight;
+ createGlyph(stretchyCharacters[index].extensionGlyph, extensionGlyphLineHeight, glyphHeight);
+ remaining -= glyphHeight;
}
}
- createGlyph(stretchyCharacters[index].bottomGlyph, 0, gBottomGlyphTopAdjust);
+ createGlyph(stretchyCharacters[index].bottomGlyph, bottomGlyphLineHeight, 0, gBottomGlyphTopAdjust);
}
}
+
+ setNeedsLayoutAndPrefWidthsRecalc();
}
-PassRefPtr<RenderStyle> RenderMathMLOperator::createStackableStyle(int size, int topRelative)
+PassRefPtr<RenderStyle> RenderMathMLOperator::createStackableStyle(int lineHeight, int maxHeightForRenderer, int topRelative)
{
RefPtr<RenderStyle> newStyle = RenderStyle::create();
newStyle->inheritFrom(style());
newStyle->setDisplay(BLOCK);
- FontDescription desc;
+ FontDescription desc = style()->fontDescription();
desc.setIsAbsoluteSize(true);
desc.setSpecifiedSize(gGlyphFontSize);
desc.setComputedSize(gGlyphFontSize);
newStyle->setFontDescription(desc);
- newStyle->font().update(newStyle->font().fontSelector());
- newStyle->setLineHeight(Length(gGlyphLineHeight, Fixed));
+ newStyle->font().update(style()->font().fontSelector());
+ newStyle->setLineHeight(Length(lineHeight, Fixed));
newStyle->setVerticalAlign(TOP);
- if (size > 0)
- newStyle->setMaxHeight(Length(size, Fixed));
+ if (maxHeightForRenderer > 0)
+ newStyle->setMaxHeight(Length(maxHeightForRenderer, Fixed));
newStyle->setOverflowY(OHIDDEN);
newStyle->setOverflowX(OHIDDEN);
@@ -310,10 +347,10 @@ PassRefPtr<RenderStyle> RenderMathMLOperator::createStackableStyle(int size, int
return newStyle.release();
}
-RenderBlock* RenderMathMLOperator::createGlyph(UChar glyph, int size, int charRelative, int topRelative)
+RenderBlock* RenderMathMLOperator::createGlyph(UChar glyph, int lineHeight, int maxHeightForRenderer, int charRelative, int topRelative)
{
RenderBlock* container = new (renderArena()) RenderMathMLBlock(node());
- container->setStyle(createStackableStyle(size, topRelative));
+ container->setStyle(createStackableStyle(lineHeight, maxHeightForRenderer, topRelative));
addChild(container);
RenderBlock* parent = container;
if (charRelative) {
diff --git a/Source/WebCore/rendering/mathml/RenderMathMLOperator.h b/Source/WebCore/rendering/mathml/RenderMathMLOperator.h
index 42708724a..5adab8fd1 100644
--- a/Source/WebCore/rendering/mathml/RenderMathMLOperator.h
+++ b/Source/WebCore/rendering/mathml/RenderMathMLOperator.h
@@ -38,20 +38,26 @@ public:
RenderMathMLOperator(Element*);
RenderMathMLOperator(Node*, UChar operatorChar);
virtual bool isRenderMathMLOperator() const { return true; }
- virtual RenderMathMLOperator* unembellishedOperator() { return this; }
- virtual void stretchToHeight(int pixelHeight);
- virtual void updateFromElement();
+
virtual bool isChildAllowed(RenderObject*, RenderStyle*) const;
+ virtual void updateFromElement() OVERRIDE;
+
+ virtual RenderMathMLOperator* unembellishedOperator() OVERRIDE { return this; }
+ void stretchToHeight(int pixelHeight);
+
virtual LayoutUnit baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const;
protected:
- virtual void layout();
- virtual PassRefPtr<RenderStyle> createStackableStyle(int size, int topRelative);
- virtual RenderBlock* createGlyph(UChar glyph, int size = 0, int charRelative = 0, int topRelative = 0);
+ virtual void computePreferredLogicalWidths() OVERRIDE;
+ PassRefPtr<RenderStyle> createStackableStyle(int lineHeight, int maxHeightForRenderer, int topRelative);
+ RenderBlock* createGlyph(UChar glyph, int lineHeight, int maxHeightForRenderer = 0, int charRelative = 0, int topRelative = 0);
private:
virtual const char* renderName() const { return isAnonymous() ? "RenderMathMLOperator (anonymous)" : "RenderMathMLOperator"; }
+ int glyphHeightForCharacter(UChar);
+ int lineHeightForCharacter(UChar);
+
int m_stretchHeight;
bool m_isStacked;
UChar m_operator;
diff --git a/Source/WebCore/rendering/mathml/RenderMathMLRoot.cpp b/Source/WebCore/rendering/mathml/RenderMathMLRoot.cpp
index 07e8ff911..e6d5165a9 100644
--- a/Source/WebCore/rendering/mathml/RenderMathMLRoot.cpp
+++ b/Source/WebCore/rendering/mathml/RenderMathMLRoot.cpp
@@ -34,122 +34,83 @@
#include "MathMLNames.h"
#include "PaintInfo.h"
+using namespace std;
+
namespace WebCore {
using namespace MathMLNames;
-// Left margin of the radical (px)
-const int gRadicalLeftMargin = 3;
-// Bottom padding of the radical (px)
-const int gRadicalBasePad = 3;
-// Threshold above which the radical shape is modified to look nice with big bases (%)
-const float gThresholdBaseHeight = 1.5f;
-// Radical width (%)
-const float gRadicalWidth = 0.75f;
-// Horizontal position of the bottom point of the radical (%)
-const float gRadicalBottomPointXPos= 0.5f;
-// Horizontal position of the top left point of the radical (%)
-const float gRadicalTopLeftPointXPos = 0.8f;
-// Vertical position of the top left point of the radical (%)
-const float gRadicalTopLeftPointYPos = 0.625f;
-// Vertical shift of the left end point of the radical (%)
-const float gRadicalLeftEndYShift = 0.05f;
-// Root padding around the base (%)
-const float gRootPadding = 0.2f;
-// Additional bottom root padding (%)
-const float gRootBottomPadding = 0.2f;
-
-// Radical line thickness (%)
-const float gRadicalLineThickness = 0.02f;
-// Radical thick line thickness (%)
-const float gRadicalThickLineThickness = 0.1f;
+// 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.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)
+const float gBigRootBottomPaddingEms = 0.2f;
+
+// Radical line thickness (em)
+const float gRadicalLineThicknessEms = 0.02f;
+// Radical thick line thickness (em)
+const float gRadicalThickLineThicknessEms = 0.1f;
RenderMathMLRoot::RenderMathMLRoot(Element* element)
: RenderMathMLBlock(element)
{
}
-void RenderMathMLRoot::addChild(RenderObject* child, RenderObject* )
+RenderBoxModelObject* RenderMathMLRoot::index() const
{
- if (isEmpty()) {
- // Add a block for the index
- RenderBlock* block = new (renderArena()) RenderBlock(node());
- RefPtr<RenderStyle> indexStyle = createBlockStyle();
- indexStyle->setDisplay(INLINE_BLOCK);
- block->setStyle(indexStyle.release());
- RenderBlock::addChild(block);
-
- // FIXME: the wrapping does not seem to be needed anymore.
- // this is the base, so wrap it so we can pad it
- block = new (renderArena()) RenderBlock(node());
- RefPtr<RenderStyle> baseStyle = createBlockStyle();
- baseStyle->setDisplay(INLINE_BLOCK);
- baseStyle->setPaddingLeft(Length(5 * gRadicalWidth , Percent));
- block->setStyle(baseStyle.release());
- RenderBlock::addChild(block);
- block->addChild(child);
- } else {
- // always add to the index
- firstChild()->addChild(child);
- }
+ if (!firstChild())
+ return 0;
+ RenderObject* index = firstChild()->nextSibling();
+ if (!index || !index->isBoxModelObject())
+ return 0;
+ return toRenderBoxModelObject(index);
}
-
+
void RenderMathMLRoot::paint(PaintInfo& info, const LayoutPoint& paintOffset)
{
RenderMathMLBlock::paint(info, paintOffset);
if (info.context->paintingDisabled())
return;
-
- if (!firstChild() || !lastChild())
- return;
-
- IntPoint adjustedPaintOffset = roundedIntPoint(paintOffset + location());
-
- RenderBoxModelObject* indexBox = toRenderBoxModelObject(lastChild());
- LayoutUnit maxHeight = indexBox->offsetHeight();
- // default to the font size in pixels if we're empty
- if (!maxHeight)
- maxHeight = style()->fontSize();
- LayoutUnit width = indexBox->offsetWidth();
+ if (!index())
+ return;
- LayoutUnit indexWidth = 0;
- RenderObject* current = firstChild();
- while (current != lastChild()) {
- if (current->isBoxModelObject()) {
- RenderBoxModelObject* box = toRenderBoxModelObject(current);
- indexWidth += box->offsetWidth();
- }
- current = current->nextSibling();
- }
+ IntPoint adjustedPaintOffset = roundedIntPoint(paintOffset + location() + computedCSSContentBoxRect().location());
- int frontWidth = static_cast<int>(style()->fontSize() * gRadicalWidth);
- int topStartShift = 0;
- // Base height above which the shape of the root changes
- int thresholdHeight = static_cast<int>(gThresholdBaseHeight * style()->fontSize());
+ int baseHeight = roundToInt(getBoxModelObjectHeight(firstChild()));
- if (maxHeight > thresholdHeight && thresholdHeight) {
- float shift = (maxHeight - thresholdHeight) / static_cast<float>(thresholdHeight);
- if (shift > 1.)
- shift = 1.0f;
- topStartShift = static_cast<int>(gRadicalBottomPointXPos * frontWidth * shift);
- }
+ 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;
- width += topStartShift;
+ int rootPad = static_cast<int>(roundf(gSpaceAboveEms * style()->fontSize()));
+ adjustedPaintOffset.setY(adjustedPaintOffset.y() + m_intrinsicPaddingBefore - rootPad);
- int rootPad = static_cast<int>(gRootPadding * style()->fontSize());
- LayoutUnit start = adjustedPaintOffset.x() + indexWidth + gRadicalLeftMargin + style()->paddingLeft().value() - rootPad;
- adjustedPaintOffset.setY(adjustedPaintOffset.y() + style()->paddingTop().value() - rootPad);
-
- FloatPoint topStart(start - topStartShift, adjustedPaintOffset.y());
- FloatPoint bottomLeft(start - gRadicalBottomPointXPos * frontWidth , adjustedPaintOffset.y() + maxHeight + gRadicalBasePad);
- FloatPoint topLeft(start - gRadicalTopLeftPointXPos * frontWidth , adjustedPaintOffset.y() + gRadicalTopLeftPointYPos * maxHeight);
- FloatPoint leftEnd(start - frontWidth , topLeft.y() + gRadicalLeftEndYShift * style()->fontSize());
+ 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 leftEnd(startX - frontWidth, dipLeftPoint.y() + gRadicalLeftEndYShiftEms * style()->fontSize());
GraphicsContextStateSaver stateSaver(*info.context);
- info.context->setStrokeThickness(gRadicalLineThickness * style()->fontSize());
+ info.context->setStrokeThickness(gRadicalLineThicknessEms * style()->fontSize());
info.context->setStrokeStyle(SolidStroke);
info.context->setStrokeColor(style()->visitedDependentColor(CSSPropertyColor), ColorSpaceDeviceRGB);
info.context->setLineJoin(MiterJoin);
@@ -157,13 +118,13 @@ void RenderMathMLRoot::paint(PaintInfo& info, const LayoutPoint& paintOffset)
Path root;
- root.moveTo(FloatPoint(topStart.x() + width, adjustedPaintOffset.y()));
+ root.moveTo(FloatPoint(overbarLeftPoint.x() + overbarWidth, adjustedPaintOffset.y()));
// draw top
- root.addLineTo(topStart);
+ root.addLineTo(overbarLeftPoint);
// draw from top left corner to bottom point of radical
- root.addLineTo(bottomLeft);
- // draw from bottom point to top of left part of radical base "pocket"
- root.addLineTo(topLeft);
+ 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);
@@ -174,21 +135,21 @@ void RenderMathMLRoot::paint(PaintInfo& info, const LayoutPoint& paintOffset)
// Build a mask to draw the thick part of the root.
Path mask;
- mask.moveTo(topStart);
- mask.addLineTo(bottomLeft);
- mask.addLineTo(topLeft);
- mask.addLineTo(FloatPoint(2 * topLeft.x() - leftEnd.x(), 2 * topLeft.y() - leftEnd.y()));
+ 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(gRadicalThickLineThickness * style()->fontSize());
+ info.context->setStrokeThickness(gRadicalThickLineThicknessEms * style()->fontSize());
info.context->setLineCap(SquareCap);
Path line;
- line.moveTo(bottomLeft);
- line.addLineTo(topLeft);
-
+ line.moveTo(bottomPoint);
+ line.addLineTo(dipLeftPoint);
+
info.context->strokePath(line);
}
@@ -196,60 +157,42 @@ void RenderMathMLRoot::layout()
{
RenderBlock::layout();
- if (!firstChild() || !lastChild())
+ if (!index())
return;
- LayoutUnit maxHeight = toRenderBoxModelObject(lastChild())->offsetHeight();
-
- RenderObject* current = lastChild()->firstChild();
- if (current)
- current->style()->setVerticalAlign(BASELINE);
-
- if (!maxHeight)
- maxHeight = style()->fontSize();
+ int baseHeight = roundToInt(getBoxModelObjectHeight(firstChild()));
// Base height above which the shape of the root changes
- LayoutUnit thresholdHeight = static_cast<LayoutUnit>(gThresholdBaseHeight * style()->fontSize());
- LayoutUnit topStartShift = 0;
-
- if (maxHeight > thresholdHeight && thresholdHeight) {
- float shift = (maxHeight - thresholdHeight) / static_cast<float>(thresholdHeight);
- if (shift > 1.)
- shift = 1.0f;
- LayoutUnit frontWidth = static_cast<LayoutUnit>(style()->fontSize() * gRadicalWidth);
- topStartShift = static_cast<LayoutUnit>(gRadicalBottomPointXPos * frontWidth * shift);
-
- style()->setPaddingBottom(Length(static_cast<LayoutUnit>(gRootBottomPadding * style()->fontSize()), Fixed));
+ 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;
}
- // Positioning of the index
- RenderObject* possibleIndex = firstChild()->firstChild();
- while (possibleIndex && !possibleIndex->isBoxModelObject())
- possibleIndex = possibleIndex->nextSibling();
- RenderBoxModelObject* indexBox = toRenderBoxModelObject(possibleIndex);
- if (!indexBox)
- return;
+ RenderBoxModelObject* index = this->index();
- LayoutUnit indexShift = indexBox->offsetWidth() + topStartShift;
- LayoutUnit radicalHeight = static_cast<LayoutUnit>((1 - gRadicalTopLeftPointYPos) * maxHeight);
- LayoutUnit rootMarginTop = radicalHeight + style()->paddingBottom().value() + indexBox->offsetHeight()
- - (maxHeight + static_cast<LayoutUnit>(gRootPadding * style()->fontSize()));
+ m_intrinsicPaddingStart = index->pixelSnappedOffsetWidth() + m_overbarLeftPointShift;
- style()->setPaddingLeft(Length(indexShift, Fixed));
- if (rootMarginTop > 0)
- style()->setPaddingTop(Length(rootMarginTop + static_cast<LayoutUnit>(gRootPadding * style()->fontSize()), Fixed));
+ 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);
- setPreferredLogicalWidthsDirty(true, false);
+ 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();
-
- indexBox->style()->setBottom(Length(radicalHeight + style()->paddingBottom().value(), Fixed));
-
- // Now that we've potentially changed its position, we need layout the index again.
- indexBox->setNeedsLayout(true);
- indexBox->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 19b2ec6ec..65ec82dc7 100644
--- a/Source/WebCore/rendering/mathml/RenderMathMLRoot.h
+++ b/Source/WebCore/rendering/mathml/RenderMathMLRoot.h
@@ -32,16 +32,23 @@
namespace WebCore {
+// Render base^(1/index), using radical notation.
class RenderMathMLRoot : public RenderMathMLBlock {
public:
RenderMathMLRoot(Element*);
- virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0);
- virtual void paint(PaintInfo&, const LayoutPoint&);
+
protected:
- virtual void layout();
+ virtual void layout() OVERRIDE;
+
+ virtual void paint(PaintInfo&, const LayoutPoint&) OVERRIDE;
private:
virtual const char* renderName() const { return "RenderMathMLRoot"; }
+
+ // This may return 0 for a non-MathML index (which won't occur in valid MathML).
+ RenderBoxModelObject* index() const;
+
+ int m_overbarLeftPointShift;
};
}
diff --git a/Source/WebCore/rendering/mathml/RenderMathMLRow.cpp b/Source/WebCore/rendering/mathml/RenderMathMLRow.cpp
index 203d194de..347e96cf0 100644
--- a/Source/WebCore/rendering/mathml/RenderMathMLRow.cpp
+++ b/Source/WebCore/rendering/mathml/RenderMathMLRow.cpp
@@ -36,53 +36,64 @@ namespace WebCore {
using namespace MathMLNames;
-RenderMathMLRow::RenderMathMLRow(Element* element)
- : RenderMathMLBlock(element)
+RenderMathMLRow::RenderMathMLRow(Node* node)
+ : RenderMathMLBlock(node)
{
}
-void RenderMathMLRow::layout()
+// FIXME: Change all these createAnonymous... routines to return a PassOwnPtr<>.
+RenderMathMLRow* RenderMathMLRow::createAnonymousWithParentRenderer(const RenderObject* parent)
{
- RenderBlock::layout();
-
- LayoutUnit maxHeight = 0;
+ RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(parent->style(), INLINE_BLOCK);
+ RenderMathMLRow* newMRow = new (parent->renderArena()) RenderMathMLRow(parent->document() /* is anonymous */);
+ newMRow->setStyle(newStyle.release());
+ return newMRow;
+}
- // Calculate the non-operator max height of the row.
- for (RenderObject* current = firstChild(); current; current = current->nextSibling()) {
- if (current->isRenderMathMLBlock()) {
- RenderMathMLBlock* block = toRenderMathMLBlock(current);
- if (!block->unembellishedOperator() && block->offsetHeight() > maxHeight)
- maxHeight = block->offsetHeight();
- } else if (current->isBoxModelObject()) {
- RenderBoxModelObject* box = toRenderBoxModelObject(current);
- // Check to see if this box has a larger height.
- if (box->offsetHeight() > maxHeight)
- maxHeight = box->offsetHeight();
+void RenderMathMLRow::computePreferredLogicalWidths()
+{
+ ASSERT(preferredLogicalWidthsDirty() && needsLayout());
+
+ computeChildrenPreferredLogicalHeights();
+ int stretchLogicalHeight = 0;
+ for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
+ if (child->isRenderMathMLBlock()) {
+ RenderMathMLOperator* renderMo = toRenderMathMLBlock(child)->unembellishedOperator();
+ // FIXME: Only skip renderMo if it is stretchy.
+ if (renderMo)
+ continue;
}
+ stretchLogicalHeight = max<int>(stretchLogicalHeight, roundToInt(preferredLogicalHeightAfterSizing(child)));
}
+ if (!stretchLogicalHeight)
+ stretchLogicalHeight = style()->fontSize();
- if (!maxHeight)
- maxHeight = style()->fontSize();
-
- // Stretch everything to the same height (blocks can ignore the request).
- if (maxHeight > 0) {
- bool didStretch = false;
- for (RenderObject* current = firstChild(); current; current = current->nextSibling()) {
- if (current->isRenderMathMLBlock()) {
- RenderMathMLBlock* block = toRenderMathMLBlock(current);
- block->stretchToHeight(maxHeight);
- didStretch = true;
- }
- }
- if (didStretch) {
- setNeedsLayout(true);
- setPreferredLogicalWidthsDirty(true, false);
- RenderBlock::layout();
+ // Set the sizes of (possibly embellished) stretchy operator children.
+ for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
+ if (child->isRenderMathMLBlock()) {
+ RenderMathMLOperator* renderMo = toRenderMathMLBlock(child)->unembellishedOperator();
+ if (renderMo)
+ renderMo->stretchToHeight(stretchLogicalHeight);
}
}
-}
+ 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 RenderMathMLRow::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();
+}
+
}
#endif // ENABLE(MATHML)
diff --git a/Source/WebCore/rendering/mathml/RenderMathMLRow.h b/Source/WebCore/rendering/mathml/RenderMathMLRow.h
index 2a520d07b..37f64a1db 100644
--- a/Source/WebCore/rendering/mathml/RenderMathMLRow.h
+++ b/Source/WebCore/rendering/mathml/RenderMathMLRow.h
@@ -34,16 +34,21 @@ namespace WebCore {
class RenderMathMLRow : public RenderMathMLBlock {
public:
- RenderMathMLRow(Element*);
+ RenderMathMLRow(Node*);
+ static RenderMathMLRow* createAnonymousWithParentRenderer(const RenderObject*);
+
virtual bool isRenderMathMLRow() const { return true; }
- virtual void stretchToHeight(int) {}
+
protected:
+ // This also sets our stretchy embellished operator children to their correct sizes.
+ virtual void computePreferredLogicalWidths() OVERRIDE;
+
virtual void layout();
private:
virtual const char* renderName() const { return isAnonymous() ? "RenderMathMLRow (anonymous)" : "RenderMathMLRow"; }
};
-
+
}
#endif // ENABLE(MATHML)
diff --git a/Source/WebCore/rendering/mathml/RenderMathMLSquareRoot.cpp b/Source/WebCore/rendering/mathml/RenderMathMLSquareRoot.cpp
index 206426a13..86975dbfb 100644
--- a/Source/WebCore/rendering/mathml/RenderMathMLSquareRoot.cpp
+++ b/Source/WebCore/rendering/mathml/RenderMathMLSquareRoot.cpp
@@ -33,89 +33,119 @@
#include "GraphicsContext.h"
#include "MathMLNames.h"
#include "PaintInfo.h"
-#include "Path.h"
+#include "RenderMathMLRow.h"
+
+using namespace std;
namespace WebCore {
using namespace MathMLNames;
-// Bottom padding of the radical (px)
-const int gRadicalBasePad = 3;
-// Threshold above which the radical shape is modified to look nice with big bases (%)
-const float gThresholdBaseHeight = 1.5f;
-// Radical width (%)
-const float gRadicalWidth = 0.75f;
-// Horizontal position of the bottom point of the radical (%)
-const float gRadicalBottomPointXPos= 0.5f;
-// Horizontal position of the top left point of the radical (%)
-const float gRadicalTopLeftPointXPos = 0.2f;
-// Vertical position of the top left point of the radical (%)
-const float gRadicalTopLeftPointYPos = 0.5f;
-// Vertical shift of the left end point of the radical (%)
-const float gRadicalLeftEndYShift = 0.05f;
-// Additional bottom root padding (%)
-const float gRootBottomPadding = 0.2f;
-
-// Radical line thickness (%)
-const float gRadicalLineThickness = 0.02f;
-// Radical thick line thickness (%)
-const float gRadicalThickLineThickness = 0.1f;
+// 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)
{
}
+void RenderMathMLSquareRoot::addChild(RenderObject* newChild, RenderObject* beforeChild)
+{
+ if (!firstChild()) {
+ RenderMathMLRow* newMRow = RenderMathMLRow::createAnonymousWithParentRenderer(this);
+
+ RenderMathMLBlock::addChild(newMRow);
+
+ // newMRow->isAnonymousBlock() is false because newMRow's display is INLINE_BLOCK,
+ // so we don't need to worry about removeLeftoverAnonymousBlock().
+ ASSERT(!newMRow->isAnonymousBlock());
+ }
+
+ ASSERT(firstChild() && firstChild()->isAnonymous() && firstChild()->isRenderMathMLBlock() && toRenderMathMLBlock(firstChild())->isRenderMathMLRow());
+ firstChild()->addChild(newChild, beforeChild);
+}
+
+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());
- IntPoint adjustedPaintOffset = roundedIntPoint(paintOffset + location());
-
- LayoutUnit maxHeight = 0;
- LayoutUnit width = 0;
- RenderObject* current = firstChild();
- while (current) {
- if (current->isBoxModelObject()) {
-
- RenderBoxModelObject* box = toRenderBoxModelObject(current);
-
- // Check to see if this box has a larger height
- if (box->offsetHeight() > maxHeight)
- maxHeight = box->offsetHeight();
- width += box->offsetWidth();
- }
- current = current->nextSibling();
- }
- // default to the font size in pixels if we're empty
- if (!maxHeight)
- maxHeight = style()->fontSize();
+ int baseHeight = roundToInt(getBoxModelObjectHeight(firstChild()));
+ int overbarWidth = roundToInt(getBoxModelObjectWidth(firstChild()));
- int frontWidth = static_cast<int>(style()->fontSize() * gRadicalWidth);
- int topStartShift = 0;
+ int frontWidth = m_intrinsicPaddingStart;
+ int overbarLeftPointShift = 0;
// Base height above which the shape of the root changes
- int thresholdHeight = static_cast<int>(gThresholdBaseHeight * style()->fontSize());
+ float thresholdHeight = gThresholdBaseHeightEms * style()->fontSize();
- if (maxHeight > thresholdHeight && thresholdHeight) {
- float shift = (maxHeight - thresholdHeight) / static_cast<float>(thresholdHeight);
- if (shift > 1.)
- shift = 1.0f;
- topStartShift = static_cast<int>(gRadicalBottomPointXPos * frontWidth * shift);
+ if (baseHeight > thresholdHeight && thresholdHeight) {
+ float shift = min<float>((baseHeight - thresholdHeight) / thresholdHeight, 1.0f);
+ overbarLeftPointShift = static_cast<int>(shift * gRadicalBottomPointXFront * frontWidth);
}
- width += topStartShift;
+ overbarWidth += overbarLeftPointShift;
- FloatPoint topStart(adjustedPaintOffset.x() + frontWidth - topStartShift, adjustedPaintOffset.y());
- FloatPoint bottomLeft(adjustedPaintOffset.x() + frontWidth * gRadicalBottomPointXPos , adjustedPaintOffset.y() + maxHeight + gRadicalBasePad);
- FloatPoint topLeft(adjustedPaintOffset.x() + frontWidth * gRadicalTopLeftPointXPos , adjustedPaintOffset.y() + gRadicalTopLeftPointYPos * maxHeight);
- FloatPoint leftEnd(adjustedPaintOffset.x() , topLeft.y() + gRadicalLeftEndYShift * style()->fontSize());
+ 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(gRadicalLineThickness * style()->fontSize());
+ info.context->setStrokeThickness(gRadicalLineThicknessEms * style()->fontSize());
info.context->setStrokeStyle(SolidStroke);
info.context->setStrokeColor(style()->visitedDependentColor(CSSPropertyColor), ColorSpaceDeviceRGB);
info.context->setLineJoin(MiterJoin);
@@ -123,16 +153,16 @@ void RenderMathMLSquareRoot::paint(PaintInfo& info, const LayoutPoint& paintOffs
Path root;
- root.moveTo(FloatPoint(topStart.x() + width , adjustedPaintOffset.y()));
+ root.moveTo(FloatPoint(overbarLeftPoint.x() + overbarWidth, adjustedPaintOffset.y()));
// draw top
- root.addLineTo(topStart);
+ root.addLineTo(overbarLeftPoint);
// draw from top left corner to bottom point of radical
- root.addLineTo(bottomLeft);
- // draw from bottom point to top of left part of radical base "pocket"
- root.addLineTo(topLeft);
+ 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);
@@ -140,52 +170,24 @@ void RenderMathMLSquareRoot::paint(PaintInfo& info, const LayoutPoint& paintOffs
// Build a mask to draw the thick part of the root.
Path mask;
- mask.moveTo(topStart);
- mask.addLineTo(bottomLeft);
- mask.addLineTo(topLeft);
- mask.addLineTo(FloatPoint(2 * topLeft.x() - leftEnd.x(), 2 * topLeft.y() - leftEnd.y()));
+ 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(gRadicalThickLineThickness * style()->fontSize());
+ info.context->setStrokeThickness(gRadicalThickLineThicknessEms * style()->fontSize());
info.context->setLineCap(SquareCap);
Path line;
- line.moveTo(bottomLeft);
- line.addLineTo(topLeft);
+ line.moveTo(bottomPoint);
+ line.addLineTo(dipLeftPoint);
info.context->strokePath(line);
}
-void RenderMathMLSquareRoot::layout()
-{
- LayoutUnit maxHeight = 0;
-
- RenderObject* current = firstChild();
- while (current) {
- if (current->isBoxModelObject()) {
- RenderBoxModelObject* box = toRenderBoxModelObject(current);
-
- if (box->offsetHeight() > maxHeight)
- maxHeight = box->offsetHeight();
-
- box->style()->setVerticalAlign(BASELINE);
- }
- current = current->nextSibling();
- }
-
- if (!maxHeight)
- maxHeight = style()->fontSize();
-
-
- if (maxHeight > static_cast<LayoutUnit>(gThresholdBaseHeight * style()->fontSize()))
- style()->setPaddingBottom(Length(static_cast<LayoutUnit>(gRootBottomPadding * style()->fontSize()), Fixed));
-
-
- RenderBlock::layout();
-}
-
}
#endif // ENABLE(MATHML)
diff --git a/Source/WebCore/rendering/mathml/RenderMathMLSquareRoot.h b/Source/WebCore/rendering/mathml/RenderMathMLSquareRoot.h
index ad81fdc56..ea6d324db 100644
--- a/Source/WebCore/rendering/mathml/RenderMathMLSquareRoot.h
+++ b/Source/WebCore/rendering/mathml/RenderMathMLSquareRoot.h
@@ -32,15 +32,23 @@
namespace WebCore {
+// Render sqrt(base), using radical notation.
class RenderMathMLSquareRoot : public RenderMathMLBlock {
public:
RenderMathMLSquareRoot(Element*);
- virtual void paint(PaintInfo&, const LayoutPoint&);
-protected:
- virtual void layout();
-
+
+ virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0) OVERRIDE;
+
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/mathml/RenderMathMLSubSup.cpp b/Source/WebCore/rendering/mathml/RenderMathMLSubSup.cpp
index 84928d4b4..5342cbd84 100644
--- a/Source/WebCore/rendering/mathml/RenderMathMLSubSup.cpp
+++ b/Source/WebCore/rendering/mathml/RenderMathMLSubSup.cpp
@@ -68,38 +68,31 @@ void RenderMathMLSubSup::addChild(RenderObject* child, RenderObject* beforeChild
// Note: The RenderMathMLBlock only allows element children to be added.
Element* childElement = toElement(child->node());
- if (!childElement->previousElementSibling()) {
+ if (childElement && !childElement->previousElementSibling()) {
// Position 1 is always the base of the msub/msup/msubsup.
- RenderMathMLBlock* wrapper = new (renderArena()) RenderMathMLBlock(node());
- RefPtr<RenderStyle> wrapperStyle = RenderStyle::create();
- wrapperStyle->inheritFrom(style());
- wrapperStyle->setDisplay(INLINE_BLOCK);
- wrapperStyle->setVerticalAlign(BASELINE);
- wrapper->setStyle(wrapperStyle.release());
- RenderMathMLBlock::addChild(wrapper, firstChild());
- wrapper->addChild(child);
+ RenderBlock* baseWrapper = createAlmostAnonymousBlock(INLINE_BLOCK);
+ RenderMathMLBlock::addChild(baseWrapper, firstChild());
+ baseWrapper->addChild(child);
// Make sure we have a script block for rendering.
if (m_kind == SubSup && !m_scripts) {
- m_scripts = new (renderArena()) RenderMathMLBlock(node());
- RefPtr<RenderStyle> scriptsStyle = RenderStyle::create();
- scriptsStyle->inheritFrom(style());
- scriptsStyle->setDisplay(INLINE_BLOCK);
+ RefPtr<RenderStyle> scriptsStyle = RenderStyle::createAnonymousStyleWithDisplay(style(), INLINE_BLOCK);
scriptsStyle->setVerticalAlign(TOP);
scriptsStyle->setMarginLeft(Length(gSubsupScriptMargin, Fixed));
scriptsStyle->setTextAlign(LEFT);
// Set this wrapper's font-size for its line-height & baseline position.
scriptsStyle->setBlendedFontSize(static_cast<int>(0.75 * style()->fontSize()));
- m_scripts->setStyle(scriptsStyle.release());
+ m_scripts = new (renderArena()) RenderMathMLBlock(node());
+ m_scripts->setStyle(scriptsStyle);
RenderMathMLBlock::addChild(m_scripts, beforeChild);
}
} else {
if (m_kind == SubSup) {
- RenderBlock* script = new (renderArena()) RenderMathMLBlock(node());
- RefPtr<RenderStyle> scriptStyle = RenderStyle::create();
- scriptStyle->inheritFrom(m_scripts->style());
- scriptStyle->setDisplay(BLOCK);
- script->setStyle(scriptStyle.release());
+ ASSERT(childElement);
+ if (!childElement)
+ return;
+
+ RenderBlock* script = m_scripts->createAlmostAnonymousBlock();
// The order is always backwards so the first script is the subscript and the superscript
// is last. That means the superscript is the first to render vertically.
@@ -123,13 +116,6 @@ RenderMathMLOperator* RenderMathMLSubSup::unembellishedOperator()
return toRenderMathMLBlock(base)->unembellishedOperator();
}
-void RenderMathMLSubSup::stretchToHeight(int height)
-{
- RenderBoxModelObject* base = this->base();
- if (base && base->isRenderMathMLBlock())
- toRenderMathMLBlock(base)->stretchToHeight(height);
-}
-
void RenderMathMLSubSup::layout()
{
RenderBlock::layout();
@@ -175,15 +161,15 @@ void RenderMathMLSubSup::layout()
basePaddingTop = 0;
}
- setChildNeedsLayout(true, false);
+ setChildNeedsLayout(true, MarkOnlyThis);
RenderObject* baseWrapper = firstChild();
baseWrapper->style()->setPaddingTop(Length(basePaddingTop, Fixed));
- baseWrapper->setNeedsLayout(true, false);
+ baseWrapper->setNeedsLayout(true, MarkOnlyThis);
superscriptWrapper->style()->setPaddingBottom(Length(superPaddingBottom, Fixed));
- superscriptWrapper->setNeedsLayout(true, false);
- m_scripts->setNeedsLayout(true, false);
+ superscriptWrapper->setNeedsLayout(true, MarkOnlyThis);
+ m_scripts->setNeedsLayout(true, MarkOnlyThis);
RenderBlock::layout();
}
diff --git a/Source/WebCore/rendering/mathml/RenderMathMLSubSup.h b/Source/WebCore/rendering/mathml/RenderMathMLSubSup.h
index 0a291de97..c88fe663b 100644
--- a/Source/WebCore/rendering/mathml/RenderMathMLSubSup.h
+++ b/Source/WebCore/rendering/mathml/RenderMathMLSubSup.h
@@ -32,13 +32,13 @@
namespace WebCore {
+// Render a base with a subscript and/or a superscript.
class RenderMathMLSubSup : public RenderMathMLBlock {
public:
RenderMathMLSubSup(Element*);
virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0);
virtual RenderMathMLOperator* unembellishedOperator();
- virtual void stretchToHeight(int pixelHeight);
protected:
virtual void layout();
@@ -52,7 +52,7 @@ private:
enum SubSupType { Sub, Sup, SubSup };
SubSupType m_kind;
- RenderBlock* m_scripts;
+ RenderMathMLBlock* m_scripts;
};
}
diff --git a/Source/WebCore/rendering/mathml/RenderMathMLUnderOver.cpp b/Source/WebCore/rendering/mathml/RenderMathMLUnderOver.cpp
index 0621cd6dd..03c9c31ef 100644
--- a/Source/WebCore/rendering/mathml/RenderMathMLUnderOver.cpp
+++ b/Source/WebCore/rendering/mathml/RenderMathMLUnderOver.cpp
@@ -29,7 +29,6 @@
#include "RenderMathMLUnderOver.h"
-#include "FontSelector.h"
#include "MathMLNames.h"
namespace WebCore {
@@ -67,10 +66,7 @@ RenderBoxModelObject* RenderMathMLUnderOver::base() const
void RenderMathMLUnderOver::addChild(RenderObject* child, RenderObject* beforeChild)
{
- RenderMathMLBlock* row = new (renderArena()) RenderMathMLBlock(node());
- RefPtr<RenderStyle> rowStyle = createBlockStyle();
- row->setStyle(rowStyle.release());
- row->setIsAnonymous(true);
+ RenderBlock* row = createAnonymousBlock();
// look through the children for rendered elements counting the blocks so we know what child
// we are adding
@@ -131,22 +127,12 @@ inline int getOffsetHeight(RenderObject* obj)
{
if (obj->isBoxModelObject()) {
RenderBoxModelObject* box = toRenderBoxModelObject(obj);
- return box->offsetHeight();
+ return box->pixelSnappedOffsetHeight();
}
return 0;
}
-void RenderMathMLUnderOver::stretchToHeight(int height)
-{
- RenderBoxModelObject* base = this->base();
- if (base && base->isRenderMathMLBlock()) {
- RenderMathMLBlock* block = toRenderMathMLBlock(base);
- block->stretchToHeight(height);
- setNeedsLayout(true);
- }
-}
-
void RenderMathMLUnderOver::layout()
{
RenderBlock::layout();
@@ -185,7 +171,7 @@ void RenderMathMLUnderOver::layout()
// base row wrapper
base = firstChild();
if (base) {
- LayoutUnit baseHeight = getOffsetHeight(base);
+ int baseHeight = getOffsetHeight(base);
// actual base
base = base->firstChild();
if (!base || !base->isBoxModelObject())
@@ -226,7 +212,7 @@ void RenderMathMLUnderOver::layout()
// We need to calculate the baseline of the base versus the start of the under block and
// adjust the placement of the under block.
- LayoutUnit baseHeight = getOffsetHeight(base);
+ int baseHeight = getOffsetHeight(base);
// actual base
base = base->firstChild();
if (!base || !base->isBoxModelObject())
diff --git a/Source/WebCore/rendering/mathml/RenderMathMLUnderOver.h b/Source/WebCore/rendering/mathml/RenderMathMLUnderOver.h
index e25e94768..3a4f70d76 100644
--- a/Source/WebCore/rendering/mathml/RenderMathMLUnderOver.h
+++ b/Source/WebCore/rendering/mathml/RenderMathMLUnderOver.h
@@ -40,7 +40,6 @@ public:
virtual RenderMathMLOperator* unembellishedOperator();
virtual void layout();
virtual LayoutUnit baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const;
- virtual void stretchToHeight(int pixelHeight);
private:
virtual const char* renderName() const { return "RenderMathMLUnderOver"; }
diff --git a/Source/WebCore/rendering/style/BorderValue.h b/Source/WebCore/rendering/style/BorderValue.h
index d9d404b85..c8f6512c5 100644
--- a/Source/WebCore/rendering/style/BorderValue.h
+++ b/Source/WebCore/rendering/style/BorderValue.h
@@ -34,7 +34,9 @@ class BorderValue {
friend class RenderStyle;
public:
BorderValue()
- : m_width(3)
+ : m_color(0)
+ , m_colorIsValid(false)
+ , m_width(3)
, m_style(BNONE)
, m_isAuto(AUTO_OFF)
{
@@ -47,7 +49,7 @@ public:
bool isTransparent() const
{
- return m_color.isValid() && !m_color.alpha();
+ return m_colorIsValid && !alphaChannel(m_color);
}
bool isVisible(bool checkStyle = true) const
@@ -57,21 +59,30 @@ public:
bool operator==(const BorderValue& o) const
{
- return m_width == o.m_width && m_style == o.m_style && m_color == o.m_color;
+ return m_width == o.m_width && m_style == o.m_style && m_color == o.m_color && m_colorIsValid == o.m_colorIsValid;
}
bool operator!=(const BorderValue& o) const
{
return !(*this == o);
}
-
- const Color& color() const { return m_color; }
+
+ void setColor(const Color& color)
+ {
+ m_color = color.rgb();
+ m_colorIsValid = color.isValid();
+ }
+
+ Color color() const { return Color(m_color, m_colorIsValid); }
+
unsigned width() const { return m_width; }
EBorderStyle style() const { return static_cast<EBorderStyle>(m_style); }
protected:
- Color m_color;
- unsigned m_width : 27;
+ RGBA32 m_color;
+ unsigned m_colorIsValid : 1;
+
+ unsigned m_width : 26;
unsigned m_style : 4; // EBorderStyle
// This is only used by OutlineValue but moved here to keep the bits packed.
diff --git a/Source/WebCore/rendering/style/CollapsedBorderValue.h b/Source/WebCore/rendering/style/CollapsedBorderValue.h
index c84555e0c..049a4ac68 100644
--- a/Source/WebCore/rendering/style/CollapsedBorderValue.h
+++ b/Source/WebCore/rendering/style/CollapsedBorderValue.h
@@ -36,6 +36,15 @@ public:
{
}
+ // This copy constructor is for preventing GCC (x86) from creating an
+ // unexpected one as written in <http://webkit.org/b/81502>.
+ CollapsedBorderValue(const CollapsedBorderValue& other)
+ : m_border(other.m_border)
+ , m_borderColor(other.m_borderColor)
+ , m_precedence(other.m_precedence)
+ {
+ }
+
CollapsedBorderValue(const BorderValue& b, Color c, EBorderPrecedence p)
: m_border(b)
, m_borderColor(c)
diff --git a/Source/WebCore/rendering/style/FillLayer.cpp b/Source/WebCore/rendering/style/FillLayer.cpp
index c957cfe31..195a05c5d 100644
--- a/Source/WebCore/rendering/style/FillLayer.cpp
+++ b/Source/WebCore/rendering/style/FillLayer.cpp
@@ -24,11 +24,27 @@
namespace WebCore {
+struct SameSizeAsFillLayer {
+ FillLayer* m_next;
+
+ RefPtr<StyleImage> m_image;
+
+ Length m_xPosition;
+ Length m_yPosition;
+
+ LengthSize m_sizeLength;
+
+ unsigned m_bitfields;
+};
+
+COMPILE_ASSERT(sizeof(FillLayer) == sizeof(SameSizeAsFillLayer), FillLayer_should_stay_small);
+
FillLayer::FillLayer(EFillLayerType type)
: m_next(0)
, m_image(FillLayer::initialFillImage(type))
, m_xPosition(FillLayer::initialFillXPosition(type))
, m_yPosition(FillLayer::initialFillYPosition(type))
+ , m_sizeLength(FillLayer::initialFillSizeLength(type))
, m_attachment(FillLayer::initialFillAttachment(type))
, m_clip(FillLayer::initialFillClip(type))
, m_origin(FillLayer::initialFillOrigin(type))
@@ -36,7 +52,6 @@ FillLayer::FillLayer(EFillLayerType type)
, m_repeatY(FillLayer::initialFillRepeatY(type))
, m_composite(FillLayer::initialFillComposite(type))
, m_sizeType(SizeNone)
- , m_sizeLength(FillLayer::initialFillSizeLength(type))
, m_imageSet(false)
, m_attachmentSet(false)
, m_clipSet(false)
@@ -55,6 +70,7 @@ FillLayer::FillLayer(const FillLayer& o)
, m_image(o.m_image)
, m_xPosition(o.m_xPosition)
, m_yPosition(o.m_yPosition)
+ , m_sizeLength(o.m_sizeLength)
, m_attachment(o.m_attachment)
, m_clip(o.m_clip)
, m_origin(o.m_origin)
@@ -62,7 +78,6 @@ FillLayer::FillLayer(const FillLayer& o)
, m_repeatY(o.m_repeatY)
, m_composite(o.m_composite)
, m_sizeType(o.m_sizeType)
- , m_sizeLength(o.m_sizeLength)
, m_imageSet(o.m_imageSet)
, m_attachmentSet(o.m_attachmentSet)
, m_clipSet(o.m_clipSet)
@@ -91,6 +106,7 @@ FillLayer& FillLayer::operator=(const FillLayer& o)
m_image = o.m_image;
m_xPosition = o.m_xPosition;
m_yPosition = o.m_yPosition;
+ m_sizeLength = o.m_sizeLength;
m_attachment = o.m_attachment;
m_clip = o.m_clip;
m_composite = o.m_composite;
@@ -98,7 +114,6 @@ FillLayer& FillLayer::operator=(const FillLayer& o)
m_repeatX = o.m_repeatX;
m_repeatY = o.m_repeatY;
m_sizeType = o.m_sizeType;
- m_sizeLength = o.m_sizeLength;
m_imageSet = o.m_imageSet;
m_attachmentSet = o.m_attachmentSet;
diff --git a/Source/WebCore/rendering/style/FillLayer.h b/Source/WebCore/rendering/style/FillLayer.h
index 2f0228874..7f1ceb148 100644
--- a/Source/WebCore/rendering/style/FillLayer.h
+++ b/Source/WebCore/rendering/style/FillLayer.h
@@ -174,6 +174,8 @@ private:
Length m_xPosition;
Length m_yPosition;
+ LengthSize m_sizeLength;
+
unsigned m_attachment : 2; // EFillAttachment
unsigned m_clip : 2; // EFillBox
unsigned m_origin : 2; // EFillBox
@@ -182,17 +184,15 @@ private:
unsigned m_composite : 4; // CompositeOperator
unsigned m_sizeType : 2; // EFillSizeType
- LengthSize m_sizeLength;
-
- bool m_imageSet : 1;
- bool m_attachmentSet : 1;
- bool m_clipSet : 1;
- bool m_originSet : 1;
- bool m_repeatXSet : 1;
- bool m_repeatYSet : 1;
- bool m_xPosSet : 1;
- bool m_yPosSet : 1;
- bool m_compositeSet : 1;
+ unsigned m_imageSet : 1;
+ unsigned m_attachmentSet : 1;
+ unsigned m_clipSet : 1;
+ unsigned m_originSet : 1;
+ unsigned m_repeatXSet : 1;
+ unsigned m_repeatYSet : 1;
+ unsigned m_xPosSet : 1;
+ unsigned m_yPosSet : 1;
+ unsigned m_compositeSet : 1;
unsigned m_type : 1; // EFillLayerType
};
diff --git a/Source/WebCore/rendering/style/KeyframeList.cpp b/Source/WebCore/rendering/style/KeyframeList.cpp
index bafa4267c..a127b468b 100644
--- a/Source/WebCore/rendering/style/KeyframeList.cpp
+++ b/Source/WebCore/rendering/style/KeyframeList.cpp
@@ -85,11 +85,11 @@ void KeyframeList::insert(const KeyframeValue& keyframe)
m_properties.clear();
for (Vector<KeyframeValue>::const_iterator it = m_keyframes.begin(); it != m_keyframes.end(); ++it) {
const KeyframeValue& currKeyframe = *it;
- for (HashSet<int>::const_iterator it = currKeyframe.properties().begin(); it != currKeyframe.properties().end(); ++it)
+ for (HashSet<CSSPropertyID>::const_iterator it = currKeyframe.properties().begin(); it != currKeyframe.properties().end(); ++it)
m_properties.add(*it);
}
} else {
- for (HashSet<int>::const_iterator it = keyframe.properties().begin(); it != keyframe.properties().end(); ++it)
+ for (HashSet<CSSPropertyID>::const_iterator it = keyframe.properties().begin(); it != keyframe.properties().end(); ++it)
m_properties.add(*it);
}
}
diff --git a/Source/WebCore/rendering/style/KeyframeList.h b/Source/WebCore/rendering/style/KeyframeList.h
index 64170ce0c..fb352f9fd 100644
--- a/Source/WebCore/rendering/style/KeyframeList.h
+++ b/Source/WebCore/rendering/style/KeyframeList.h
@@ -25,6 +25,7 @@
#ifndef KeyframeList_h
#define KeyframeList_h
+#include "CSSPropertyNames.h"
#include <wtf/Vector.h>
#include <wtf/HashSet.h>
#include <wtf/RefPtr.h>
@@ -43,9 +44,9 @@ public:
{
}
- void addProperty(int prop) { m_properties.add(prop); }
- bool containsProperty(int prop) const { return m_properties.contains(prop); }
- const HashSet<int>& properties() const { return m_properties; }
+ void addProperty(CSSPropertyID prop) { m_properties.add(prop); }
+ bool containsProperty(CSSPropertyID prop) const { return m_properties.contains(prop); }
+ const HashSet<CSSPropertyID>& properties() const { return m_properties; }
float key() const { return m_key; }
void setKey(float key) { m_key = key; }
@@ -55,7 +56,7 @@ public:
private:
float m_key;
- HashSet<int> m_properties; // The properties specified in this keyframe.
+ HashSet<CSSPropertyID> m_properties; // The properties specified in this keyframe.
RefPtr<RenderStyle> m_style;
};
@@ -77,10 +78,10 @@ public:
void insert(const KeyframeValue& keyframe);
- void addProperty(int prop) { m_properties.add(prop); }
- bool containsProperty(int prop) const { return m_properties.contains(prop); }
- HashSet<int>::const_iterator beginProperties() const { return m_properties.begin(); }
- HashSet<int>::const_iterator endProperties() const { return m_properties.end(); }
+ void addProperty(CSSPropertyID prop) { m_properties.add(prop); }
+ bool containsProperty(CSSPropertyID prop) const { return m_properties.contains(prop); }
+ HashSet<CSSPropertyID>::const_iterator beginProperties() const { return m_properties.begin(); }
+ HashSet<CSSPropertyID>::const_iterator endProperties() const { return m_properties.end(); }
void clear();
bool isEmpty() const { return m_keyframes.isEmpty(); }
@@ -89,8 +90,8 @@ public:
private:
AtomicString m_animationName;
- Vector<KeyframeValue> m_keyframes; // kept sorted by key
- HashSet<int> m_properties; // the properties being animated
+ Vector<KeyframeValue> m_keyframes; // Kept sorted by key.
+ HashSet<CSSPropertyID> m_properties; // The properties being animated.
RenderObject* m_renderer;
};
diff --git a/Source/WebCore/rendering/style/OutlineValue.h b/Source/WebCore/rendering/style/OutlineValue.h
index 0e9148d71..f380af628 100644
--- a/Source/WebCore/rendering/style/OutlineValue.h
+++ b/Source/WebCore/rendering/style/OutlineValue.h
@@ -39,7 +39,7 @@ public:
bool operator==(const OutlineValue& o) const
{
- return m_width == o.m_width && m_style == o.m_style && m_color == o.m_color && m_offset == o.m_offset && m_isAuto == o.m_isAuto;
+ return m_width == o.m_width && m_style == o.m_style && m_color == o.m_color && m_colorIsValid == o.m_colorIsValid && m_offset == o.m_offset && m_isAuto == o.m_isAuto;
}
bool operator!=(const OutlineValue& o) const
diff --git a/Source/WebCore/rendering/style/QuotesData.cpp b/Source/WebCore/rendering/style/QuotesData.cpp
index 03a2554a2..4e81f7567 100644
--- a/Source/WebCore/rendering/style/QuotesData.cpp
+++ b/Source/WebCore/rendering/style/QuotesData.cpp
@@ -28,10 +28,10 @@ QuotesData* QuotesData::create(int stringCount)
char* tmp = new char[sizeof(QuotesData)+sizeof(String)*stringCount];
if (!tmp)
return 0;
- new (tmp) QuotesData(stringCount);
+ QuotesData* ret = new (tmp) QuotesData(stringCount);
for (int i = 0; i < stringCount; ++i)
new (tmp +sizeof(QuotesData) + sizeof(String)*i) String();
- return reinterpret_cast<QuotesData*>(tmp);
+ return ret;
}
bool QuotesData::equal(const QuotesData* quotesData1, const QuotesData* quotesData2)
diff --git a/Source/WebCore/rendering/style/RenderStyle.cpp b/Source/WebCore/rendering/style/RenderStyle.cpp
index 8f31e0f7d..a98d558a1 100644
--- a/Source/WebCore/rendering/style/RenderStyle.cpp
+++ b/Source/WebCore/rendering/style/RenderStyle.cpp
@@ -1,6 +1,7 @@
/*
* Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
* Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2011 Adobe Systems Incorporated. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -25,7 +26,6 @@
#include "ContentData.h"
#include "CursorList.h"
#include "CSSPropertyNames.h"
-#include "CSSStyleSelector.h"
#include "CSSWrapShapes.h"
#include "FontSelector.h"
#include "QuotesData.h"
@@ -34,6 +34,7 @@
#include "ScaleTransformOperation.h"
#include "ShadowData.h"
#include "StyleImage.h"
+#include "StyleResolver.h"
#if ENABLE(TOUCH_EVENTS)
#include "RenderTheme.h"
#endif
@@ -45,7 +46,7 @@ using namespace std;
namespace WebCore {
struct SameSizeAsBorderValue {
- Color m_color;
+ RGBA32 m_color;
unsigned m_width;
};
@@ -86,11 +87,12 @@ PassRefPtr<RenderStyle> RenderStyle::createDefaultStyle()
return adoptRef(new RenderStyle(true));
}
-PassRefPtr<RenderStyle> RenderStyle::createAnonymousStyle(const RenderStyle* parentStyle)
+PassRefPtr<RenderStyle> RenderStyle::createAnonymousStyleWithDisplay(const RenderStyle* parentStyle, EDisplay display)
{
RefPtr<RenderStyle> newStyle = RenderStyle::create();
newStyle->inheritFrom(parentStyle);
newStyle->inheritUnicodeBidiFrom(parentStyle);
+ newStyle->setDisplay(display);
return newStyle;
}
@@ -221,7 +223,7 @@ bool RenderStyle::operator==(const RenderStyle& o) const
bool RenderStyle::isStyleAvailable() const
{
- return this != CSSStyleSelector::styleNotYetAvailable();
+ return this != StyleResolver::styleNotYetAvailable();
}
static inline int pseudoBit(PseudoId pseudo)
@@ -418,12 +420,6 @@ StyleDifference RenderStyle::diff(const RenderStyle* other, unsigned& changedCon
#endif
}
-#if ENABLE(CSS_FILTERS)
- if (rareNonInheritedData->m_filter.get() != other->rareNonInheritedData->m_filter.get()
- && *rareNonInheritedData->m_filter.get() != *other->rareNonInheritedData->m_filter.get()) {
- return StyleDifferenceLayout;
- }
-#endif
#if ENABLE(CSS_GRID_LAYOUT)
if (rareNonInheritedData->m_grid.get() != other->rareNonInheritedData->m_grid.get()
&& rareNonInheritedData->m_gridItem.get() != other->rareNonInheritedData->m_gridItem.get())
@@ -605,6 +601,18 @@ StyleDifference RenderStyle::diff(const RenderStyle* other, unsigned& changedCon
#endif
}
+#if ENABLE(CSS_FILTERS)
+ if (rareNonInheritedData->m_filter.get() != other->rareNonInheritedData->m_filter.get()
+ && *rareNonInheritedData->m_filter.get() != *other->rareNonInheritedData->m_filter.get()) {
+#if USE(ACCELERATED_COMPOSITING)
+ changedContextSensitiveProperties |= ContextSensitivePropertyFilter;
+ // Don't return; keep looking for another change.
+#else
+ return StyleDifferenceRepaintLayer;
+#endif
+ }
+#endif
+
if (rareNonInheritedData->m_mask != other->rareNonInheritedData->m_mask
|| rareNonInheritedData->m_maskBoxImage != other->rareNonInheritedData->m_maskBoxImage)
return StyleDifferenceRepaintLayer;
@@ -769,39 +777,70 @@ void RenderStyle::setContent(QuoteType quote, bool add)
rareNonInheritedData.access()->m_content = ContentData::create(quote);
}
-
-void RenderStyle::applyTransform(TransformationMatrix& transform, const LayoutSize& borderBoxSize, ApplyTransformOrigin applyOrigin) const
+
+inline bool requireTransformOrigin(const Vector<RefPtr<TransformOperation> >& transformOperations, RenderStyle::ApplyTransformOrigin applyOrigin)
{
// transform-origin brackets the transform with translate operations.
// Optimize for the case where the only transform is a translation, since the transform-origin is irrelevant
// in that case.
- bool applyTransformOrigin = false;
- unsigned s = rareNonInheritedData->m_transform->m_operations.operations().size();
- unsigned i;
- if (applyOrigin == IncludeTransformOrigin) {
- for (i = 0; i < s; i++) {
- TransformOperation::OperationType type = rareNonInheritedData->m_transform->m_operations.operations()[i]->getOperationType();
- if (type != TransformOperation::TRANSLATE_X
- && type != TransformOperation::TRANSLATE_Y
- && type != TransformOperation::TRANSLATE
- && type != TransformOperation::TRANSLATE_Z
- && type != TransformOperation::TRANSLATE_3D
- ) {
- applyTransformOrigin = true;
- break;
- }
- }
- }
+ if (applyOrigin != RenderStyle::IncludeTransformOrigin)
+ return false;
- if (applyTransformOrigin) {
- transform.translate3d(transformOriginX().calcFloatValue(borderBoxSize.width()), transformOriginY().calcFloatValue(borderBoxSize.height()), transformOriginZ());
+ unsigned size = transformOperations.size();
+ for (unsigned i = 0; i < size; ++i) {
+ TransformOperation::OperationType type = transformOperations[i]->getOperationType();
+ if (type != TransformOperation::TRANSLATE_X
+ && type != TransformOperation::TRANSLATE_Y
+ && type != TransformOperation::TRANSLATE
+ && type != TransformOperation::TRANSLATE_Z
+ && type != TransformOperation::TRANSLATE_3D)
+ return true;
}
+
+ return false;
+}
+
+void RenderStyle::applyTransform(TransformationMatrix& transform, const LayoutSize& borderBoxSize, ApplyTransformOrigin applyOrigin) const
+{
+ // FIXME: when subpixel layout is supported (bug 71143) the body of this function could be replaced by
+ // applyTransform(transform, FloatRect(FloatPoint(), borderBoxSize), applyOrigin);
+
+ const Vector<RefPtr<TransformOperation> >& transformOperations = rareNonInheritedData->m_transform->m_operations.operations();
+ bool applyTransformOrigin = requireTransformOrigin(transformOperations, applyOrigin);
+
+ if (applyTransformOrigin)
+ transform.translate3d(floatValueForLength(transformOriginX(), borderBoxSize.width()), floatValueForLength(transformOriginY(), borderBoxSize.height()), transformOriginZ());
- for (i = 0; i < s; i++)
- rareNonInheritedData->m_transform->m_operations.operations()[i]->apply(transform, borderBoxSize);
+ unsigned size = transformOperations.size();
+ for (unsigned i = 0; i < size; ++i)
+ transformOperations[i]->apply(transform, borderBoxSize);
+ if (applyTransformOrigin)
+ transform.translate3d(-floatValueForLength(transformOriginX(), borderBoxSize.width()), -floatValueForLength(transformOriginY(), borderBoxSize.height()), -transformOriginZ());
+}
+
+void RenderStyle::applyTransform(TransformationMatrix& transform, const FloatRect& boundingBox, ApplyTransformOrigin applyOrigin) const
+{
+ const Vector<RefPtr<TransformOperation> >& transformOperations = rareNonInheritedData->m_transform->m_operations.operations();
+ bool applyTransformOrigin = requireTransformOrigin(transformOperations, applyOrigin);
+
+ float offsetX = transformOriginX().type() == Percent ? boundingBox.x() : 0;
+ float offsetY = transformOriginY().type() == Percent ? boundingBox.y() : 0;
+
+ if (applyTransformOrigin) {
+ transform.translate3d(floatValueForLength(transformOriginX(), boundingBox.width()) + offsetX,
+ floatValueForLength(transformOriginY(), boundingBox.height()) + offsetY,
+ transformOriginZ());
+ }
+
+ unsigned size = transformOperations.size();
+ for (unsigned i = 0; i < size; ++i)
+ transformOperations[i]->apply(transform, boundingBox.size());
+
if (applyTransformOrigin) {
- transform.translate3d(-transformOriginX().calcFloatValue(borderBoxSize.width()), -transformOriginY().calcFloatValue(borderBoxSize.height()), -transformOriginZ());
+ transform.translate3d(-floatValueForLength(transformOriginX(), boundingBox.width()) - offsetX,
+ -floatValueForLength(transformOriginY(), boundingBox.height()) - offsetY,
+ -transformOriginZ());
}
}
@@ -842,17 +881,17 @@ void RenderStyle::setBoxShadow(PassOwnPtr<ShadowData> shadowData, bool add)
rareData->m_boxShadow = shadowData;
}
-static RoundedRect::Radii calcRadiiFor(const BorderData& border, LayoutSize size)
+static RoundedRect::Radii calcRadiiFor(const BorderData& border, IntSize size, RenderView* renderView)
{
return RoundedRect::Radii(
- IntSize(border.topLeft().width().calcValue(size.width()),
- border.topLeft().height().calcValue(size.height())),
- IntSize(border.topRight().width().calcValue(size.width()),
- border.topRight().height().calcValue(size.height())),
- IntSize(border.bottomLeft().width().calcValue(size.width()),
- border.bottomLeft().height().calcValue(size.height())),
- IntSize(border.bottomRight().width().calcValue(size.width()),
- border.bottomRight().height().calcValue(size.height())));
+ IntSize(valueForLength(border.topLeft().width(), size.width(), renderView),
+ valueForLength(border.topLeft().height(), size.height(), renderView)),
+ IntSize(valueForLength(border.topRight().width(), size.width(), renderView),
+ valueForLength(border.topRight().height(), size.height(), renderView)),
+ IntSize(valueForLength(border.bottomLeft().width(), size.width(), renderView),
+ valueForLength(border.bottomLeft().height(), size.height(), renderView)),
+ IntSize(valueForLength(border.bottomRight().width(), size.width(), renderView),
+ valueForLength(border.bottomRight().height(), size.height(), renderView)));
}
static float calcConstraintScaleFor(const IntRect& rect, const RoundedRect::Radii& radii)
@@ -887,12 +926,13 @@ static float calcConstraintScaleFor(const IntRect& rect, const RoundedRect::Radi
return factor;
}
-RoundedRect RenderStyle::getRoundedBorderFor(const LayoutRect& borderRect, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
+RoundedRect RenderStyle::getRoundedBorderFor(const LayoutRect& borderRect, RenderView* renderView, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
{
- RoundedRect roundedRect(pixelSnappedIntRect(borderRect));
+ IntRect snappedBorderRect(pixelSnappedIntRect(borderRect));
+ RoundedRect roundedRect(snappedBorderRect);
if (hasBorderRadius()) {
- RoundedRect::Radii radii = calcRadiiFor(surround->border, borderRect.size());
- radii.scale(calcConstraintScaleFor(borderRect, radii));
+ RoundedRect::Radii radii = calcRadiiFor(surround->border, snappedBorderRect.size(), renderView);
+ radii.scale(calcConstraintScaleFor(snappedBorderRect, radii));
roundedRect.includeLogicalEdges(radii, isHorizontalWritingMode(), includeLogicalLeftEdge, includeLogicalRightEdge);
}
return roundedRect;
@@ -1095,12 +1135,12 @@ AnimationList* RenderStyle::accessTransitions()
return rareNonInheritedData->m_transitions.get();
}
-const Animation* RenderStyle::transitionForProperty(int property) const
+const Animation* RenderStyle::transitionForProperty(CSSPropertyID property) const
{
if (transitions()) {
for (size_t i = 0; i < transitions()->size(); ++i) {
const Animation* p = transitions()->animation(i);
- if (p->property() == cAnimateAll || p->property() == property) {
+ if (p->animationMode() == Animation::AnimateAll || p->property() == property) {
return p;
}
}
@@ -1130,10 +1170,10 @@ void RenderStyle::getShadowExtent(const ShadowData* shadow, LayoutUnit &top, Lay
continue;
int blurAndSpread = shadow->blur() + shadow->spread();
- top = min(top, shadow->y() - blurAndSpread);
- right = max(right, shadow->x() + blurAndSpread);
- bottom = max(bottom, shadow->y() + blurAndSpread);
- left = min(left, shadow->x() - blurAndSpread);
+ top = min<LayoutUnit>(top, shadow->y() - blurAndSpread);
+ right = max<LayoutUnit>(right, shadow->x() + blurAndSpread);
+ bottom = max<LayoutUnit>(bottom, shadow->y() + blurAndSpread);
+ left = min<LayoutUnit>(left, shadow->x() - blurAndSpread);
}
}
@@ -1147,8 +1187,8 @@ void RenderStyle::getShadowHorizontalExtent(const ShadowData* shadow, LayoutUnit
continue;
int blurAndSpread = shadow->blur() + shadow->spread();
- left = min(left, shadow->x() - blurAndSpread);
- right = max(right, shadow->x() + blurAndSpread);
+ left = min<LayoutUnit>(left, shadow->x() - blurAndSpread);
+ right = max<LayoutUnit>(right, shadow->x() + blurAndSpread);
}
}
@@ -1162,8 +1202,8 @@ void RenderStyle::getShadowVerticalExtent(const ShadowData* shadow, LayoutUnit &
continue;
int blurAndSpread = shadow->blur() + shadow->spread();
- top = min(top, shadow->y() - blurAndSpread);
- bottom = max(bottom, shadow->y() + blurAndSpread);
+ top = min<LayoutUnit>(top, shadow->y() - blurAndSpread);
+ bottom = max<LayoutUnit>(bottom, shadow->y() + blurAndSpread);
}
}
diff --git a/Source/WebCore/rendering/style/RenderStyle.h b/Source/WebCore/rendering/style/RenderStyle.h
index 55151d3ec..d57551497 100644
--- a/Source/WebCore/rendering/style/RenderStyle.h
+++ b/Source/WebCore/rendering/style/RenderStyle.h
@@ -39,6 +39,7 @@
#include "GraphicsTypes.h"
#include "Length.h"
#include "LengthBox.h"
+#include "LengthFunctions.h"
#include "LengthSize.h"
#include "LineClampValue.h"
#include "NinePieceImage.h"
@@ -95,18 +96,22 @@ template<typename T, typename U> inline bool compareEqual(const T& t, const U& u
if (!compareEqual(group->variable, value)) \
group.access()->variable = value;
+#define SET_BORDERVALUE_COLOR(group, variable, value) \
+ if (!compareEqual(group->variable.color(), value)) \
+ group.access()->variable.setColor(value);
+
namespace WebCore {
using std::max;
class BorderData;
-class CSSStyleSelector;
class CounterContent;
class CursorList;
class IntRect;
class Pair;
class ShadowData;
class StyleImage;
+class StyleResolver;
class TransformationMatrix;
class ContentData;
@@ -114,15 +119,15 @@ class ContentData;
typedef Vector<RefPtr<RenderStyle>, 4> PseudoStyleCache;
class RenderStyle: public RefCounted<RenderStyle> {
- friend class AnimationBase; // Used by CSS animations. We can't allow them to animate based off visited colors.
+ friend class CSSPropertyAnimation; // Used by CSS animations. We can't allow them to animate based off visited colors.
friend class ApplyStyleCommand; // Editing has to only reveal unvisited info.
friend class EditingStyle; // Editing has to only reveal unvisited info.
- friend class CSSStyleApplyProperty; // Sets members directly.
- friend class CSSStyleSelector; // Sets members directly.
friend class CSSComputedStyleDeclaration; // Ignores visited styles, so needs to be able to see unvisited info.
friend class PropertyWrapperMaybeInvalidColor; // Used by CSS animations. We can't allow them to animate based off visited colors.
friend class RenderSVGResource; // FIXME: Needs to alter the visited state by hand. Should clean the SVG code up and move it into RenderStyle perhaps.
friend class RenderTreeAsText; // FIXME: Only needed so the render tree can keep lying and dump the wrong colors. Rebaselining would allow this to be yanked.
+ friend class StyleBuilder; // Sets members directly.
+ friend class StyleResolver; // Sets members directly.
protected:
class RenderStyleBitfields {
@@ -214,7 +219,7 @@ protected:
DataRef<SVGRenderStyle> m_svgStyle;
#endif
-// !START SYNC!: Keep this in sync with the copy constructor in RenderStyle.cpp and implicitlyInherited() in CSSStyleSelector.cpp
+// !START SYNC!: Keep this in sync with the copy constructor in RenderStyle.cpp and implicitlyInherited() in StyleResolver.cpp
// inherit
struct InheritedFlags {
@@ -385,7 +390,7 @@ private:
public:
static PassRefPtr<RenderStyle> create();
static PassRefPtr<RenderStyle> createDefaultStyle();
- static PassRefPtr<RenderStyle> createAnonymousStyle(const RenderStyle* parentStyle);
+ static PassRefPtr<RenderStyle> createAnonymousStyleWithDisplay(const RenderStyle* parentStyle, EDisplay);
static PassRefPtr<RenderStyle> clone(const RenderStyle*);
void inheritFrom(const RenderStyle* inheritParent);
@@ -460,7 +465,7 @@ public:
}
#if ENABLE(CSS_FILTERS)
- void getFilterOutsets(LayoutUnit& top, LayoutUnit& right, LayoutUnit& bottom, LayoutUnit& left) const
+ void getFilterOutsets(int& top, int& right, int& bottom, int& left) const
{
if (hasFilter())
filter().getOutsets(top, right, bottom, left);
@@ -617,7 +622,7 @@ public:
bool isLeftToRightDirection() const { return direction() == LTR; }
Length lineHeight() const { return inherited->line_height; }
- int computedLineHeight() const
+ int computedLineHeight(RenderView* renderView = 0) const
{
const Length& lh = inherited->line_height;
@@ -626,7 +631,10 @@ public:
return fontMetrics().lineSpacing();
if (lh.isPercent())
- return lh.calcMinValue(fontSize());
+ return minimumValueForLength(lh, fontSize());
+
+ if (lh.isViewportPercentage())
+ return valueForLength(lh, 0, renderView);
return lh.value();
}
@@ -799,10 +807,9 @@ public:
EBoxOrient boxOrient() const { return static_cast<EBoxOrient>(rareNonInheritedData->m_deprecatedFlexibleBox->orient); }
EBoxPack boxPack() const { return static_cast<EBoxPack>(rareNonInheritedData->m_deprecatedFlexibleBox->pack); }
- float flexboxWidthPositiveFlex() const { return rareNonInheritedData->m_flexibleBox->m_widthPositiveFlex; }
- float flexboxWidthNegativeFlex() const { return rareNonInheritedData->m_flexibleBox->m_widthNegativeFlex; }
- float flexboxHeightPositiveFlex() const { return rareNonInheritedData->m_flexibleBox->m_heightPositiveFlex; }
- float flexboxHeightNegativeFlex() const { return rareNonInheritedData->m_flexibleBox->m_heightNegativeFlex; }
+ float positiveFlex() const { return rareNonInheritedData->m_flexibleBox->m_positiveFlex; }
+ float negativeFlex() const { return rareNonInheritedData->m_flexibleBox->m_negativeFlex; }
+ Length flexPreferredSize() const { return rareNonInheritedData->m_flexibleBox->m_preferredSize; }
int flexOrder() const { return rareNonInheritedData->m_flexibleBox->m_flexOrder; }
EFlexPack flexPack() const { return static_cast<EFlexPack>(rareNonInheritedData->m_flexibleBox->m_flexPack); }
EFlexAlign flexAlign() const { return static_cast<EFlexAlign>(rareNonInheritedData->m_flexibleBox->m_flexAlign); }
@@ -811,6 +818,7 @@ public:
bool isColumnFlexDirection() const { return flexDirection() == FlowColumn || flexDirection() == FlowColumnReverse; }
bool isReverseFlexDirection() const { return flexDirection() == FlowRowReverse || flexDirection() == FlowColumnReverse; }
EFlexWrap flexWrap() const { return static_cast<EFlexWrap>(rareNonInheritedData->m_flexibleBox->m_flexWrap); }
+ EFlexLinePack flexLinePack() const { return static_cast<EFlexLinePack>(rareNonInheritedData->m_flexibleBox->m_flexLinePack); }
#if ENABLE(CSS_GRID_LAYOUT)
const Vector<Length>& gridColumns() const { return rareNonInheritedData->m_grid->m_gridColumns; }
@@ -894,6 +902,7 @@ public:
enum ApplyTransformOrigin { IncludeTransformOrigin, ExcludeTransformOrigin };
void applyTransform(TransformationMatrix&, const LayoutSize& borderBoxSize, ApplyTransformOrigin = IncludeTransformOrigin) const;
+ void applyTransform(TransformationMatrix&, const FloatRect& boundingBox, ApplyTransformOrigin = IncludeTransformOrigin) const;
void setPageScaleTransform(float);
bool hasMask() const { return rareNonInheritedData->m_mask.hasImage() || rareNonInheritedData->m_maskBoxImage.hasImage(); }
@@ -925,7 +934,7 @@ public:
bool hasTransitions() const { return rareNonInheritedData->m_transitions && rareNonInheritedData->m_transitions->size() > 0; }
// return the first found Animation (including 'all' transitions)
- const Animation* transitionForProperty(int property) const;
+ const Animation* transitionForProperty(CSSPropertyID) const;
ETransformStyle3D transformStyle3D() const { return static_cast<ETransformStyle3D>(rareNonInheritedData->m_transformStyle3D); }
bool preserves3D() const { return rareNonInheritedData->m_transformStyle3D == TransformStyle3DPreserve3D; }
@@ -1058,7 +1067,7 @@ public:
setBorderRadius(LengthSize(Length(s.width(), Fixed), Length(s.height(), Fixed)));
}
- RoundedRect getRoundedBorderFor(const LayoutRect& borderRect, bool includeLogicalLeftEdge = true, bool includeLogicalRightEdge = true) const;
+ RoundedRect getRoundedBorderFor(const LayoutRect& borderRect, RenderView* = 0, bool includeLogicalLeftEdge = true, bool includeLogicalRightEdge = true) const;
RoundedRect getRoundedInnerBorderFor(const LayoutRect& borderRect, bool includeLogicalLeftEdge = true, bool includeLogicalRightEdge = true) const;
RoundedRect getRoundedInnerBorderFor(const LayoutRect& borderRect,
@@ -1066,21 +1075,21 @@ public:
void setBorderLeftWidth(unsigned v) { SET_VAR(surround, border.m_left.m_width, v) }
void setBorderLeftStyle(EBorderStyle v) { SET_VAR(surround, border.m_left.m_style, v) }
- void setBorderLeftColor(const Color& v) { SET_VAR(surround, border.m_left.m_color, v) }
+ void setBorderLeftColor(const Color& v) { SET_BORDERVALUE_COLOR(surround, border.m_left, v) }
void setBorderRightWidth(unsigned v) { SET_VAR(surround, border.m_right.m_width, v) }
void setBorderRightStyle(EBorderStyle v) { SET_VAR(surround, border.m_right.m_style, v) }
- void setBorderRightColor(const Color& v) { SET_VAR(surround, border.m_right.m_color, v) }
+ void setBorderRightColor(const Color& v) { SET_BORDERVALUE_COLOR(surround, border.m_right, v) }
void setBorderTopWidth(unsigned v) { SET_VAR(surround, border.m_top.m_width, v) }
void setBorderTopStyle(EBorderStyle v) { SET_VAR(surround, border.m_top.m_style, v) }
- void setBorderTopColor(const Color& v) { SET_VAR(surround, border.m_top.m_color, v) }
+ void setBorderTopColor(const Color& v) { SET_BORDERVALUE_COLOR(surround, border.m_top, v) }
void setBorderBottomWidth(unsigned v) { SET_VAR(surround, border.m_bottom.m_width, v) }
void setBorderBottomStyle(EBorderStyle v) { SET_VAR(surround, border.m_bottom.m_style, v) }
- void setBorderBottomColor(const Color& v) { SET_VAR(surround, border.m_bottom.m_color, v) }
+ void setBorderBottomColor(const Color& v) { SET_BORDERVALUE_COLOR(surround, border.m_bottom, v) }
void setOutlineWidth(unsigned short v) { SET_VAR(m_background, m_outline.m_width, v) }
void setOutlineStyleIsAuto(OutlineIsAuto isAuto) { SET_VAR(m_background, m_outline.m_isAuto, isAuto) }
void setOutlineStyle(EBorderStyle v) { SET_VAR(m_background, m_outline.m_style, v) }
- void setOutlineColor(const Color& v) { SET_VAR(m_background, m_outline.m_color, v) }
+ void setOutlineColor(const Color& v) { SET_BORDERVALUE_COLOR(m_background, m_outline, v) }
void setOverflowX(EOverflow v) { noninherited_flags._overflowX = v; }
void setOverflowY(EOverflow v) { noninherited_flags._overflowY = v; }
@@ -1223,7 +1232,7 @@ public:
void setTextStrokeWidth(float w) { SET_VAR(rareInheritedData, textStrokeWidth, w) }
void setTextFillColor(const Color& c) { SET_VAR(rareInheritedData, textFillColor, c) }
void setColorSpace(ColorSpace space) { SET_VAR(rareInheritedData, colorSpace, space) }
- void setOpacity(float f) { SET_VAR(rareNonInheritedData, opacity, f); }
+ void setOpacity(float f) { float v = clampTo<float>(f, 0, 1); SET_VAR(rareNonInheritedData, opacity, v); }
void setAppearance(ControlPart a) { SET_VAR(rareNonInheritedData, m_appearance, a); }
// For valid values of box-align see http://www.w3.org/TR/2009/WD-css3-flexbox-20090723/#alignment
void setBoxAlign(EBoxAlignment a) { SET_VAR(rareNonInheritedData.access()->m_deprecatedFlexibleBox, align, a); }
@@ -1237,16 +1246,16 @@ public:
void setBoxShadow(PassOwnPtr<ShadowData>, bool add = false);
void setBoxReflect(PassRefPtr<StyleReflection> reflect) { if (rareNonInheritedData->m_boxReflect != reflect) rareNonInheritedData.access()->m_boxReflect = reflect; }
void setBoxSizing(EBoxSizing s) { SET_VAR(m_box, m_boxSizing, s); }
- void setFlexboxWidthPositiveFlex(float f) { SET_VAR(rareNonInheritedData.access()->m_flexibleBox, m_widthPositiveFlex, f); }
- void setFlexboxWidthNegativeFlex(float f) { SET_VAR(rareNonInheritedData.access()->m_flexibleBox, m_widthNegativeFlex, f); }
- void setFlexboxHeightPositiveFlex(float f) { SET_VAR(rareNonInheritedData.access()->m_flexibleBox, m_heightPositiveFlex, f); }
- void setFlexboxHeightNegativeFlex(float f) { SET_VAR(rareNonInheritedData.access()->m_flexibleBox, m_heightNegativeFlex, f); }
+ void setPositiveFlex(float f) { SET_VAR(rareNonInheritedData.access()->m_flexibleBox, m_positiveFlex, f); }
+ void setNegativeFlex(float f) { SET_VAR(rareNonInheritedData.access()->m_flexibleBox, m_negativeFlex, f); }
+ void setFlexPreferredSize(Length l) { SET_VAR(rareNonInheritedData.access()->m_flexibleBox, m_preferredSize, l); }
void setFlexOrder(int o) { SET_VAR(rareNonInheritedData.access()->m_flexibleBox, m_flexOrder, o); }
void setFlexPack(EFlexPack p) { SET_VAR(rareNonInheritedData.access()->m_flexibleBox, m_flexPack, p); }
void setFlexAlign(EFlexAlign a) { SET_VAR(rareNonInheritedData.access()->m_flexibleBox, m_flexAlign, a); }
void setFlexItemAlign(EFlexAlign a) { SET_VAR(rareNonInheritedData.access()->m_flexibleBox, m_flexItemAlign, a); }
void setFlexDirection(EFlexDirection direction) { SET_VAR(rareNonInheritedData.access()->m_flexibleBox, m_flexDirection, direction); }
void setFlexWrap(EFlexWrap w) { SET_VAR(rareNonInheritedData.access()->m_flexibleBox, m_flexWrap, w); }
+ void setFlexLinePack(EFlexLinePack p) { SET_VAR(rareNonInheritedData.access()->m_flexibleBox, m_flexLinePack, p); }
#if ENABLE(CSS_GRID_LAYOUT)
void setGridColumns(const Vector<Length>& lengths) { SET_VAR(rareNonInheritedData.access()->m_grid, m_gridColumns, lengths); }
void setGridRows(const Vector<Length>& lengths) { SET_VAR(rareNonInheritedData.access()->m_grid, m_gridRows, lengths); }
@@ -1287,7 +1296,7 @@ public:
void setHasAutoColumnCount() { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_autoCount, true); SET_VAR(rareNonInheritedData.access()->m_multiCol, m_count, 0); }
void setColumnGap(float f) { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_normalGap, false); SET_VAR(rareNonInheritedData.access()->m_multiCol, m_gap, f); }
void setHasNormalColumnGap() { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_normalGap, true); SET_VAR(rareNonInheritedData.access()->m_multiCol, m_gap, 0); }
- void setColumnRuleColor(const Color& c) { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_rule.m_color, c); }
+ void setColumnRuleColor(const Color& c) { SET_BORDERVALUE_COLOR(rareNonInheritedData.access()->m_multiCol, m_rule, c); }
void setColumnRuleStyle(EBorderStyle b) { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_rule.m_style, b); }
void setColumnRuleWidth(unsigned short w) { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_rule.m_width, w); }
void resetColumnRule() { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_rule, BorderValue()) }
@@ -1376,13 +1385,13 @@ public:
SVGRenderStyle* accessSVGStyle() { return m_svgStyle.access(); }
const SVGPaint::SVGPaintType& fillPaintType() const { return svgStyle()->fillPaintType(); }
- const Color& fillPaintColor() const { return svgStyle()->fillPaintColor(); }
+ Color fillPaintColor() const { return svgStyle()->fillPaintColor(); }
void setFillPaintColor(const Color& c) { accessSVGStyle()->setFillPaint(SVGPaint::SVG_PAINTTYPE_RGBCOLOR, c, ""); }
float fillOpacity() const { return svgStyle()->fillOpacity(); }
void setFillOpacity(float f) { accessSVGStyle()->setFillOpacity(f); }
const SVGPaint::SVGPaintType& strokePaintType() const { return svgStyle()->strokePaintType(); }
- const Color& strokePaintColor() const { return svgStyle()->strokePaintColor(); }
+ Color strokePaintColor() const { return svgStyle()->strokePaintColor(); }
void setStrokePaintColor(const Color& c) { accessSVGStyle()->setStrokePaint(SVGPaint::SVG_PAINTTYPE_RGBCOLOR, c, ""); }
float strokeOpacity() const { return svgStyle()->strokeOpacity(); }
void setStrokeOpacity(float f) { accessSVGStyle()->setStrokeOpacity(f); }
@@ -1456,9 +1465,21 @@ public:
StyleDifference diff(const RenderStyle*, unsigned& changedContextSensitiveProperties) const;
- bool isDisplayReplacedType() const { return isDisplayReplacedType(display()); }
- bool isDisplayInlineType() const { return isDisplayInlineType(display()); }
- bool isOriginalDisplayInlineType() const { return isDisplayInlineType(originalDisplay()); }
+ bool isDisplayReplacedType() const
+ {
+ return display() == INLINE_BLOCK || display() == INLINE_BOX || display() == INLINE_TABLE;
+ }
+
+ bool isDisplayInlineType() const
+ {
+ return display() == INLINE || isDisplayReplacedType();
+ }
+
+ bool isOriginalDisplayInlineType() const
+ {
+ return originalDisplay() == INLINE || originalDisplay() == INLINE_BLOCK
+ || originalDisplay() == INLINE_BOX || originalDisplay() == INLINE_TABLE;
+ }
void setWritingMode(WritingMode v) { inherited_flags.m_writingMode = v; }
@@ -1559,16 +1580,16 @@ public:
static unsigned int initialBoxOrdinalGroup() { return 1; }
static EBoxSizing initialBoxSizing() { return CONTENT_BOX; }
static StyleReflection* initialBoxReflect() { return 0; }
- static float initialFlexboxWidthPositiveFlex() { return 0; }
- static float initialFlexboxWidthNegativeFlex() { return 0; }
- static float initialFlexboxHeightPositiveFlex() { return 0; }
- static float initialFlexboxHeightNegativeFlex() { return 0; }
+ static float initialPositiveFlex() { return 0; }
+ static float initialNegativeFlex() { return 0; }
+ static Length initialFlexPreferredSize() { return Length(Auto); }
static int initialFlexOrder() { return 0; }
static EFlexPack initialFlexPack() { return PackStart; }
static EFlexAlign initialFlexAlign() { return AlignStretch; }
static EFlexAlign initialFlexItemAlign() { return AlignAuto; }
static EFlexDirection initialFlexDirection() { return FlowRow; }
static EFlexWrap initialFlexWrap() { return FlexWrapNone; }
+ static EFlexLinePack initialFlexLinePack() { return LinePackStretch; }
static int initialMarqueeLoopCount() { return -1; }
static int initialMarqueeSpeed() { return 85; }
static Length initialMarqueeIncrement() { return Length(6, Fixed); }
@@ -1709,43 +1730,37 @@ private:
return isHorizontalWritingMode() ? getImageVerticalOutsets(image, logicalTop, logicalBottom) : getImageHorizontalOutsets(image, logicalTop, logicalBottom);
}
- bool isDisplayReplacedType(EDisplay display) const
- {
- return display == INLINE_BLOCK || display == INLINE_BOX || display == INLINE_FLEXBOX || display == INLINE_TABLE;
- }
- bool isDisplayInlineType(EDisplay display) const { return display == INLINE || isDisplayReplacedType(display); }
-
// Color accessors are all private to make sure callers use visitedDependentColor instead to access them.
- const Color& invalidColor() const { static Color invalid; return invalid; }
- const Color& borderLeftColor() const { return surround->border.left().color(); }
- const Color& borderRightColor() const { return surround->border.right().color(); }
- const Color& borderTopColor() const { return surround->border.top().color(); }
- const Color& borderBottomColor() const { return surround->border.bottom().color(); }
- const Color& backgroundColor() const { return m_background->color(); }
- const Color& color() const { return inherited->color; }
- const Color& columnRuleColor() const { return rareNonInheritedData->m_multiCol->m_rule.color(); }
- const Color& outlineColor() const { return m_background->outline().color(); }
- const Color& textEmphasisColor() const { return rareInheritedData->textEmphasisColor; }
- const Color& textFillColor() const { return rareInheritedData->textFillColor; }
- const Color& textStrokeColor() const { return rareInheritedData->textStrokeColor; }
- const Color& visitedLinkColor() const { return inherited->visitedLinkColor; }
- const Color& visitedLinkBackgroundColor() const { return rareNonInheritedData->m_visitedLinkBackgroundColor; }
- const Color& visitedLinkBorderLeftColor() const { return rareNonInheritedData->m_visitedLinkBorderLeftColor; }
- const Color& visitedLinkBorderRightColor() const { return rareNonInheritedData->m_visitedLinkBorderRightColor; }
- const Color& visitedLinkBorderBottomColor() const { return rareNonInheritedData->m_visitedLinkBorderBottomColor; }
- const Color& visitedLinkBorderTopColor() const { return rareNonInheritedData->m_visitedLinkBorderTopColor; }
- const Color& visitedLinkOutlineColor() const { return rareNonInheritedData->m_visitedLinkOutlineColor; }
- const Color& visitedLinkColumnRuleColor() const { return rareNonInheritedData->m_multiCol->m_visitedLinkColumnRuleColor; }
- const Color& visitedLinkTextEmphasisColor() const { return rareInheritedData->visitedLinkTextEmphasisColor; }
- const Color& visitedLinkTextFillColor() const { return rareInheritedData->visitedLinkTextFillColor; }
- const Color& visitedLinkTextStrokeColor() const { return rareInheritedData->visitedLinkTextStrokeColor; }
+ Color invalidColor() const { static Color invalid; return invalid; }
+ Color borderLeftColor() const { return surround->border.left().color(); }
+ Color borderRightColor() const { return surround->border.right().color(); }
+ Color borderTopColor() const { return surround->border.top().color(); }
+ Color borderBottomColor() const { return surround->border.bottom().color(); }
+ Color backgroundColor() const { return m_background->color(); }
+ Color color() const { return inherited->color; }
+ Color columnRuleColor() const { return rareNonInheritedData->m_multiCol->m_rule.color(); }
+ Color outlineColor() const { return m_background->outline().color(); }
+ Color textEmphasisColor() const { return rareInheritedData->textEmphasisColor; }
+ Color textFillColor() const { return rareInheritedData->textFillColor; }
+ Color textStrokeColor() const { return rareInheritedData->textStrokeColor; }
+ Color visitedLinkColor() const { return inherited->visitedLinkColor; }
+ Color visitedLinkBackgroundColor() const { return rareNonInheritedData->m_visitedLinkBackgroundColor; }
+ Color visitedLinkBorderLeftColor() const { return rareNonInheritedData->m_visitedLinkBorderLeftColor; }
+ Color visitedLinkBorderRightColor() const { return rareNonInheritedData->m_visitedLinkBorderRightColor; }
+ Color visitedLinkBorderBottomColor() const { return rareNonInheritedData->m_visitedLinkBorderBottomColor; }
+ Color visitedLinkBorderTopColor() const { return rareNonInheritedData->m_visitedLinkBorderTopColor; }
+ Color visitedLinkOutlineColor() const { return rareNonInheritedData->m_visitedLinkOutlineColor; }
+ Color visitedLinkColumnRuleColor() const { return rareNonInheritedData->m_multiCol->m_visitedLinkColumnRuleColor; }
+ Color visitedLinkTextEmphasisColor() const { return rareInheritedData->visitedLinkTextEmphasisColor; }
+ Color visitedLinkTextFillColor() const { return rareInheritedData->visitedLinkTextFillColor; }
+ Color visitedLinkTextStrokeColor() const { return rareInheritedData->visitedLinkTextStrokeColor; }
Color colorIncludingFallback(int colorProperty, bool visitedLink) const;
#if ENABLE(SVG)
- const Color& stopColor() const { return svgStyle()->stopColor(); }
- const Color& floodColor() const { return svgStyle()->floodColor(); }
- const Color& lightingColor() const { return svgStyle()->lightingColor(); }
+ Color stopColor() const { return svgStyle()->stopColor(); }
+ Color floodColor() const { return svgStyle()->floodColor(); }
+ Color lightingColor() const { return svgStyle()->lightingColor(); }
#endif
void appendContent(PassOwnPtr<ContentData>);
@@ -1764,7 +1779,7 @@ inline int adjustForAbsoluteZoom(int value, const RenderStyle* style)
value++;
}
- return roundForImpreciseConversion<int, INT_MAX, INT_MIN>(value / zoomFactor);
+ return roundForImpreciseConversion<int>(value / zoomFactor);
}
inline float adjustFloatForAbsoluteZoom(float value, const RenderStyle* style)
diff --git a/Source/WebCore/rendering/style/RenderStyleConstants.h b/Source/WebCore/rendering/style/RenderStyleConstants.h
index aee10813a..741acc6e5 100644
--- a/Source/WebCore/rendering/style/RenderStyleConstants.h
+++ b/Source/WebCore/rendering/style/RenderStyleConstants.h
@@ -63,7 +63,8 @@ enum StyleDifference {
enum StyleDifferenceContextSensitiveProperty {
ContextSensitivePropertyNone = 0,
ContextSensitivePropertyTransform = (1 << 0),
- ContextSensitivePropertyOpacity = (1 << 1)
+ ContextSensitivePropertyOpacity = (1 << 1),
+ ContextSensitivePropertyFilter = (1 << 2)
};
// Static pseudo styles. Dynamic ones are produced on the fly.
@@ -97,7 +98,7 @@ enum EPosition {
};
enum EFloat {
- NoFloat, LeftFloat, RightFloat, PositionedFloat
+ NoFloat, LeftFloat, RightFloat
};
enum EMarginCollapse { MCOLLAPSE, MSEPARATE, MDISCARD };
@@ -171,6 +172,7 @@ enum EBoxDirection { BNORMAL, BREVERSE };
enum EFlexPack { PackStart, PackEnd, PackCenter, PackJustify, PackDistribute };
enum EFlexAlign { AlignAuto, AlignStart, AlignEnd, AlignCenter, AlignStretch, AlignBaseline };
enum EFlexDirection { FlowRow, FlowRowReverse, FlowColumn, FlowColumnReverse };
+enum EFlexLinePack { LinePackStart, LinePackEnd, LinePackCenter, LinePackJustify, LinePackDistribute, LinePackStretch };
enum EFlexWrap { FlexWrapNone, FlexWrap, FlexWrapReverse };
enum ETextSecurity {
@@ -458,7 +460,7 @@ enum LineSnap { LineSnapNone, LineSnapBaseline, LineSnapContain };
enum LineAlign { LineAlignNone, LineAlignEdges };
-enum WrapFlow { WrapFlowAuto, WrapFlowBoth, WrapFlowLeft, WrapFlowRight, WrapFlowMaximum, WrapFlowClear };
+enum WrapFlow { WrapFlowAuto, WrapFlowBoth, WrapFlowStart, WrapFlowEnd, WrapFlowMaximum, WrapFlowClear };
enum WrapThrough { WrapThroughWrap, WrapThroughNone };
diff --git a/Source/WebCore/rendering/style/SVGRenderStyle.h b/Source/WebCore/rendering/style/SVGRenderStyle.h
index 6539f719a..e8984c048 100644
--- a/Source/WebCore/rendering/style/SVGRenderStyle.h
+++ b/Source/WebCore/rendering/style/SVGRenderStyle.h
@@ -362,6 +362,7 @@ public:
bool hasFilter() const { return !filterResource().isEmpty(); }
bool hasMarkers() const { return !markerStartResource().isEmpty() || !markerMidResource().isEmpty() || !markerEndResource().isEmpty(); }
bool hasStroke() const { return strokePaintType() != SVGPaint::SVG_PAINTTYPE_NONE; }
+ bool hasVisibleStroke() const { return hasStroke() && !strokeWidth().isZero(); }
bool hasFill() const { return fillPaintType() != SVGPaint::SVG_PAINTTYPE_NONE; }
bool isVerticalWritingMode() const { return writingMode() == WM_TBRL || writingMode() == WM_TB; }
diff --git a/Source/WebCore/rendering/style/ShadowData.cpp b/Source/WebCore/rendering/style/ShadowData.cpp
index c359cbf62..f30d87f2b 100644
--- a/Source/WebCore/rendering/style/ShadowData.cpp
+++ b/Source/WebCore/rendering/style/ShadowData.cpp
@@ -27,8 +27,7 @@ using namespace std;
namespace WebCore {
ShadowData::ShadowData(const ShadowData& o)
- : m_x(o.m_x)
- , m_y(o.m_y)
+ : m_location(o.m_location)
, m_blur(o.m_blur)
, m_spread(o.m_spread)
, m_color(o.m_color)
@@ -44,8 +43,7 @@ bool ShadowData::operator==(const ShadowData& o) const
|| (m_next && o.m_next && *m_next != *o.m_next))
return false;
- return m_x == o.m_x
- && m_y == o.m_y
+ return m_location == o.m_location
&& m_blur == o.m_blur
&& m_spread == o.m_spread
&& m_style == o.m_style
@@ -53,7 +51,7 @@ bool ShadowData::operator==(const ShadowData& o) const
&& m_isWebkitBoxShadow == o.m_isWebkitBoxShadow;
}
-static inline void calculateShadowExtent(const ShadowData* shadow, int additionalOutlineSize, LayoutUnit& shadowLeft, LayoutUnit& shadowRight, LayoutUnit& shadowTop, LayoutUnit& shadowBottom)
+static inline void calculateShadowExtent(const ShadowData* shadow, int additionalOutlineSize, int& shadowLeft, int& shadowRight, int& shadowTop, int& shadowBottom)
{
do {
int blurAndSpread = shadow->blur() + shadow->spread() + additionalOutlineSize;
@@ -68,12 +66,12 @@ static inline void calculateShadowExtent(const ShadowData* shadow, int additiona
} while (shadow);
}
-void ShadowData::adjustRectForShadow(IntRect& rect, int additionalOutlineSize) const
+void ShadowData::adjustRectForShadow(LayoutRect& rect, int additionalOutlineSize) const
{
- LayoutUnit shadowLeft = 0;
- LayoutUnit shadowRight = 0;
- LayoutUnit shadowTop = 0;
- LayoutUnit shadowBottom = 0;
+ int shadowLeft = 0;
+ int shadowRight = 0;
+ int shadowTop = 0;
+ int shadowBottom = 0;
calculateShadowExtent(this, additionalOutlineSize, shadowLeft, shadowRight, shadowTop, shadowBottom);
rect.move(shadowLeft, shadowTop);
@@ -83,10 +81,10 @@ void ShadowData::adjustRectForShadow(IntRect& rect, int additionalOutlineSize) c
void ShadowData::adjustRectForShadow(FloatRect& rect, int additionalOutlineSize) const
{
- LayoutUnit shadowLeft = 0;
- LayoutUnit shadowRight = 0;
- LayoutUnit shadowTop = 0;
- LayoutUnit shadowBottom = 0;
+ int shadowLeft = 0;
+ int shadowRight = 0;
+ int shadowTop = 0;
+ int shadowBottom = 0;
calculateShadowExtent(this, additionalOutlineSize, shadowLeft, shadowRight, shadowTop, shadowBottom);
rect.move(shadowLeft, shadowTop);
diff --git a/Source/WebCore/rendering/style/ShadowData.h b/Source/WebCore/rendering/style/ShadowData.h
index fea8d3d02..b8df95d88 100644
--- a/Source/WebCore/rendering/style/ShadowData.h
+++ b/Source/WebCore/rendering/style/ShadowData.h
@@ -40,18 +40,15 @@ class ShadowData {
WTF_MAKE_FAST_ALLOCATED;
public:
ShadowData()
- : m_x(0)
- , m_y(0)
- , m_blur(0)
+ : m_blur(0)
, m_spread(0)
, m_style(Normal)
, m_isWebkitBoxShadow(false)
{
}
- ShadowData(LayoutUnit x, LayoutUnit y, int blur, int spread, ShadowStyle style, bool isWebkitBoxShadow, const Color& color)
- : m_x(x)
- , m_y(y)
+ ShadowData(const IntPoint& location, int blur, int spread, ShadowStyle style, bool isWebkitBoxShadow, const Color& color)
+ : m_location(location)
, m_blur(blur)
, m_spread(spread)
, m_color(color)
@@ -68,8 +65,9 @@ public:
return !(*this == o);
}
- LayoutUnit x() const { return m_x; }
- LayoutUnit y() const { return m_y; }
+ int x() const { return m_location.x(); }
+ int y() const { return m_location.y(); }
+ IntPoint location() const { return m_location; }
int blur() const { return m_blur; }
int spread() const { return m_spread; }
ShadowStyle style() const { return m_style; }
@@ -79,12 +77,11 @@ public:
const ShadowData* next() const { return m_next.get(); }
void setNext(PassOwnPtr<ShadowData> shadow) { m_next = shadow; }
- void adjustRectForShadow(IntRect&, int additionalOutlineSize = 0) const;
+ void adjustRectForShadow(LayoutRect&, int additionalOutlineSize = 0) const;
void adjustRectForShadow(FloatRect&, int additionalOutlineSize = 0) const;
private:
- LayoutUnit m_x;
- LayoutUnit m_y;
+ IntPoint m_location;
int m_blur;
int m_spread;
Color m_color;
diff --git a/Source/WebCore/rendering/style/StyleCachedImageSet.cpp b/Source/WebCore/rendering/style/StyleCachedImageSet.cpp
new file mode 100644
index 000000000..f5071d169
--- /dev/null
+++ b/Source/WebCore/rendering/style/StyleCachedImageSet.cpp
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "StyleCachedImageSet.h"
+
+#if ENABLE(CSS_IMAGE_SET)
+
+#include "CSSImageSetValue.h"
+#include "CachedImage.h"
+#include "RenderObject.h"
+
+namespace WebCore {
+
+StyleCachedImageSet::StyleCachedImageSet(CachedImage* image, float imageScaleFactor, CSSImageSetValue* value)
+ : m_bestFitImage(image)
+ , m_imageScaleFactor(imageScaleFactor)
+ , m_imageSetValue(value)
+{
+ m_isCachedImageSet = true;
+ m_bestFitImage->addClient(this);
+}
+
+
+StyleCachedImageSet::~StyleCachedImageSet()
+{
+ m_bestFitImage->removeClient(this);
+}
+
+PassRefPtr<CSSValue> StyleCachedImageSet::cssValue() const
+{
+ return m_imageSetValue;
+}
+
+bool StyleCachedImageSet::canRender(const RenderObject* renderer, float multiplier) const
+{
+ return m_bestFitImage->canRender(renderer, multiplier);
+}
+
+bool StyleCachedImageSet::isLoaded() const
+{
+ return m_bestFitImage->isLoaded();
+}
+
+bool StyleCachedImageSet::errorOccurred() const
+{
+ return m_bestFitImage->errorOccurred();
+}
+
+IntSize StyleCachedImageSet::imageSize(const RenderObject* renderer, float multiplier) const
+{
+ IntSize scaledImageSize = m_bestFitImage->imageSizeForRenderer(renderer, multiplier);
+ scaledImageSize.scale(1 / m_imageScaleFactor);
+ return scaledImageSize;
+}
+
+bool StyleCachedImageSet::imageHasRelativeWidth() const
+{
+ return m_bestFitImage->imageHasRelativeWidth();
+}
+
+bool StyleCachedImageSet::imageHasRelativeHeight() const
+{
+ return m_bestFitImage->imageHasRelativeHeight();
+}
+
+void StyleCachedImageSet::computeIntrinsicDimensions(const RenderObject*, Length& intrinsicWidth, Length& intrinsicHeight, FloatSize& intrinsicRatio)
+{
+ m_bestFitImage->computeIntrinsicDimensions(intrinsicWidth, intrinsicHeight, intrinsicRatio);
+}
+
+bool StyleCachedImageSet::usesImageContainerSize() const
+{
+ return m_bestFitImage->usesImageContainerSize();
+}
+
+void StyleCachedImageSet::setContainerSizeForRenderer(const RenderObject* renderer, const IntSize& imageContainerSize, float imageContainerZoomFactor)
+{
+ m_bestFitImage->setContainerSizeForRenderer(renderer, imageContainerSize, imageContainerZoomFactor);
+}
+
+void StyleCachedImageSet::addClient(RenderObject* renderer)
+{
+ m_bestFitImage->addClient(renderer);
+}
+
+void StyleCachedImageSet::removeClient(RenderObject* renderer)
+{
+ m_bestFitImage->removeClientForRenderer(renderer);
+}
+
+PassRefPtr<Image> StyleCachedImageSet::image(RenderObject* renderer, const IntSize&) const
+{
+ return m_bestFitImage->imageForRenderer(renderer);
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(CSS_IMAGE_SET)
diff --git a/Source/WebCore/rendering/style/StyleCachedImageSet.h b/Source/WebCore/rendering/style/StyleCachedImageSet.h
new file mode 100644
index 000000000..d35947fb3
--- /dev/null
+++ b/Source/WebCore/rendering/style/StyleCachedImageSet.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef StyleCachedImageSet_h
+#define StyleCachedImageSet_h
+
+#if ENABLE(CSS_IMAGE_SET)
+
+#include "CachedImage.h"
+#include "CachedResourceHandle.h"
+#include "StyleImage.h"
+
+namespace WebCore {
+
+class CachedImage;
+class CSSImageSetValue;
+
+// This class keeps one cached image and has access to a set of alternatives.
+
+class StyleCachedImageSet : public StyleImage, private CachedImageClient {
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ static PassRefPtr<StyleCachedImageSet> create(CachedImage* image, float imageScaleFactor, CSSImageSetValue* value)
+ {
+ return adoptRef(new StyleCachedImageSet(image, imageScaleFactor, value));
+ }
+ virtual ~StyleCachedImageSet();
+
+ virtual PassRefPtr<CSSValue> cssValue() const;
+
+ // FIXME: This is used by StyleImage for equals comparison, but this implementation
+ // only looks at the image from the set that we have loaded. I'm not sure if that is
+ // meaningful enough or not.
+ virtual WrappedImagePtr data() const { return m_bestFitImage.get(); }
+
+ CachedImage* cachedImage() const { return m_bestFitImage.get(); }
+
+ virtual bool canRender(const RenderObject*, float multiplier) const;
+ virtual bool isLoaded() const;
+ virtual bool errorOccurred() const;
+ virtual IntSize imageSize(const RenderObject*, float multiplier) const;
+ virtual bool imageHasRelativeWidth() const;
+ virtual bool imageHasRelativeHeight() const;
+ virtual void computeIntrinsicDimensions(const RenderObject*, Length& intrinsicWidth, Length& intrinsicHeight, FloatSize& intrinsicRatio);
+ virtual bool usesImageContainerSize() const;
+ virtual void setContainerSizeForRenderer(const RenderObject*, const IntSize&, float);
+ virtual void addClient(RenderObject*);
+ virtual void removeClient(RenderObject*);
+ virtual PassRefPtr<Image> image(RenderObject*, const IntSize&) const;
+ virtual float imageScaleFactor() const { return m_imageScaleFactor; }
+
+private:
+ StyleCachedImageSet(CachedImage*, float imageScaleFactor, CSSImageSetValue*);
+
+ CachedResourceHandle<CachedImage> m_bestFitImage;
+ float m_imageScaleFactor;
+ CSSImageSetValue* m_imageSetValue; // Not retained; it owns us.
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(CSS_IMAGE_SET)
+
+#endif // StyleCachedImageSet_h
diff --git a/Source/WebCore/rendering/style/StyleCustomFilterProgram.h b/Source/WebCore/rendering/style/StyleCustomFilterProgram.h
index b6eec7470..bff09a98c 100644
--- a/Source/WebCore/rendering/style/StyleCustomFilterProgram.h
+++ b/Source/WebCore/rendering/style/StyleCustomFilterProgram.h
@@ -113,6 +113,16 @@ public:
if (isLoaded())
notifyClients();
}
+
+ CachedShader* cachedVertexShader() const { return m_vertexShader ? m_vertexShader->cachedShader() : 0; }
+ CachedShader* cachedFragmentShader() const { return m_fragmentShader ? m_fragmentShader->cachedShader() : 0; }
+
+ virtual bool operator==(const CustomFilterProgram& o) const
+ {
+ // The following cast is ugly, but StyleCustomFilterProgram is the single implementation of CustomFilterProgram.
+ const StyleCustomFilterProgram* other = static_cast<const StyleCustomFilterProgram*>(&o);
+ return cachedVertexShader() == other->cachedVertexShader() && cachedFragmentShader() == other->cachedFragmentShader();
+ }
private:
StyleCustomFilterProgram(PassRefPtr<StyleShader> vertexShader, PassRefPtr<StyleShader> fragmentShader)
diff --git a/Source/WebCore/rendering/style/StyleFlexibleBoxData.cpp b/Source/WebCore/rendering/style/StyleFlexibleBoxData.cpp
index de6fabdf0..62a7ee89e 100644
--- a/Source/WebCore/rendering/style/StyleFlexibleBoxData.cpp
+++ b/Source/WebCore/rendering/style/StyleFlexibleBoxData.cpp
@@ -31,40 +31,40 @@
namespace WebCore {
StyleFlexibleBoxData::StyleFlexibleBoxData()
- : m_widthPositiveFlex(RenderStyle::initialFlexboxWidthPositiveFlex())
- , m_widthNegativeFlex(RenderStyle::initialFlexboxWidthNegativeFlex())
- , m_heightPositiveFlex(RenderStyle::initialFlexboxHeightPositiveFlex())
- , m_heightNegativeFlex(RenderStyle::initialFlexboxHeightNegativeFlex())
+ : m_positiveFlex(RenderStyle::initialPositiveFlex())
+ , m_negativeFlex(RenderStyle::initialNegativeFlex())
+ , m_preferredSize(RenderStyle::initialFlexPreferredSize())
, m_flexOrder(RenderStyle::initialFlexOrder())
, m_flexPack(RenderStyle::initialFlexPack())
, m_flexAlign(RenderStyle::initialFlexAlign())
, m_flexItemAlign(RenderStyle::initialFlexItemAlign())
, m_flexDirection(RenderStyle::initialFlexDirection())
, m_flexWrap(RenderStyle::initialFlexWrap())
+ , m_flexLinePack(RenderStyle::initialFlexLinePack())
{
}
StyleFlexibleBoxData::StyleFlexibleBoxData(const StyleFlexibleBoxData& o)
: RefCounted<StyleFlexibleBoxData>()
- , m_widthPositiveFlex(o.m_widthPositiveFlex)
- , m_widthNegativeFlex(o.m_widthNegativeFlex)
- , m_heightPositiveFlex(o.m_heightPositiveFlex)
- , m_heightNegativeFlex(o.m_heightNegativeFlex)
+ , m_positiveFlex(o.m_positiveFlex)
+ , m_negativeFlex(o.m_negativeFlex)
+ , m_preferredSize(o.m_preferredSize)
, m_flexOrder(o.m_flexOrder)
, m_flexPack(o.m_flexPack)
, m_flexAlign(o.m_flexAlign)
, m_flexItemAlign(o.m_flexItemAlign)
, m_flexDirection(o.m_flexDirection)
, m_flexWrap(o.m_flexWrap)
+ , m_flexLinePack(o.m_flexLinePack)
{
}
bool StyleFlexibleBoxData::operator==(const StyleFlexibleBoxData& o) const
{
- return m_widthPositiveFlex == o.m_widthPositiveFlex && m_widthNegativeFlex == o.m_widthNegativeFlex
- && m_heightPositiveFlex == o.m_heightPositiveFlex && m_heightNegativeFlex == o.m_heightNegativeFlex
+ return m_positiveFlex == o.m_positiveFlex && m_negativeFlex == o.m_negativeFlex && m_preferredSize == o.m_preferredSize
&& m_flexOrder == o.m_flexOrder && m_flexPack == o.m_flexPack && m_flexAlign == o.m_flexAlign
- && m_flexItemAlign == o.m_flexItemAlign && m_flexDirection == o.m_flexDirection && m_flexWrap == o.m_flexWrap;
+ && m_flexItemAlign == o.m_flexItemAlign && m_flexDirection == o.m_flexDirection && m_flexWrap == o.m_flexWrap
+ && m_flexLinePack == o.m_flexLinePack;
}
}
diff --git a/Source/WebCore/rendering/style/StyleFlexibleBoxData.h b/Source/WebCore/rendering/style/StyleFlexibleBoxData.h
index c3bf5c39a..1ced849bc 100644
--- a/Source/WebCore/rendering/style/StyleFlexibleBoxData.h
+++ b/Source/WebCore/rendering/style/StyleFlexibleBoxData.h
@@ -26,6 +26,8 @@
#ifndef StyleFlexibleBoxData_h
#define StyleFlexibleBoxData_h
+#include "Length.h"
+
#include <wtf/PassRefPtr.h>
#include <wtf/RefCounted.h>
@@ -42,10 +44,9 @@ public:
return !(*this == o);
}
- float m_widthPositiveFlex;
- float m_widthNegativeFlex;
- float m_heightPositiveFlex;
- float m_heightNegativeFlex;
+ float m_positiveFlex;
+ float m_negativeFlex;
+ Length m_preferredSize;
int m_flexOrder;
@@ -54,6 +55,7 @@ public:
unsigned m_flexItemAlign : 3; // EFlexAlign
unsigned m_flexDirection : 2; // EFlexDirection
unsigned m_flexWrap : 2; // EFlexWrap
+ unsigned m_flexLinePack : 3; // EFlexLinePack
private:
StyleFlexibleBoxData();
diff --git a/Source/WebCore/rendering/style/StyleGeneratedImage.cpp b/Source/WebCore/rendering/style/StyleGeneratedImage.cpp
index c52c74f6d..fd9949295 100644
--- a/Source/WebCore/rendering/style/StyleGeneratedImage.cpp
+++ b/Source/WebCore/rendering/style/StyleGeneratedImage.cpp
@@ -25,8 +25,8 @@
#include "StyleGeneratedImage.h"
#include "CSSImageGeneratorValue.h"
-#include "CSSStyleSelector.h"
#include "RenderObject.h"
+#include "StyleResolver.h"
namespace WebCore {
@@ -85,7 +85,7 @@ void StyleGeneratedImage::removeClient(RenderObject* renderer)
PassRefPtr<Image> StyleGeneratedImage::image(RenderObject* renderer, const IntSize& size) const
{
- renderer->document()->styleSelector()->setStyle(renderer->style());
+ renderer->document()->styleResolver()->setStyle(renderer->style());
return m_imageGeneratorValue->image(renderer, size);
}
diff --git a/Source/WebCore/rendering/style/StyleImage.h b/Source/WebCore/rendering/style/StyleImage.h
index 0a5766b4f..1fc8e9759 100644
--- a/Source/WebCore/rendering/style/StyleImage.h
+++ b/Source/WebCore/rendering/style/StyleImage.h
@@ -62,10 +62,12 @@ public:
virtual void removeClient(RenderObject*) = 0;
virtual PassRefPtr<Image> image(RenderObject*, const IntSize&) const = 0;
virtual WrappedImagePtr data() const = 0;
+ virtual float imageScaleFactor() const { return 1; }
ALWAYS_INLINE bool isCachedImage() const { return m_isCachedImage; }
ALWAYS_INLINE bool isPendingImage() const { return m_isPendingImage; }
ALWAYS_INLINE bool isGeneratedImage() const { return m_isGeneratedImage; }
+ ALWAYS_INLINE bool isCachedImageSet() const { return m_isCachedImageSet; }
static bool imagesEquivalent(StyleImage* image1, StyleImage* image2)
{
@@ -82,11 +84,13 @@ protected:
: m_isCachedImage(false)
, m_isPendingImage(false)
, m_isGeneratedImage(false)
+ , m_isCachedImageSet(false)
{
}
bool m_isCachedImage:1;
bool m_isPendingImage:1;
bool m_isGeneratedImage:1;
+ bool m_isCachedImageSet:1;
};
}
diff --git a/Source/WebCore/rendering/style/StylePendingImage.h b/Source/WebCore/rendering/style/StylePendingImage.h
index 9aa0e20bf..6badc9238 100644
--- a/Source/WebCore/rendering/style/StylePendingImage.h
+++ b/Source/WebCore/rendering/style/StylePendingImage.h
@@ -27,6 +27,9 @@
#define StylePendingImage_h
#include "CSSImageGeneratorValue.h"
+#if ENABLE(CSS_IMAGE_SET)
+#include "CSSImageSetValue.h"
+#endif
#include "CSSImageValue.h"
#include "Image.h"
#include "StyleImage.h"
@@ -46,6 +49,9 @@ public:
virtual PassRefPtr<CSSValue> cssValue() const { return m_value; }
CSSImageValue* cssImageValue() const { return m_value->isImageValue() ? static_cast<CSSImageValue*>(m_value) : 0; }
CSSImageGeneratorValue* cssImageGeneratorValue() const { return m_value->isImageGeneratorValue() ? static_cast<CSSImageGeneratorValue*>(m_value) : 0; }
+#if ENABLE(CSS_IMAGE_SET)
+ CSSImageSetValue* cssImageSetValue() const { return m_value->isImageSetValue() ? static_cast<CSSImageSetValue*>(m_value) : 0; }
+#endif
virtual IntSize imageSize(const RenderObject*, float /*multiplier*/) const { return IntSize(); }
virtual bool imageHasRelativeWidth() const { return false; }
diff --git a/Source/WebCore/rendering/style/StyleRareNonInheritedData.cpp b/Source/WebCore/rendering/style/StyleRareNonInheritedData.cpp
index 529fc4eb8..c242dcc02 100644
--- a/Source/WebCore/rendering/style/StyleRareNonInheritedData.cpp
+++ b/Source/WebCore/rendering/style/StyleRareNonInheritedData.cpp
@@ -22,7 +22,6 @@
#include "config.h"
#include "StyleRareNonInheritedData.h"
-#include "CSSStyleSelector.h"
#include "ContentData.h"
#include "RenderCounter.h"
#include "RenderStyle.h"
@@ -30,6 +29,7 @@
#include "StyleFilterData.h"
#include "StyleTransformData.h"
#include "StyleImage.h"
+#include "StyleResolver.h"
namespace WebCore {
diff --git a/Source/WebCore/rendering/style/StyleRareNonInheritedData.h b/Source/WebCore/rendering/style/StyleRareNonInheritedData.h
index e95c55b60..ae72bd60a 100644
--- a/Source/WebCore/rendering/style/StyleRareNonInheritedData.h
+++ b/Source/WebCore/rendering/style/StyleRareNonInheritedData.h
@@ -39,7 +39,6 @@
namespace WebCore {
class AnimationList;
-class CSSStyleSelector;
class ShadowData;
class StyleDeprecatedFlexibleBoxData;
#if ENABLE(CSS_FILTERS)
@@ -53,6 +52,7 @@ class StyleGridItemData;
class StyleMarqueeData;
class StyleMultiColData;
class StyleReflection;
+class StyleResolver;
class StyleTransformData;
class ContentData;
diff --git a/Source/WebCore/rendering/svg/RenderSVGAllInOne.cpp b/Source/WebCore/rendering/svg/RenderSVGAllInOne.cpp
index 8f8c86ea6..334f6eeb8 100644
--- a/Source/WebCore/rendering/svg/RenderSVGAllInOne.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGAllInOne.cpp
@@ -27,6 +27,7 @@
#include "RenderSVGBlock.cpp"
#include "RenderSVGContainer.cpp"
+#include "RenderSVGEllipse.cpp"
#include "RenderSVGForeignObject.cpp"
#include "RenderSVGGradientStop.cpp"
#include "RenderSVGHiddenContainer.cpp"
@@ -55,7 +56,6 @@
#include "RenderSVGTextPath.cpp"
#include "RenderSVGTransformableContainer.cpp"
#include "RenderSVGViewportContainer.cpp"
-#include "SVGImageBufferTools.cpp"
#include "SVGInlineFlowBox.cpp"
#include "SVGInlineTextBox.cpp"
#include "SVGMarkerLayoutInfo.cpp"
diff --git a/Source/WebCore/rendering/svg/RenderSVGContainer.cpp b/Source/WebCore/rendering/svg/RenderSVGContainer.cpp
index e16bfa33c..a1fd8321d 100644
--- a/Source/WebCore/rendering/svg/RenderSVGContainer.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGContainer.cpp
@@ -40,6 +40,7 @@ namespace WebCore {
RenderSVGContainer::RenderSVGContainer(SVGStyledElement* node)
: RenderSVGModelObject(node)
+ , m_objectBoundingBoxValid(false)
, m_needsBoundariesUpdate(true)
{
}
@@ -150,10 +151,11 @@ void RenderSVGContainer::addFocusRingRects(Vector<IntRect>& rects, const LayoutP
void RenderSVGContainer::updateCachedBoundaries()
{
m_objectBoundingBox = FloatRect();
+ m_objectBoundingBoxValid = false;
m_strokeBoundingBox = FloatRect();
m_repaintBoundingBox = FloatRect();
- SVGRenderSupport::computeContainerBoundingBoxes(this, m_objectBoundingBox, m_strokeBoundingBox, m_repaintBoundingBox);
+ SVGRenderSupport::computeContainerBoundingBoxes(this, m_objectBoundingBox, m_objectBoundingBoxValid, m_strokeBoundingBox, m_repaintBoundingBox);
SVGRenderSupport::intersectRepaintRectWithResources(this, m_repaintBoundingBox);
}
diff --git a/Source/WebCore/rendering/svg/RenderSVGContainer.h b/Source/WebCore/rendering/svg/RenderSVGContainer.h
index 84621f175..5be036638 100644
--- a/Source/WebCore/rendering/svg/RenderSVGContainer.h
+++ b/Source/WebCore/rendering/svg/RenderSVGContainer.h
@@ -42,6 +42,7 @@ public:
virtual void paint(PaintInfo&, const LayoutPoint&);
virtual void setNeedsBoundariesUpdate() { m_needsBoundariesUpdate = true; }
virtual bool didTransformToRootUpdate() { return false; }
+ bool isObjectBoundingBoxValid() const { return m_objectBoundingBoxValid; }
protected:
virtual RenderObjectChildList* virtualChildren() { return children(); }
@@ -76,6 +77,7 @@ protected:
private:
RenderObjectChildList m_children;
FloatRect m_objectBoundingBox;
+ bool m_objectBoundingBoxValid;
FloatRect m_strokeBoundingBox;
FloatRect m_repaintBoundingBox;
bool m_needsBoundariesUpdate : 1;
@@ -83,15 +85,13 @@ private:
inline RenderSVGContainer* toRenderSVGContainer(RenderObject* object)
{
- // Note: isSVGContainer is also true for RenderSVGViewportContainer, which is not derived from this.
- ASSERT(!object || (object->isSVGContainer() && strcmp(object->renderName(), "RenderSVGViewportContainer")));
+ ASSERT(!object || object->isSVGContainer());
return static_cast<RenderSVGContainer*>(object);
}
inline const RenderSVGContainer* toRenderSVGContainer(const RenderObject* object)
{
- // Note: isSVGContainer is also true for RenderSVGViewportContainer, which is not derived from this.
- ASSERT(!object || (object->isSVGContainer() && strcmp(object->renderName(), "RenderSVGViewportContainer")));
+ ASSERT(!object || object->isSVGContainer());
return static_cast<const RenderSVGContainer*>(object);
}
diff --git a/Source/WebCore/rendering/svg/RenderSVGEllipse.cpp b/Source/WebCore/rendering/svg/RenderSVGEllipse.cpp
new file mode 100644
index 000000000..d147f6bfc
--- /dev/null
+++ b/Source/WebCore/rendering/svg/RenderSVGEllipse.cpp
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2012 Google, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY UNIVERSITY OF SZEGED ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL UNIVERSITY OF SZEGED OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(SVG)
+#include "RenderSVGEllipse.h"
+
+#include "SVGCircleElement.h"
+#include "SVGEllipseElement.h"
+#include "SVGNames.h"
+#include "SVGStyledTransformableElement.h"
+
+namespace WebCore {
+
+RenderSVGEllipse::RenderSVGEllipse(SVGStyledTransformableElement* node)
+ : RenderSVGShape(node)
+{
+}
+
+RenderSVGEllipse::~RenderSVGEllipse()
+{
+}
+
+void RenderSVGEllipse::createShape()
+{
+ // Before creating a new object we need to clear the cached bounding box
+ // to avoid using garbage.
+ m_boundingBox = FloatRect();
+ m_outerStrokeRect = FloatRect();
+ m_center = FloatPoint();
+ m_radii = FloatSize();
+
+ // Fallback to RenderSVGShape if shape has a non scaling stroke.
+ if (style()->svgStyle()->vectorEffect() == VE_NON_SCALING_STROKE) {
+ RenderSVGShape::createShape();
+ setIsPaintingFallback(true);
+ return;
+ }
+
+ calculateRadiiAndCenter();
+
+ // Spec: "A value of zero disables rendering of the element."
+ if (m_radii.width() <= 0 || m_radii.height() <= 0)
+ return;
+
+ m_boundingBox = FloatRect(m_center.x() - m_radii.width(), m_center.y() - m_radii.height(), 2 * m_radii.width(), 2 * m_radii.height());
+ m_outerStrokeRect = m_boundingBox;
+ if (style()->svgStyle()->hasStroke())
+ m_outerStrokeRect.inflate(strokeWidth() / 2);
+}
+
+void RenderSVGEllipse::calculateRadiiAndCenter()
+{
+ ASSERT(node());
+ if (node()->hasTagName(SVGNames::circleTag)) {
+
+ SVGCircleElement* circle = static_cast<SVGCircleElement*>(node());
+
+ SVGLengthContext lengthContext(circle);
+ float radius = circle->r().value(lengthContext);
+ m_radii = FloatSize(radius, radius);
+ m_center = FloatPoint(circle->cx().value(lengthContext), circle->cy().value(lengthContext));
+ return;
+ }
+
+ ASSERT(node()->hasTagName(SVGNames::ellipseTag));
+ SVGEllipseElement* ellipse = static_cast<SVGEllipseElement*>(node());
+
+ SVGLengthContext lengthContext(ellipse);
+ m_radii = FloatSize(ellipse->rx().value(lengthContext), ellipse->ry().value(lengthContext));
+ m_center = FloatPoint(ellipse->cx().value(lengthContext), ellipse->cy().value(lengthContext));
+}
+
+FloatRect RenderSVGEllipse::objectBoundingBox() const
+{
+ if (isPaintingFallback())
+ return RenderSVGShape::objectBoundingBox();
+ return m_boundingBox;
+}
+
+FloatRect RenderSVGEllipse::strokeBoundingBox() const
+{
+ if (isPaintingFallback())
+ return RenderSVGShape::strokeBoundingBox();
+ return m_outerStrokeRect;
+}
+
+void RenderSVGEllipse::fillShape(GraphicsContext* context) const
+{
+ if (isPaintingFallback()) {
+ RenderSVGShape::fillShape(context);
+ return;
+ }
+ context->fillEllipse(m_boundingBox);
+}
+
+void RenderSVGEllipse::strokeShape(GraphicsContext* context) const
+{
+ if (!style()->svgStyle()->hasVisibleStroke())
+ return;
+ if (isPaintingFallback()) {
+ RenderSVGShape::strokeShape(context);
+ return;
+ }
+ context->strokeEllipse(m_boundingBox);
+}
+
+bool RenderSVGEllipse::shapeDependentStrokeContains(const FloatPoint& point) const
+{
+ if (isPaintingFallback())
+ return RenderSVGShape::shapeDependentStrokeContains(point);
+
+ float halfStrokeWidth = strokeWidth() / 2;
+ FloatPoint center = FloatPoint(m_center.x() - point.x(), m_center.y() - point.y());
+
+ // This works by checking if the point satisfies the ellipse equation,
+ // (x/rX)^2 + (y/rY)^2 <= 1, for the outer but not the inner stroke.
+ float xrXOuter = center.x() / (m_radii.width() + halfStrokeWidth);
+ float yrYOuter = center.y() / (m_radii.height() + halfStrokeWidth);
+ if (xrXOuter * xrXOuter + yrYOuter * yrYOuter > 1.0)
+ return false;
+
+ float xrXInner = center.x() / (m_radii.width() - halfStrokeWidth);
+ float yrYInner = center.y() / (m_radii.height() - halfStrokeWidth);
+ return xrXInner * xrXInner + yrYInner * yrYInner >= 1.0;
+}
+
+bool RenderSVGEllipse::shapeDependentFillContains(const FloatPoint& point, const WindRule fillRule) const
+{
+ if (isPaintingFallback())
+ return RenderSVGShape::shapeDependentFillContains(point, fillRule);
+
+ FloatPoint center = FloatPoint(m_center.x() - point.x(), m_center.y() - point.y());
+
+ // This works by checking if the point satisfies the ellipse equation.
+ // (x/rX)^2 + (y/rY)^2 <= 1
+ float xrX = center.x() / m_radii.width();
+ float yrY = center.y() / m_radii.height();
+ return xrX * xrX + yrY * yrY <= 1.0;
+}
+
+}
+
+#endif // ENABLE(SVG)
diff --git a/Source/WebCore/rendering/svg/RenderSVGEllipse.h b/Source/WebCore/rendering/svg/RenderSVGEllipse.h
new file mode 100644
index 000000000..76295c686
--- /dev/null
+++ b/Source/WebCore/rendering/svg/RenderSVGEllipse.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2012 Google, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY UNIVERSITY OF SZEGED ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL UNIVERSITY OF SZEGED OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef RenderSVGEllipse_h
+#define RenderSVGEllipse_h
+
+#if ENABLE(SVG)
+#include "RenderSVGShape.h"
+#include "SVGStyledTransformableElement.h"
+
+namespace WebCore {
+
+class RenderSVGEllipse : public RenderSVGShape {
+public:
+ explicit RenderSVGEllipse(SVGStyledTransformableElement*);
+ virtual ~RenderSVGEllipse();
+
+private:
+ virtual bool isSVGEllipse() const { return true; }
+ virtual const char* renderName() const { return "RenderSVGEllipse"; }
+
+ virtual void createShape();
+ virtual bool isEmpty() const { return hasPath() ? RenderSVGShape::isEmpty() : m_boundingBox.isEmpty(); };
+ virtual void fillShape(GraphicsContext*) const;
+ virtual void strokeShape(GraphicsContext*) const;
+ virtual FloatRect objectBoundingBox() const;
+ virtual FloatRect strokeBoundingBox() const;
+ virtual bool shapeDependentStrokeContains(const FloatPoint&) const;
+ virtual bool shapeDependentFillContains(const FloatPoint&, const WindRule) const;
+ void calculateRadiiAndCenter();
+
+private:
+ FloatRect m_boundingBox;
+ FloatRect m_outerStrokeRect;
+ FloatPoint m_center;
+ FloatSize m_radii;
+};
+
+}
+
+#endif // ENABLE(SVG)
+#endif
diff --git a/Source/WebCore/rendering/svg/RenderSVGForeignObject.cpp b/Source/WebCore/rendering/svg/RenderSVGForeignObject.cpp
index 676e8f4a7..2918fe3a9 100644
--- a/Source/WebCore/rendering/svg/RenderSVGForeignObject.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGForeignObject.cpp
@@ -26,6 +26,7 @@
#include "GraphicsContext.h"
#include "LayoutRepainter.h"
+#include "RenderObject.h"
#include "RenderSVGResource.h"
#include "RenderView.h"
#include "SVGForeignObjectElement.h"
@@ -165,13 +166,20 @@ void RenderSVGForeignObject::layout()
bool RenderSVGForeignObject::nodeAtFloatPoint(const HitTestRequest& request, HitTestResult& result, const FloatPoint& pointInParent, HitTestAction hitTestAction)
{
+ // Embedded content is drawn in the foreground phase.
+ if (hitTestAction != HitTestForeground)
+ return false;
+
FloatPoint localPoint = localTransform().inverse().mapPoint(pointInParent);
// Early exit if local point is not contained in clipped viewport area
if (SVGRenderSupport::isOverflowHidden(this) && !m_viewport.contains(localPoint))
return false;
- return RenderBlock::nodeAtPoint(request, result, roundedLayoutPoint(localPoint), LayoutPoint(), hitTestAction);
+ // FOs establish a stacking context, so we need to hit-test all layers.
+ return RenderBlock::nodeAtPoint(request, result, roundedLayoutPoint(localPoint), LayoutPoint(), HitTestForeground)
+ || RenderBlock::nodeAtPoint(request, result, roundedLayoutPoint(localPoint), LayoutPoint(), HitTestFloat)
+ || RenderBlock::nodeAtPoint(request, result, roundedLayoutPoint(localPoint), LayoutPoint(), HitTestChildBlockBackgrounds);
}
bool RenderSVGForeignObject::nodeAtPoint(const HitTestRequest&, HitTestResult&, const LayoutPoint&, const LayoutPoint&, HitTestAction)
@@ -180,7 +188,7 @@ bool RenderSVGForeignObject::nodeAtPoint(const HitTestRequest&, HitTestResult&,
return false;
}
-void RenderSVGForeignObject::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool /* fixed */, bool /* useTransforms */, TransformState& transformState, bool* wasFixed) const
+void RenderSVGForeignObject::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool /* fixed */, bool /* useTransforms */, TransformState& transformState, ApplyContainerFlipOrNot, bool* wasFixed) const
{
SVGRenderSupport::mapLocalToContainer(this, repaintContainer, transformState, wasFixed);
}
diff --git a/Source/WebCore/rendering/svg/RenderSVGForeignObject.h b/Source/WebCore/rendering/svg/RenderSVGForeignObject.h
index 905b488b6..4a1a8ac25 100644
--- a/Source/WebCore/rendering/svg/RenderSVGForeignObject.h
+++ b/Source/WebCore/rendering/svg/RenderSVGForeignObject.h
@@ -54,7 +54,7 @@ public:
virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const LayoutPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction);
virtual bool isSVGForeignObject() const { return true; }
- virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed, bool useTransforms, TransformState&, bool* wasFixed = 0) const;
+ virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed, bool useTransforms, TransformState&, ApplyContainerFlipOrNot = ApplyContainerFlip, bool* wasFixed = 0) const;
virtual void setNeedsTransformUpdate() { m_needsTransformUpdate = true; }
private:
diff --git a/Source/WebCore/rendering/svg/RenderSVGInline.cpp b/Source/WebCore/rendering/svg/RenderSVGInline.cpp
index ea2746e79..ab8cc1a87 100644
--- a/Source/WebCore/rendering/svg/RenderSVGInline.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGInline.cpp
@@ -79,7 +79,7 @@ void RenderSVGInline::computeFloatRectForRepaint(RenderBoxModelObject* repaintCo
SVGRenderSupport::computeFloatRectForRepaint(this, repaintContainer, repaintRect, fixed);
}
-void RenderSVGInline::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool /* useTransforms */, bool /* fixed */, TransformState& transformState, bool* wasFixed) const
+void RenderSVGInline::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool /* useTransforms */, bool /* fixed */, TransformState& transformState, ApplyContainerFlipOrNot, bool* wasFixed) const
{
SVGRenderSupport::mapLocalToContainer(this, repaintContainer, transformState, wasFixed);
}
diff --git a/Source/WebCore/rendering/svg/RenderSVGInline.h b/Source/WebCore/rendering/svg/RenderSVGInline.h
index 4344fb506..8aa4ab875 100644
--- a/Source/WebCore/rendering/svg/RenderSVGInline.h
+++ b/Source/WebCore/rendering/svg/RenderSVGInline.h
@@ -47,7 +47,7 @@ public:
virtual LayoutRect clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer) const;
virtual void computeFloatRectForRepaint(RenderBoxModelObject* repaintContainer, FloatRect&, bool fixed = false) const;
- virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool useTransforms, bool fixed, TransformState&, bool* wasFixed = 0) const;
+ virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool useTransforms, bool fixed, TransformState&, ApplyContainerFlipOrNot = ApplyContainerFlip, bool* wasFixed = 0) const;
virtual void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const;
private:
diff --git a/Source/WebCore/rendering/svg/RenderSVGInlineText.cpp b/Source/WebCore/rendering/svg/RenderSVGInlineText.cpp
index 591316291..09d446b7d 100644
--- a/Source/WebCore/rendering/svg/RenderSVGInlineText.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGInlineText.cpp
@@ -27,16 +27,16 @@
#include "RenderSVGInlineText.h"
#include "CSSFontSelector.h"
-#include "CSSStyleSelector.h"
#include "FloatConversion.h"
#include "FloatQuad.h"
#include "RenderBlock.h"
#include "RenderSVGRoot.h"
#include "RenderSVGText.h"
#include "Settings.h"
-#include "SVGImageBufferTools.h"
#include "SVGInlineTextBox.h"
+#include "SVGRenderingContext.h"
#include "SVGRootInlineBox.h"
+#include "StyleResolver.h"
#include "VisiblePosition.h"
namespace WebCore {
@@ -87,7 +87,8 @@ void RenderSVGInlineText::willBeDestroyed()
if (affectedAttributes.isEmpty())
return;
- textRenderer->rebuildLayoutAttributes(affectedAttributes);
+ if (!documentBeingDestroyed())
+ textRenderer->rebuildLayoutAttributes(affectedAttributes);
}
void RenderSVGInlineText::setTextInternal(PassRefPtr<StringImpl> text)
@@ -99,7 +100,7 @@ void RenderSVGInlineText::setTextInternal(PassRefPtr<StringImpl> text)
// the RenderSVGInlineText objects, and thus needs to be rebuild. The latter will assure that the
// SVGTextLayoutAttributes associated with the RenderSVGInlineText will be updated.
if (RenderSVGText* textRenderer = RenderSVGText::locateRenderSVGTextAncestor(this)) {
- textRenderer->textDOMChanged();
+ textRenderer->invalidateTextPositioningElements();
textRenderer->layoutAttributesChanged(this);
}
}
@@ -147,13 +148,13 @@ LayoutRect RenderSVGInlineText::localCaretRect(InlineBox* box, int caretOffset,
// Use the edge of the selection rect to determine the caret rect.
if (static_cast<unsigned>(caretOffset) < textBox->start() + textBox->len()) {
- IntRect rect = textBox->localSelectionRect(caretOffset, caretOffset + 1);
- int x = box->isLeftToRightDirection() ? rect.x() : rect.maxX();
+ LayoutRect rect = textBox->localSelectionRect(caretOffset, caretOffset + 1);
+ LayoutUnit x = box->isLeftToRightDirection() ? rect.x() : rect.maxX();
return LayoutRect(x, rect.y(), caretWidth, rect.height());
}
- IntRect rect = textBox->localSelectionRect(caretOffset - 1, caretOffset);
- int x = box->isLeftToRightDirection() ? rect.maxX() : rect.x();
+ LayoutRect rect = textBox->localSelectionRect(caretOffset - 1, caretOffset);
+ LayoutUnit x = box->isLeftToRightDirection() ? rect.maxX() : rect.x();
return LayoutRect(x, rect.y(), caretWidth, rect.height());
}
@@ -165,7 +166,7 @@ FloatRect RenderSVGInlineText::floatLinesBoundingBox() const
return boundingBox;
}
-LayoutRect RenderSVGInlineText::linesBoundingBox() const
+IntRect RenderSVGInlineText::linesBoundingBox() const
{
return enclosingIntRect(floatLinesBoundingBox());
}
@@ -253,12 +254,12 @@ void RenderSVGInlineText::computeNewScaledFontForStyle(RenderObject* renderer, c
Document* document = renderer->document();
ASSERT(document);
- CSSStyleSelector* styleSelector = document->styleSelector();
- ASSERT(styleSelector);
+ StyleResolver* styleResolver = document->styleResolver();
+ ASSERT(styleResolver);
// Alter font-size to the right on-screen value to avoid scaling the glyphs themselves, except when GeometricPrecision is specified
AffineTransform ctm;
- SVGImageBufferTools::calculateTransformationToOutermostSVGCoordinateSystem(renderer, ctm);
+ SVGRenderingContext::calculateTransformationToOutermostSVGCoordinateSystem(renderer, ctm);
scalingFactor = narrowPrecisionToFloat(sqrt((pow(ctm.xScale(), 2) + pow(ctm.yScale(), 2)) / 2));
if (scalingFactor == 1 || !scalingFactor || style->fontDescription().textRenderingMode() == GeometricPrecision) {
scalingFactor = 1;
@@ -269,10 +270,10 @@ void RenderSVGInlineText::computeNewScaledFontForStyle(RenderObject* renderer, c
FontDescription fontDescription(style->fontDescription());
// FIXME: We need to better handle the case when we compute very small fonts below (below 1pt).
- fontDescription.setComputedSize(CSSStyleSelector::getComputedSizeFromSpecifiedSize(document, scalingFactor, fontDescription.isAbsoluteSize(), fontDescription.computedSize(), DoNotUseSmartMinimumForFontSize));
+ fontDescription.setComputedSize(StyleResolver::getComputedSizeFromSpecifiedSize(document, scalingFactor, fontDescription.isAbsoluteSize(), fontDescription.computedSize(), DoNotUseSmartMinimumForFontSize));
scaledFont = Font(fontDescription, 0, 0);
- scaledFont.update(styleSelector->fontSelector());
+ scaledFont.update(styleResolver->fontSelector());
}
}
diff --git a/Source/WebCore/rendering/svg/RenderSVGInlineText.h b/Source/WebCore/rendering/svg/RenderSVGInlineText.h
index 6ac768c67..51378fd07 100644
--- a/Source/WebCore/rendering/svg/RenderSVGInlineText.h
+++ b/Source/WebCore/rendering/svg/RenderSVGInlineText.h
@@ -59,7 +59,7 @@ private:
virtual VisiblePosition positionForPoint(const LayoutPoint&);
virtual LayoutRect localCaretRect(InlineBox*, int caretOffset, LayoutUnit* extraWidthToEndOfLine = 0);
- virtual LayoutRect linesBoundingBox() const;
+ virtual IntRect linesBoundingBox() const;
virtual InlineTextBox* createTextBox();
float m_scalingFactor;
diff --git a/Source/WebCore/rendering/svg/RenderSVGModelObject.cpp b/Source/WebCore/rendering/svg/RenderSVGModelObject.cpp
index 3841336a5..48fd7d879 100644
--- a/Source/WebCore/rendering/svg/RenderSVGModelObject.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGModelObject.cpp
@@ -55,7 +55,7 @@ void RenderSVGModelObject::computeFloatRectForRepaint(RenderBoxModelObject* repa
SVGRenderSupport::computeFloatRectForRepaint(this, repaintContainer, repaintRect, fixed);
}
-void RenderSVGModelObject::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool /* fixed */, bool /* useTransforms */, TransformState& transformState, bool* wasFixed) const
+void RenderSVGModelObject::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool /* fixed */, bool /* useTransforms */, TransformState& transformState, ApplyContainerFlipOrNot, bool* wasFixed) const
{
SVGRenderSupport::mapLocalToContainer(this, repaintContainer, transformState, wasFixed);
}
diff --git a/Source/WebCore/rendering/svg/RenderSVGModelObject.h b/Source/WebCore/rendering/svg/RenderSVGModelObject.h
index 1582ff5fa..b9692fe1d 100644
--- a/Source/WebCore/rendering/svg/RenderSVGModelObject.h
+++ b/Source/WebCore/rendering/svg/RenderSVGModelObject.h
@@ -58,7 +58,7 @@ public:
virtual void absoluteRects(Vector<IntRect>&, const LayoutPoint& accumulatedOffset) const;
virtual void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const;
- virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool useTransforms, bool fixed, TransformState&, bool* wasFixed = 0) const;
+ virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool useTransforms, bool fixed, TransformState&, ApplyContainerFlipOrNot = ApplyContainerFlip, bool* wasFixed = 0) const;
virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle);
virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
virtual void updateFromElement();
diff --git a/Source/WebCore/rendering/svg/RenderSVGRect.cpp b/Source/WebCore/rendering/svg/RenderSVGRect.cpp
index f3f020464..a200f3b11 100755
--- a/Source/WebCore/rendering/svg/RenderSVGRect.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGRect.cpp
@@ -80,6 +80,14 @@ void RenderSVGRect::createShape()
m_innerStrokeRect.inflate(-strokeWidth / 2);
m_outerStrokeRect.inflate(strokeWidth / 2);
}
+
+ m_strokeBoundingRect = m_outerStrokeRect;
+
+#if USE(CG)
+ // CoreGraphics can inflate the stroke by 1px when drawing a rectangle with antialiasing disabled at non-integer coordinates, we need to compensate.
+ if (style()->svgStyle()->shapeRendering() == SR_CRISPEDGES)
+ m_strokeBoundingRect.inflate(1);
+#endif
}
FloatRect RenderSVGRect::objectBoundingBox() const
@@ -93,7 +101,7 @@ FloatRect RenderSVGRect::strokeBoundingBox() const
{
if (isPaintingFallback())
return RenderSVGShape::strokeBoundingBox();
- return m_outerStrokeRect;
+ return m_strokeBoundingRect;
}
void RenderSVGRect::fillShape(GraphicsContext* context) const
@@ -119,6 +127,8 @@ void RenderSVGRect::fillShape(GraphicsContext* context) const
void RenderSVGRect::strokeShape(GraphicsContext* context) const
{
+ if (!style()->svgStyle()->hasVisibleStroke())
+ return;
if (!isPaintingFallback()) {
context->strokeRect(m_boundingBox, strokeWidth());
return;
diff --git a/Source/WebCore/rendering/svg/RenderSVGRect.h b/Source/WebCore/rendering/svg/RenderSVGRect.h
index 37a116053..ab6eb2343 100644
--- a/Source/WebCore/rendering/svg/RenderSVGRect.h
+++ b/Source/WebCore/rendering/svg/RenderSVGRect.h
@@ -56,6 +56,7 @@ private:
FloatRect m_boundingBox;
FloatRect m_innerStrokeRect;
FloatRect m_outerStrokeRect;
+ FloatRect m_strokeBoundingRect;
};
}
diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceClipper.cpp b/Source/WebCore/rendering/svg/RenderSVGResourceClipper.cpp
index ba20502f3..7339e2859 100644
--- a/Source/WebCore/rendering/svg/RenderSVGResourceClipper.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGResourceClipper.cpp
@@ -39,9 +39,9 @@
#include "RenderStyle.h"
#include "SVGClipPathElement.h"
#include "SVGElement.h"
-#include "SVGImageBufferTools.h"
#include "SVGNames.h"
#include "SVGRenderSupport.h"
+#include "SVGRenderingContext.h"
#include "SVGResources.h"
#include "SVGResourcesCache.h"
#include "SVGStyledElement.h"
@@ -155,7 +155,8 @@ bool RenderSVGResourceClipper::pathOnlyClipping(GraphicsContext* context, const
bool RenderSVGResourceClipper::applyClippingToContext(RenderObject* object, const FloatRect& objectBoundingBox,
const FloatRect& repaintRect, GraphicsContext* context)
{
- if (!m_clipper.contains(object))
+ bool missingClipperData = !m_clipper.contains(object);
+ if (missingClipperData)
m_clipper.set(object, new ClipperData);
bool shouldCreateClipData = false;
@@ -168,10 +169,10 @@ bool RenderSVGResourceClipper::applyClippingToContext(RenderObject* object, cons
}
AffineTransform absoluteTransform;
- SVGImageBufferTools::calculateTransformationToOutermostSVGCoordinateSystem(object, absoluteTransform);
+ SVGRenderingContext::calculateTransformationToOutermostSVGCoordinateSystem(object, absoluteTransform);
if (shouldCreateClipData && !repaintRect.isEmpty()) {
- if (!SVGImageBufferTools::createImageBuffer(repaintRect, absoluteTransform, clipperData->clipMaskImage, ColorSpaceDeviceRGB, Unaccelerated))
+ if (!SVGRenderingContext::createImageBuffer(repaintRect, absoluteTransform, clipperData->clipMaskImage, ColorSpaceDeviceRGB, Unaccelerated))
return false;
GraphicsContext* maskContext = clipperData->clipMaskImage->context();
@@ -201,7 +202,7 @@ bool RenderSVGResourceClipper::applyClippingToContext(RenderObject* object, cons
if (!clipperData->clipMaskImage)
return false;
- SVGImageBufferTools::clipToImageBuffer(context, absoluteTransform, repaintRect, clipperData->clipMaskImage);
+ SVGRenderingContext::clipToImageBuffer(context, absoluteTransform, repaintRect, clipperData->clipMaskImage, missingClipperData);
return true;
}
@@ -263,7 +264,7 @@ bool RenderSVGResourceClipper::drawContentIntoMaskImage(ClipperData* clipperData
// In the case of a <use> element, we obtained its renderere above, to retrieve its clipRule.
// We have to pass the <use> renderer itself to renderSubtreeToImageBuffer() to apply it's x/y/transform/etc. values when rendering.
// So if isUseElement is true, refetch the childNode->renderer(), as renderer got overriden above.
- SVGImageBufferTools::renderSubtreeToImageBuffer(clipperData->clipMaskImage.get(), isUseElement ? childNode->renderer() : renderer, maskContentTransformation);
+ SVGRenderingContext::renderSubtreeToImageBuffer(clipperData->clipMaskImage.get(), isUseElement ? childNode->renderer() : renderer, maskContentTransformation);
}
frame()->view()->setPaintBehavior(oldBehavior);
diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceContainer.cpp b/Source/WebCore/rendering/svg/RenderSVGResourceContainer.cpp
index 2952442cf..3dba672dd 100644
--- a/Source/WebCore/rendering/svg/RenderSVGResourceContainer.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGResourceContainer.cpp
@@ -22,6 +22,7 @@
#if ENABLE(SVG)
#include "RenderSVGResourceContainer.h"
+#include "RenderSVGRoot.h"
#include "RenderView.h"
#include "SVGResourcesCache.h"
#include "SVGStyledTransformableElement.h"
@@ -53,7 +54,7 @@ void RenderSVGResourceContainer::layout()
{
// Invalidate all resources if our layout changed.
if (everHadLayout() && selfNeedsLayout())
- removeAllClientsFromCache();
+ RenderSVGRoot::addResourceForClientInvalidation(this);
RenderSVGHiddenContainer::layout();
}
diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp b/Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp
index 43ebee284..d5d792ded 100644
--- a/Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp
@@ -43,8 +43,8 @@
#include "SVGFilter.h"
#include "SVGFilterElement.h"
#include "SVGFilterPrimitiveStandardAttributes.h"
-#include "SVGImageBufferTools.h"
#include "SVGNames.h"
+#include "SVGRenderingContext.h"
#include "SVGStyledElement.h"
#include "SVGUnitTypes.h"
@@ -165,7 +165,7 @@ bool RenderSVGResourceFilter::applyResource(RenderObject* object, RenderStyle*,
// Determine absolute transformation matrix for filter.
AffineTransform absoluteTransform;
- SVGImageBufferTools::calculateTransformationToOutermostSVGCoordinateSystem(object, absoluteTransform);
+ SVGRenderingContext::calculateTransformationToOutermostSVGCoordinateSystem(object, absoluteTransform);
if (!absoluteTransform.isInvertible())
return false;
@@ -235,7 +235,7 @@ bool RenderSVGResourceFilter::applyResource(RenderObject* object, RenderStyle*,
OwnPtr<ImageBuffer> sourceGraphic;
RenderingMode renderingMode = object->document()->page()->settings()->acceleratedFiltersEnabled() ? Accelerated : Unaccelerated;
- if (!SVGImageBufferTools::createImageBuffer(drawingRegion, effectiveTransform, sourceGraphic, ColorSpaceLinearRGB, renderingMode)) {
+ if (!SVGRenderingContext::createImageBuffer(drawingRegion, effectiveTransform, sourceGraphic, ColorSpaceLinearRGB, renderingMode)) {
ASSERT(!m_filter.contains(object));
filterData->savedContext = context;
m_filter.set(object, filterData.leakPtr());
diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceGradient.cpp b/Source/WebCore/rendering/svg/RenderSVGResourceGradient.cpp
index ead5510b5..f8f493db8 100644
--- a/Source/WebCore/rendering/svg/RenderSVGResourceGradient.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGResourceGradient.cpp
@@ -29,8 +29,8 @@
#include "GraphicsContext.h"
#include "RenderSVGShape.h"
#include "RenderSVGText.h"
-#include "SVGImageBufferTools.h"
#include "SVGRenderSupport.h"
+#include "SVGRenderingContext.h"
#include <wtf/UnusedParam.h>
namespace WebCore {
@@ -68,11 +68,11 @@ static inline bool createMaskAndSwapContextForTextGradient(GraphicsContext*& con
ASSERT(textRootBlock);
AffineTransform absoluteTransform;
- SVGImageBufferTools::calculateTransformationToOutermostSVGCoordinateSystem(textRootBlock, absoluteTransform);
+ SVGRenderingContext::calculateTransformationToOutermostSVGCoordinateSystem(textRootBlock, absoluteTransform);
FloatRect repaintRect = textRootBlock->repaintRectInLocalCoordinates();
OwnPtr<ImageBuffer> maskImage;
- if (!SVGImageBufferTools::createImageBuffer(repaintRect, absoluteTransform, maskImage, ColorSpaceDeviceRGB, Unaccelerated))
+ if (!SVGRenderingContext::createImageBuffer(repaintRect, absoluteTransform, maskImage, ColorSpaceDeviceRGB, Unaccelerated))
return false;
GraphicsContext* maskImageContext = maskImage->context();
@@ -95,10 +95,10 @@ static inline AffineTransform clipToTextMask(GraphicsContext* context,
ASSERT(textRootBlock);
AffineTransform absoluteTransform;
- SVGImageBufferTools::calculateTransformationToOutermostSVGCoordinateSystem(textRootBlock, absoluteTransform);
+ SVGRenderingContext::calculateTransformationToOutermostSVGCoordinateSystem(textRootBlock, absoluteTransform);
targetRect = textRootBlock->repaintRectInLocalCoordinates();
- SVGImageBufferTools::clipToImageBuffer(context, absoluteTransform, targetRect, imageBuffer);
+ SVGRenderingContext::clipToImageBuffer(context, absoluteTransform, targetRect, imageBuffer, false);
AffineTransform matrix;
if (boundingBoxMode) {
@@ -140,7 +140,7 @@ bool RenderSVGResourceGradient::applyResource(RenderObject* object, RenderStyle*
if (gradientUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX && objectBoundingBox.isEmpty())
return false;
- OwnPtr<GradientData>& gradientData = m_gradientMap.add(object, nullptr).first->second;
+ OwnPtr<GradientData>& gradientData = m_gradientMap.add(object, nullptr).iterator->second;
if (!gradientData)
gradientData = adoptPtr(new GradientData);
diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceMarker.cpp b/Source/WebCore/rendering/svg/RenderSVGResourceMarker.cpp
index dc0755dd9..784559e21 100644
--- a/Source/WebCore/rendering/svg/RenderSVGResourceMarker.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGResourceMarker.cpp
@@ -26,6 +26,7 @@
#include "GraphicsContext.h"
#include "RenderSVGContainer.h"
+#include "RenderSVGRoot.h"
#include "SVGElement.h"
#include "SVGMarkerElement.h"
#include "SVGRenderSupport.h"
@@ -49,7 +50,7 @@ void RenderSVGResourceMarker::layout()
{
// Invalidate all resources if our layout changed.
if (everHadLayout() && selfNeedsLayout())
- removeAllClientsFromCache();
+ RenderSVGRoot::addResourceForClientInvalidation(this);
// RenderSVGHiddenContainer overwrites layout(). We need the
// layouting of RenderSVGContainer for calculating local
diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceMasker.cpp b/Source/WebCore/rendering/svg/RenderSVGResourceMasker.cpp
index bf5954947..e6eb6afc2 100644
--- a/Source/WebCore/rendering/svg/RenderSVGResourceMasker.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGResourceMasker.cpp
@@ -32,12 +32,11 @@
#include "IntRect.h"
#include "RenderSVGResource.h"
#include "SVGElement.h"
-#include "SVGImageBufferTools.h"
#include "SVGMaskElement.h"
+#include "SVGRenderingContext.h"
#include "SVGStyledElement.h"
#include "SVGUnitTypes.h"
-#include <wtf/ByteArray.h>
#include <wtf/UnusedParam.h>
#include <wtf/Vector.h>
@@ -86,13 +85,14 @@ bool RenderSVGResourceMasker::applyResource(RenderObject* object, RenderStyle*,
ASSERT(context);
ASSERT_UNUSED(resourceMode, resourceMode == ApplyToDefaultMode);
- if (!m_masker.contains(object))
+ bool missingMaskerData = !m_masker.contains(object);
+ if (missingMaskerData)
m_masker.set(object, new MaskerData);
MaskerData* maskerData = m_masker.get(object);
AffineTransform absoluteTransform;
- SVGImageBufferTools::calculateTransformationToOutermostSVGCoordinateSystem(object, absoluteTransform);
+ SVGRenderingContext::calculateTransformationToOutermostSVGCoordinateSystem(object, absoluteTransform);
FloatRect repaintRect = object->repaintRectInLocalCoordinates();
@@ -105,7 +105,7 @@ bool RenderSVGResourceMasker::applyResource(RenderObject* object, RenderStyle*,
const SVGRenderStyle* svgStyle = style()->svgStyle();
ASSERT(svgStyle);
ColorSpace colorSpace = svgStyle->colorInterpolation() == CI_LINEARRGB ? ColorSpaceLinearRGB : ColorSpaceDeviceRGB;
- if (!SVGImageBufferTools::createImageBuffer(repaintRect, absoluteTransform, maskerData->maskImage, colorSpace, Unaccelerated))
+ if (!SVGRenderingContext::createImageBuffer(repaintRect, absoluteTransform, maskerData->maskImage, colorSpace, Unaccelerated))
return false;
if (!drawContentIntoMaskImage(maskerData, colorSpace, maskElement, object)) {
@@ -116,7 +116,7 @@ bool RenderSVGResourceMasker::applyResource(RenderObject* object, RenderStyle*,
if (!maskerData->maskImage)
return false;
- SVGImageBufferTools::clipToImageBuffer(context, absoluteTransform, repaintRect, maskerData->maskImage);
+ SVGRenderingContext::clipToImageBuffer(context, absoluteTransform, repaintRect, maskerData->maskImage, missingMaskerData);
return true;
}
@@ -144,7 +144,7 @@ bool RenderSVGResourceMasker::drawContentIntoMaskImage(MaskerData* maskerData, C
RenderStyle* style = renderer->style();
if (!style || style->display() == NONE || style->visibility() != VISIBLE)
continue;
- SVGImageBufferTools::renderSubtreeToImageBuffer(maskerData->maskImage.get(), renderer, maskContentTransformation);
+ SVGRenderingContext::renderSubtreeToImageBuffer(maskerData->maskImage.get(), renderer, maskContentTransformation);
}
#if !USE(CG)
diff --git a/Source/WebCore/rendering/svg/RenderSVGResourcePattern.cpp b/Source/WebCore/rendering/svg/RenderSVGResourcePattern.cpp
index f727bb062..4dc501b80 100644
--- a/Source/WebCore/rendering/svg/RenderSVGResourcePattern.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGResourcePattern.cpp
@@ -27,8 +27,8 @@
#include "GraphicsContext.h"
#include "PatternAttributes.h"
#include "RenderSVGRoot.h"
-#include "SVGImageBufferTools.h"
#include "SVGRenderSupport.h"
+#include "SVGRenderingContext.h"
namespace WebCore {
@@ -83,7 +83,7 @@ bool RenderSVGResourcePattern::applyResource(RenderObject* object, RenderStyle*
if (m_attributes.patternUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX && objectBoundingBox.isEmpty())
return false;
- OwnPtr<PatternData>& patternData = m_patternMap.add(object, nullptr).first->second;
+ OwnPtr<PatternData>& patternData = m_patternMap.add(object, nullptr).iterator->second;
if (!patternData)
patternData = adoptPtr(new PatternData);
@@ -99,10 +99,10 @@ bool RenderSVGResourcePattern::applyResource(RenderObject* object, RenderStyle*
return false;
AffineTransform absoluteTransformIgnoringRotation;
- SVGImageBufferTools::calculateTransformationToOutermostSVGCoordinateSystem(object, absoluteTransformIgnoringRotation);
+ SVGRenderingContext::calculateTransformationToOutermostSVGCoordinateSystem(object, absoluteTransformIgnoringRotation);
// Ignore 2D rotation, as it doesn't affect the size of the tile.
- SVGImageBufferTools::clear2DRotation(absoluteTransformIgnoringRotation);
+ SVGRenderingContext::clear2DRotation(absoluteTransformIgnoringRotation);
FloatRect absoluteTileBoundaries = absoluteTransformIgnoringRotation.mapRect(tileBoundaries);
FloatRect clampedAbsoluteTileBoundaries;
@@ -232,11 +232,11 @@ PassOwnPtr<ImageBuffer> RenderSVGResourcePattern::createTileImage(const PatternA
const AffineTransform& tileImageTransform,
FloatRect& clampedAbsoluteTileBoundaries) const
{
- clampedAbsoluteTileBoundaries = SVGImageBufferTools::clampedAbsoluteTargetRect(absoluteTileBoundaries);
+ clampedAbsoluteTileBoundaries = SVGRenderingContext::clampedAbsoluteTargetRect(absoluteTileBoundaries);
OwnPtr<ImageBuffer> tileImage;
- if (!SVGImageBufferTools::createImageBufferForPattern(absoluteTileBoundaries, clampedAbsoluteTileBoundaries, tileImage, ColorSpaceDeviceRGB, Unaccelerated))
+ if (!SVGRenderingContext::createImageBufferForPattern(absoluteTileBoundaries, clampedAbsoluteTileBoundaries, tileImage, ColorSpaceDeviceRGB, Unaccelerated))
return nullptr;
GraphicsContext* tileImageContext = tileImage->context();
@@ -260,7 +260,7 @@ PassOwnPtr<ImageBuffer> RenderSVGResourcePattern::createTileImage(const PatternA
continue;
if (node->renderer()->needsLayout())
return nullptr;
- SVGImageBufferTools::renderSubtreeToImageBuffer(tileImage.get(), node->renderer(), contentTransformation);
+ SVGRenderingContext::renderSubtreeToImageBuffer(tileImage.get(), node->renderer(), contentTransformation);
}
return tileImage.release();
diff --git a/Source/WebCore/rendering/svg/RenderSVGRoot.cpp b/Source/WebCore/rendering/svg/RenderSVGRoot.cpp
index b99701d81..67b8a714b 100644
--- a/Source/WebCore/rendering/svg/RenderSVGRoot.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGRoot.cpp
@@ -36,6 +36,7 @@
#include "RenderPart.h"
#include "RenderSVGContainer.h"
#include "RenderSVGResource.h"
+#include "RenderSVGResourceContainer.h"
#include "RenderView.h"
#include "SVGLength.h"
#include "SVGRenderingContext.h"
@@ -56,6 +57,7 @@ namespace WebCore {
RenderSVGRoot::RenderSVGRoot(SVGStyledElement* node)
: RenderReplaced(node)
+ , m_objectBoundingBoxValid(false)
, m_isLayoutSizeChanged(false)
, m_needsBoundariesOrTransformUpdate(true)
{
@@ -87,9 +89,9 @@ void RenderSVGRoot::computeIntrinsicRatioInformation(FloatSize& intrinsicSize, d
// resolving both values to user units.
if (intrinsicWidthAttribute.isFixed() || intrinsicHeightAttribute.isFixed()) {
if (intrinsicWidthAttribute.isFixed())
- intrinsicSize.setWidth(intrinsicWidthAttribute.calcFloatValue(0));
+ intrinsicSize.setWidth(floatValueForLength(intrinsicWidthAttribute, 0));
if (intrinsicHeightAttribute.isFixed())
- intrinsicSize.setHeight(intrinsicHeightAttribute.calcFloatValue(0));
+ intrinsicSize.setHeight(floatValueForLength(intrinsicHeightAttribute, 0));
if (!intrinsicSize.isEmpty())
intrinsicRatio = intrinsicSize.width() / static_cast<double>(intrinsicSize.height());
return;
@@ -151,9 +153,9 @@ bool RenderSVGRoot::isEmbeddedThroughFrameContainingSVGDocument() const
return frame->document()->isSVGDocument();
}
-static inline LayoutUnit resolveLengthAttributeForSVG(const Length& length, float scale, float maxSize)
+static inline LayoutUnit resolveLengthAttributeForSVG(const Length& length, float scale, float maxSize, RenderView* renderView)
{
- return static_cast<LayoutUnit>(length.calcValue(maxSize) * (length.isFixed() ? scale : 1));
+ return static_cast<LayoutUnit>(valueForLength(length, maxSize, renderView) * (length.isFixed() ? scale : 1));
}
LayoutUnit RenderSVGRoot::computeReplacedLogicalWidth(bool includeMaxWidth) const
@@ -169,7 +171,7 @@ LayoutUnit RenderSVGRoot::computeReplacedLogicalWidth(bool includeMaxWidth) cons
return RenderReplaced::computeReplacedLogicalWidth(includeMaxWidth);
if (svg->widthAttributeEstablishesViewport())
- return resolveLengthAttributeForSVG(svg->intrinsicWidth(SVGSVGElement::IgnoreCSSProperties), style()->effectiveZoom(), containingBlock()->availableLogicalWidth());
+ return resolveLengthAttributeForSVG(svg->intrinsicWidth(SVGSVGElement::IgnoreCSSProperties), style()->effectiveZoom(), containingBlock()->availableLogicalWidth(), view());
// Only SVGs embedded in <object> reach this point.
ASSERT(isEmbeddedThroughFrameContainingSVGDocument());
@@ -200,7 +202,7 @@ LayoutUnit RenderSVGRoot::computeReplacedLogicalHeight() const
} else
RenderBlock::removePercentHeightDescendant(const_cast<RenderSVGRoot*>(this));
- return resolveLengthAttributeForSVG(height, style()->effectiveZoom(), containingBlock()->availableLogicalHeight());
+ return resolveLengthAttributeForSVG(height, style()->effectiveZoom(), containingBlock()->availableLogicalHeight(), view());
}
// Only SVGs embedded in <object> reach this point.
@@ -212,6 +214,8 @@ void RenderSVGRoot::layout()
{
ASSERT(needsLayout());
+ m_resourcesNeedingToInvalidateClients.clear();
+
// Arbitrary affine transforms are incompatible with LayoutState.
LayoutStateDisabler layoutStateDisabler(view());
@@ -227,6 +231,16 @@ void RenderSVGRoot::layout()
m_isLayoutSizeChanged = needsLayout || (svg->hasRelativeLengths() && oldSize != size());
SVGRenderSupport::layoutChildren(this, needsLayout || SVGRenderSupport::filtersForceContainerLayout(this));
+ if (!m_resourcesNeedingToInvalidateClients.isEmpty()) {
+ // Invalidate resource clients, which may mark some nodes for layout.
+ HashSet<RenderSVGResourceContainer*>::iterator end = m_resourcesNeedingToInvalidateClients.end();
+ for (HashSet<RenderSVGResourceContainer*>::iterator it = m_resourcesNeedingToInvalidateClients.begin(); it != end; ++it)
+ (*it)->removeAllClientsFromCache();
+
+ m_isLayoutSizeChanged = false;
+ SVGRenderSupport::layoutChildren(this, false);
+ }
+
// At this point LayoutRepainter already grabbed the old bounds,
// recalculate them now so repaintAfterLayout() uses the new bounds.
if (m_needsBoundariesOrTransformUpdate) {
@@ -239,10 +253,10 @@ void RenderSVGRoot::layout()
setNeedsLayout(false);
}
-void RenderSVGRoot::paintReplaced(PaintInfo& paintInfo, const LayoutPoint& adjustedPaintOffset)
+void RenderSVGRoot::paintReplaced(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
// An empty viewport disables rendering.
- if (borderBoxRect().isEmpty())
+ if (pixelSnappedBorderBoxRect().isEmpty())
return;
// Don't paint, if the context explicitely disabled it.
@@ -271,10 +285,11 @@ void RenderSVGRoot::paintReplaced(PaintInfo& paintInfo, const LayoutPoint& adjus
childPaintInfo.context->save();
// Apply initial viewport clip - not affected by overflow handling
- childPaintInfo.context->clip(overflowClipRect(adjustedPaintOffset, paintInfo.renderRegion));
+ childPaintInfo.context->clip(pixelSnappedIntRect(overflowClipRect(paintOffset, paintInfo.renderRegion)));
// Convert from container offsets (html renderers) to a relative transform (svg renderers).
// Transform from our paint container's coordinate system to our local coords.
+ IntPoint adjustedPaintOffset = roundedIntPoint(paintOffset);
childPaintInfo.applyTransform(AffineTransform::translation(adjustedPaintOffset.x() - x(), adjustedPaintOffset.y() - y()) * localToParentTransform());
SVGRenderingContext renderingContext;
@@ -354,7 +369,7 @@ void RenderSVGRoot::computeFloatRectForRepaint(RenderBoxModelObject* repaintCont
repaintRect = m_localToBorderBoxTransform.mapRect(repaintRect);
// Apply initial viewport clip - not affected by overflow settings
- repaintRect.intersect(borderBoxRect());
+ repaintRect.intersect(pixelSnappedBorderBoxRect());
const SVGRenderStyle* svgStyle = style()->svgStyle();
if (const ShadowData* shadow = svgStyle->shadow())
@@ -365,23 +380,25 @@ void RenderSVGRoot::computeFloatRectForRepaint(RenderBoxModelObject* repaintCont
repaintRect = rect;
}
-void RenderSVGRoot::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed, bool useTransforms, TransformState& transformState, bool* wasFixed) const
+// This method expects local CSS box coordinates.
+// Callers with local SVG viewport coordinates should first apply the localToBorderBoxTransform
+// to convert from SVG viewport coordinates to local CSS box coordinates.
+void RenderSVGRoot::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed, bool useTransforms, TransformState& transformState, ApplyContainerFlipOrNot, bool* wasFixed) const
{
ASSERT(!fixed); // We should have no fixed content in the SVG rendering tree.
ASSERT(useTransforms); // mapping a point through SVG w/o respecting trasnforms is useless.
- // Transform to our border box and let RenderBox transform the rest of the way.
- transformState.applyTransform(m_localToBorderBoxTransform);
- RenderReplaced::mapLocalToContainer(repaintContainer, fixed, useTransforms, transformState, wasFixed);
+ RenderReplaced::mapLocalToContainer(repaintContainer, fixed, useTransforms, transformState, ApplyContainerFlip, wasFixed);
}
void RenderSVGRoot::updateCachedBoundaries()
{
m_objectBoundingBox = FloatRect();
+ m_objectBoundingBoxValid = false;
m_strokeBoundingBox = FloatRect();
m_repaintBoundingBox = FloatRect();
- SVGRenderSupport::computeContainerBoundingBoxes(this, m_objectBoundingBox, m_strokeBoundingBox, m_repaintBoundingBox);
+ SVGRenderSupport::computeContainerBoundingBoxes(this, m_objectBoundingBox, m_objectBoundingBoxValid, m_strokeBoundingBox, m_repaintBoundingBox);
SVGRenderSupport::intersectRepaintRectWithResources(this, m_repaintBoundingBox);
m_repaintBoundingBox.inflate(borderAndPaddingWidth());
}
@@ -428,6 +445,24 @@ bool RenderSVGRoot::hasRelativeDimensions() const
return svg->intrinsicHeight(SVGSVGElement::IgnoreCSSProperties).isPercent() || svg->intrinsicWidth(SVGSVGElement::IgnoreCSSProperties).isPercent();
}
+bool RenderSVGRoot::hasRelativeLogicalHeight() const
+{
+ SVGSVGElement* svg = static_cast<SVGSVGElement*>(node());
+ ASSERT(svg);
+
+ return svg->intrinsicHeight(SVGSVGElement::IgnoreCSSProperties).isPercent();
+}
+
+void RenderSVGRoot::addResourceForClientInvalidation(RenderSVGResourceContainer* resource)
+{
+ RenderObject* svgRoot = resource->parent();
+ while (svgRoot && !svgRoot->isSVGRoot())
+ svgRoot = svgRoot->parent();
+ if (!svgRoot)
+ return;
+ static_cast<RenderSVGRoot*>(svgRoot)->m_resourcesNeedingToInvalidateClients.add(resource);
+}
+
}
#endif // ENABLE(SVG)
diff --git a/Source/WebCore/rendering/svg/RenderSVGRoot.h b/Source/WebCore/rendering/svg/RenderSVGRoot.h
index adc1884e4..c334afbe6 100644
--- a/Source/WebCore/rendering/svg/RenderSVGRoot.h
+++ b/Source/WebCore/rendering/svg/RenderSVGRoot.h
@@ -54,6 +54,14 @@ public:
void setContainerSize(const IntSize& containerSize) { m_containerSize = containerSize; }
virtual bool hasRelativeDimensions() const;
+ virtual bool hasRelativeLogicalHeight() const;
+
+ // localToBorderBoxTransform maps local SVG viewport coordinates to local CSS box coordinates.
+ const AffineTransform& localToBorderBoxTransform() const { return m_localToBorderBoxTransform; }
+
+ // The flag is cleared at the beginning of each layout() pass. Elements then call this
+ // method during layout when they are invalidated by a filter.
+ static void addResourceForClientInvalidation(RenderSVGResourceContainer*);
private:
virtual RenderObjectChildList* virtualChildren() { return children(); }
@@ -86,7 +94,7 @@ private:
virtual LayoutRect clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer) const;
virtual void computeFloatRectForRepaint(RenderBoxModelObject* repaintContainer, FloatRect& repaintRect, bool fixed) const;
- virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool useTransforms, bool fixed, TransformState&, bool* wasFixed = 0) const;
+ virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool useTransforms, bool fixed, TransformState&, ApplyContainerFlipOrNot = ApplyContainerFlip, bool* wasFixed = 0) const;
virtual bool canBeSelectionLeaf() const { return false; }
virtual bool canHaveChildren() const { return true; }
@@ -96,10 +104,12 @@ private:
RenderObjectChildList m_children;
IntSize m_containerSize;
FloatRect m_objectBoundingBox;
+ bool m_objectBoundingBoxValid;
FloatRect m_strokeBoundingBox;
FloatRect m_repaintBoundingBox;
mutable AffineTransform m_localToParentTransform;
AffineTransform m_localToBorderBoxTransform;
+ HashSet<RenderSVGResourceContainer*> m_resourcesNeedingToInvalidateClients;
bool m_isLayoutSizeChanged : 1;
bool m_needsBoundariesOrTransformUpdate : 1;
};
diff --git a/Source/WebCore/rendering/svg/RenderSVGShape.cpp b/Source/WebCore/rendering/svg/RenderSVGShape.cpp
index c438d30b0..c3481ce40 100755
--- a/Source/WebCore/rendering/svg/RenderSVGShape.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGShape.cpp
@@ -62,13 +62,6 @@ RenderSVGShape::RenderSVGShape(SVGStyledTransformableElement* node)
{
}
-RenderSVGShape::RenderSVGShape(SVGStyledTransformableElement* node, Path* path, bool isFillFallback)
- : RenderSVGModelObject(node)
- , m_path(adoptPtr(path))
- , m_fillFallback(isFillFallback)
-{
-}
-
RenderSVGShape::~RenderSVGShape()
{
}
@@ -101,7 +94,8 @@ FloatRect RenderSVGShape::objectBoundingBox() const
void RenderSVGShape::strokeShape(GraphicsContext* context) const
{
- context->strokePath(path());
+ if (style()->svgStyle()->hasVisibleStroke())
+ context->strokePath(path());
}
bool RenderSVGShape::shapeDependentStrokeContains(const FloatPoint& point) const
@@ -129,7 +123,7 @@ bool RenderSVGShape::fillContains(const FloatPoint& point, bool requiresFill, co
bool RenderSVGShape::strokeContains(const FloatPoint& point, bool requiresStroke)
{
- if (!m_strokeAndMarkerBoundingBox.contains(point))
+ if (!strokeBoundingBox().contains(point))
return false;
Color fallbackColor;
@@ -152,7 +146,7 @@ bool RenderSVGShape::strokeContains(const FloatPoint& point, bool requiresStroke
}
if (!svgStyle->strokeDashArray().isEmpty() || svgStyle->strokeMiterLimit() != svgStyle->initialStrokeMiterLimit()
- || svgStyle->joinStyle() != svgStyle->initialJoinStyle() || svgStyle->capStyle() != svgStyle->initialCapStyle() || static_cast<SVGElement*>(node())->isStyled()) {
+ || svgStyle->joinStyle() != svgStyle->initialJoinStyle() || svgStyle->capStyle() != svgStyle->initialCapStyle()) {
if (!m_path)
RenderSVGShape::createShape();
return RenderSVGShape::shapeDependentStrokeContains(point);
@@ -272,6 +266,8 @@ void RenderSVGShape::strokePath(RenderStyle* style, GraphicsContext* context, Pa
const Color& fallbackColor, bool nonScalingStroke, const AffineTransform& nonScalingStrokeTransform,
int applyMode)
{
+ if (!style->svgStyle()->hasVisibleStroke())
+ return;
Path* usePath = path;
if (nonScalingStroke) {
usePath = nonScalingStrokePath(path, nonScalingStrokeTransform);
@@ -318,7 +314,7 @@ void RenderSVGShape::fillAndStrokePath(GraphicsContext* context)
}
-void RenderSVGShape::paint(PaintInfo& paintInfo, const IntPoint&)
+void RenderSVGShape::paint(PaintInfo& paintInfo, const LayoutPoint&)
{
if (paintInfo.context->paintingDisabled() || style()->visibility() == HIDDEN || isEmpty())
return;
diff --git a/Source/WebCore/rendering/svg/RenderSVGShape.h b/Source/WebCore/rendering/svg/RenderSVGShape.h
index 934a05d39..ab9b1cb5a 100644
--- a/Source/WebCore/rendering/svg/RenderSVGShape.h
+++ b/Source/WebCore/rendering/svg/RenderSVGShape.h
@@ -144,7 +144,6 @@ private:
bool m_needsShapeUpdate : 1;
bool m_needsTransformUpdate : 1;
bool m_fillFallback : 1;
- bool m_strokeContainsFallBack : 1;
};
inline RenderSVGShape* toRenderSVGShape(RenderObject* object)
diff --git a/Source/WebCore/rendering/svg/RenderSVGText.cpp b/Source/WebCore/rendering/svg/RenderSVGText.cpp
index d9cdeccdf..f512ab87b 100644
--- a/Source/WebCore/rendering/svg/RenderSVGText.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGText.cpp
@@ -6,6 +6,7 @@
* Copyright (C) 2008 Rob Buis <buis@kde.org>
* Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
* Copyright (C) Research In Motion Limited 2010-2012. All rights reserved.
+ * Copyright (C) 2012 Google Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -104,7 +105,7 @@ void RenderSVGText::computeFloatRectForRepaint(RenderBoxModelObject* repaintCont
SVGRenderSupport::computeFloatRectForRepaint(this, repaintContainer, repaintRect, fixed);
}
-void RenderSVGText::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool /* fixed */, bool /* useTransforms */, TransformState& transformState, bool* wasFixed) const
+void RenderSVGText::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool /* fixed */, bool /* useTransforms */, TransformState& transformState, ApplyContainerFlipOrNot, bool* wasFixed) const
{
SVGRenderSupport::mapLocalToContainer(this, repaintContainer, transformState, wasFixed);
}
@@ -177,10 +178,12 @@ void RenderSVGText::layoutAttributesWillBeDestroyed(RenderSVGInlineText* text, V
affectedAttributes.append(next);
}
-void RenderSVGText::textDOMChanged()
+void RenderSVGText::invalidateTextPositioningElements()
{
- if (m_needsPositioningValuesUpdate)
- return;
+ // 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();
}
@@ -330,7 +333,7 @@ void RenderSVGText::paint(PaintInfo& paintInfo, const LayoutPoint&)
PaintInfo blockInfo(paintInfo);
GraphicsContextStateSaver stateSaver(*blockInfo.context);
blockInfo.applyTransform(localToParentTransform());
- RenderBlock::paint(blockInfo, IntPoint());
+ RenderBlock::paint(blockInfo, LayoutPoint());
}
FloatRect RenderSVGText::strokeBoundingBox() const
diff --git a/Source/WebCore/rendering/svg/RenderSVGText.h b/Source/WebCore/rendering/svg/RenderSVGText.h
index 7b0b5efa8..5665b4442 100644
--- a/Source/WebCore/rendering/svg/RenderSVGText.h
+++ b/Source/WebCore/rendering/svg/RenderSVGText.h
@@ -49,7 +49,10 @@ public:
bool needsReordering() const { return m_needsReordering; }
- void textDOMChanged();
+ // 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 layoutAttributesChanged(RenderObject*);
void layoutAttributesWillBeDestroyed(RenderSVGInlineText*, Vector<SVGTextLayoutAttributes*>& affectedAttributes);
void rebuildLayoutAttributes(bool performFullRebuild = false);
@@ -75,7 +78,7 @@ private:
virtual void computeRectForRepaint(RenderBoxModelObject* repaintContainer, LayoutRect&, bool fixed = false) const;
virtual void computeFloatRectForRepaint(RenderBoxModelObject* repaintContainer, FloatRect&, bool fixed = false) const;
- virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool useTransforms, bool fixed, TransformState&, bool* wasFixed = 0) const;
+ 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 FloatRect objectBoundingBox() const { return frameRect(); }
diff --git a/Source/WebCore/rendering/svg/SVGImageBufferTools.cpp b/Source/WebCore/rendering/svg/SVGImageBufferTools.cpp
deleted file mode 100644
index 899550055..000000000
--- a/Source/WebCore/rendering/svg/SVGImageBufferTools.cpp
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright (C) Research In Motion Limited 2010. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-
-#if ENABLE(SVG)
-#include "SVGImageBufferTools.h"
-
-#include "FrameView.h"
-#include "GraphicsContext.h"
-#include "RenderObject.h"
-#include "RenderSVGContainer.h"
-#include "RenderSVGRoot.h"
-
-static int kMaxImageBufferSize = 4096;
-
-namespace WebCore {
-
-static AffineTransform& currentContentTransformation()
-{
- DEFINE_STATIC_LOCAL(AffineTransform, s_currentContentTransformation, ());
- return s_currentContentTransformation;
-}
-
-void SVGImageBufferTools::calculateTransformationToOutermostSVGCoordinateSystem(const RenderObject* renderer, AffineTransform& absoluteTransform)
-{
- const RenderObject* current = renderer;
- ASSERT(current);
-
- absoluteTransform = currentContentTransformation();
- while (current) {
- absoluteTransform = current->localToParentTransform() * absoluteTransform;
- if (current->isSVGRoot())
- break;
- current = current->parent();
- }
-}
-
-bool SVGImageBufferTools::createImageBuffer(const FloatRect& targetRect, const AffineTransform& absoluteTransform, OwnPtr<ImageBuffer>& imageBuffer, ColorSpace colorSpace, RenderingMode renderingMode)
-{
- IntRect paintRect = calculateImageBufferRect(targetRect, absoluteTransform);
- // Don't create empty ImageBuffers.
- if (paintRect.isEmpty())
- return false;
-
- IntSize clampedSize = clampedAbsoluteSize(paintRect.size());
- OwnPtr<ImageBuffer> image = ImageBuffer::create(clampedSize, 1, colorSpace, renderingMode);
- if (!image)
- return false;
-
- GraphicsContext* imageContext = image->context();
- ASSERT(imageContext);
-
- // This is done in absolute coordinates.
- imageContext->translate(-paintRect.x(), -paintRect.y());
-
- imageContext->concatCTM(absoluteTransform);
-
- // This happens in local coordinates.
- imageContext->scale(FloatSize(static_cast<float>(clampedSize.width()) / paintRect.width(),
- static_cast<float>(clampedSize.height()) / paintRect.height()));
-
- imageBuffer = image.release();
- return true;
-}
-
-bool SVGImageBufferTools::createImageBufferForPattern(const FloatRect& absoluteTargetRect, const FloatRect& clampedAbsoluteTargetRect, OwnPtr<ImageBuffer>& imageBuffer, ColorSpace colorSpace, RenderingMode renderingMode)
-{
- IntSize imageSize(roundedIntSize(clampedAbsoluteTargetRect.size()));
- IntSize unclampedImageSize(roundedIntSize(absoluteTargetRect.size()));
-
- // Don't create empty ImageBuffers.
- if (imageSize.isEmpty())
- return false;
-
- OwnPtr<ImageBuffer> image = ImageBuffer::create(imageSize, 1, colorSpace, renderingMode);
- if (!image)
- return false;
-
- GraphicsContext* imageContext = image->context();
- ASSERT(imageContext);
-
- // Compensate rounding effects, as the absolute target rect is using floating-point numbers and the image buffer size is integer.
- imageContext->scale(FloatSize(unclampedImageSize.width() / absoluteTargetRect.width(), unclampedImageSize.height() / absoluteTargetRect.height()));
-
- imageBuffer = image.release();
- return true;
-}
-
-void SVGImageBufferTools::renderSubtreeToImageBuffer(ImageBuffer* image, RenderObject* item, const AffineTransform& subtreeContentTransformation)
-{
- ASSERT(item);
- ASSERT(image);
- ASSERT(image->context());
-
- PaintInfo info(image->context(), PaintInfo::infiniteRect(), PaintPhaseForeground, 0, 0, 0, 0);
-
- AffineTransform& contentTransformation = currentContentTransformation();
- AffineTransform savedContentTransformation = contentTransformation;
- contentTransformation = subtreeContentTransformation * contentTransformation;
-
- ASSERT(!item->needsLayout());
- item->paint(info, IntPoint());
-
- contentTransformation = savedContentTransformation;
-}
-
-void SVGImageBufferTools::clipToImageBuffer(GraphicsContext* context, const AffineTransform& absoluteTransform, const FloatRect& targetRect, OwnPtr<ImageBuffer>& imageBuffer)
-{
- ASSERT(context);
- ASSERT(imageBuffer);
-
- FloatRect absoluteTargetRect = calculateImageBufferRect(targetRect, absoluteTransform);
-
- // The mask image has been created in the absolute coordinate space, as the image should not be scaled.
- // So the actual masking process has to be done in the absolute coordinate space as well.
- context->concatCTM(absoluteTransform.inverse());
- context->clipToImageBuffer(imageBuffer.get(), absoluteTargetRect);
- context->concatCTM(absoluteTransform);
-
- // When nesting resources, with objectBoundingBox as content unit types, there's no use in caching the
- // resulting image buffer as the parent resource already caches the result.
- if (!currentContentTransformation().isIdentity())
- imageBuffer.clear();
-}
-
-FloatRect SVGImageBufferTools::clampedAbsoluteTargetRect(const FloatRect& absoluteTargetRect)
-{
- const FloatSize maxImageBufferSize(kMaxImageBufferSize, kMaxImageBufferSize);
- return FloatRect(absoluteTargetRect.location(), absoluteTargetRect.size().shrunkTo(maxImageBufferSize));
-}
-
-IntSize SVGImageBufferTools::clampedAbsoluteSize(const IntSize& absoluteSize)
-{
- const IntSize maxImageBufferSize(kMaxImageBufferSize, kMaxImageBufferSize);
- return absoluteSize.shrunkTo(maxImageBufferSize);
-}
-
-void SVGImageBufferTools::clear2DRotation(AffineTransform& transform)
-{
- AffineTransform::DecomposedType decomposition;
- transform.decompose(decomposition);
- decomposition.angle = 0;
- transform.recompose(decomposition);
-}
-
-}
-
-#endif // ENABLE(SVG)
diff --git a/Source/WebCore/rendering/svg/SVGImageBufferTools.h b/Source/WebCore/rendering/svg/SVGImageBufferTools.h
deleted file mode 100644
index dce80cc96..000000000
--- a/Source/WebCore/rendering/svg/SVGImageBufferTools.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) Research In Motion Limited 2010. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef SVGImageBufferTools_h
-#define SVGImageBufferTools_h
-
-#if ENABLE(SVG)
-#include "ImageBuffer.h"
-#include "IntRect.h"
-#include <wtf/Noncopyable.h>
-
-namespace WebCore {
-
-class AffineTransform;
-class FloatRect;
-class FloatSize;
-class GraphicsContext;
-class RenderObject;
-
-class SVGImageBufferTools {
- WTF_MAKE_NONCOPYABLE(SVGImageBufferTools);
-
-public:
- static bool createImageBuffer(const FloatRect& paintRect, const AffineTransform& absoluteTransform, OwnPtr<ImageBuffer>&, ColorSpace, RenderingMode);
- // Patterns need a different float-to-integer coordinate mapping.
- static bool createImageBufferForPattern(const FloatRect& absoluteTargetRect, const FloatRect& clampedAbsoluteTargetRect, OwnPtr<ImageBuffer>&, ColorSpace, RenderingMode);
-
- static void renderSubtreeToImageBuffer(ImageBuffer*, RenderObject*, const AffineTransform&);
- static void clipToImageBuffer(GraphicsContext*, const AffineTransform& absoluteTransform, const FloatRect& targetRect, OwnPtr<ImageBuffer>&);
-
- static void calculateTransformationToOutermostSVGCoordinateSystem(const RenderObject*, AffineTransform& absoluteTransform);
- static IntSize clampedAbsoluteSize(const IntSize&);
- static FloatRect clampedAbsoluteTargetRect(const FloatRect& absoluteTargetRect);
- static void clear2DRotation(AffineTransform&);
-
- static IntRect calculateImageBufferRect(const FloatRect& targetRect, const AffineTransform& absoluteTransform)
- {
- return enclosingIntRect(absoluteTransform.mapRect(targetRect));
- }
-
-private:
- SVGImageBufferTools() { }
- ~SVGImageBufferTools() { }
-};
-
-}
-
-#endif
-#endif
diff --git a/Source/WebCore/rendering/svg/SVGInlineTextBox.cpp b/Source/WebCore/rendering/svg/SVGInlineTextBox.cpp
index c4b60df08..27ba5fbce 100644
--- a/Source/WebCore/rendering/svg/SVGInlineTextBox.cpp
+++ b/Source/WebCore/rendering/svg/SVGInlineTextBox.cpp
@@ -35,7 +35,7 @@
#include "RenderSVGInlineText.h"
#include "RenderSVGResource.h"
#include "RenderSVGResourceSolidColor.h"
-#include "SVGImageBufferTools.h"
+#include "SVGRenderingContext.h"
#include "SVGResourcesCache.h"
#include "SVGRootInlineBox.h"
#include "SVGTextRunRenderingContext.h"
@@ -53,6 +53,14 @@ SVGInlineTextBox::SVGInlineTextBox(RenderObject* object)
{
}
+void SVGInlineTextBox::dirtyLineBoxes()
+{
+ InlineTextBox::dirtyLineBoxes();
+
+ // Clear the now stale text fragments
+ clearTextFragments();
+}
+
int SVGInlineTextBox::offsetForPosition(float, bool) const
{
// SVG doesn't use the standard offset <-> position selection system, as it's not suitable for SVGs complex needs.
@@ -120,13 +128,13 @@ FloatRect SVGInlineTextBox::selectionRectForTextFragment(const SVGTextFragment&
return selectionRect;
}
-IntRect SVGInlineTextBox::localSelectionRect(int startPosition, int endPosition)
+LayoutRect SVGInlineTextBox::localSelectionRect(int startPosition, int endPosition)
{
int boxStart = start();
startPosition = max(startPosition - boxStart, 0);
endPosition = min(endPosition - boxStart, static_cast<int>(len()));
if (startPosition >= endPosition)
- return IntRect();
+ return LayoutRect();
RenderText* text = textRenderer();
ASSERT(text);
@@ -266,7 +274,7 @@ void SVGInlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint&, LayoutUni
ASSERT(svgStyle);
bool hasFill = svgStyle->hasFill();
- bool hasStroke = svgStyle->hasStroke();
+ bool hasVisibleStroke = svgStyle->hasVisibleStroke();
RenderStyle* selectionStyle = style;
if (hasSelection) {
@@ -277,15 +285,15 @@ void SVGInlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint&, LayoutUni
if (!hasFill)
hasFill = svgSelectionStyle->hasFill();
- if (!hasStroke)
- hasStroke = svgSelectionStyle->hasStroke();
+ if (!hasVisibleStroke)
+ hasVisibleStroke = svgSelectionStyle->hasVisibleStroke();
} else
selectionStyle = style;
}
if (textRenderer->frame() && textRenderer->frame()->view() && textRenderer->frame()->view()->paintBehavior() & PaintBehaviorRenderingSVGMask) {
hasFill = true;
- hasStroke = false;
+ hasVisibleStroke = false;
}
AffineTransform fragmentTransform;
@@ -313,7 +321,7 @@ void SVGInlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint&, LayoutUni
}
// Stroke text
- if (hasStroke) {
+ if (hasVisibleStroke) {
m_paintingResourceMode = ApplyToStrokeMode | ApplyToTextMode;
paintText(paintInfo.context, style, selectionStyle, fragment, hasSelection, paintSelectedTextOnly);
}
@@ -419,7 +427,7 @@ TextRun SVGInlineTextBox::constructTextRun(RenderStyle* style, const SVGTextFrag
, 0 /* padding, only relevant for justified text, not relevant for SVG */
, TextRun::AllowTrailingExpansion
, direction()
- , m_dirOverride || style->rtlOrdering() == VisualOrder /* directionalOverride */);
+ , dirOverride() || style->rtlOrdering() == VisualOrder /* directionalOverride */);
if (textRunNeedsRenderingContext(style->font()))
run.setRenderingContext(SVGTextRunRenderingContext::create(text));
@@ -518,14 +526,14 @@ void SVGInlineTextBox::paintDecoration(GraphicsContext* context, ETextDecoration
ASSERT(svgDecorationStyle);
bool hasDecorationFill = svgDecorationStyle->hasFill();
- bool hasDecorationStroke = svgDecorationStyle->hasStroke();
+ bool hasVisibleDecorationStroke = svgDecorationStyle->hasVisibleStroke();
if (hasDecorationFill) {
m_paintingResourceMode = ApplyToFillMode;
paintDecorationWithStyle(context, decoration, fragment, decorationRenderer);
}
- if (hasDecorationStroke) {
+ if (hasVisibleDecorationStroke) {
m_paintingResourceMode = ApplyToStrokeMode;
paintDecorationWithStyle(context, decoration, fragment, decorationRenderer);
}
diff --git a/Source/WebCore/rendering/svg/SVGInlineTextBox.h b/Source/WebCore/rendering/svg/SVGInlineTextBox.h
index 4d0c048bd..d3b9d799d 100644
--- a/Source/WebCore/rendering/svg/SVGInlineTextBox.h
+++ b/Source/WebCore/rendering/svg/SVGInlineTextBox.h
@@ -47,7 +47,7 @@ public:
void paintSelectionBackground(PaintInfo&);
virtual void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom);
- virtual IntRect localSelectionRect(int startPosition, int endPosition);
+ virtual LayoutRect localSelectionRect(int startPosition, int endPosition);
bool mapStartEndPositionsIntoFragmentCoordinates(const SVGTextFragment&, int& startPosition, int& endPosition) const;
@@ -57,6 +57,8 @@ public:
Vector<SVGTextFragment>& textFragments() { return m_textFragments; }
const Vector<SVGTextFragment>& textFragments() const { return m_textFragments; }
+ void dirtyLineBoxes() OVERRIDE;
+
bool startsNewTextChunk() const { return m_startsNewTextChunk; }
void setStartsNewTextChunk(bool newTextChunk) { m_startsNewTextChunk = newTextChunk; }
diff --git a/Source/WebCore/rendering/svg/SVGPathData.cpp b/Source/WebCore/rendering/svg/SVGPathData.cpp
index 15a2551d7..98c80b22f 100644
--- a/Source/WebCore/rendering/svg/SVGPathData.cpp
+++ b/Source/WebCore/rendering/svg/SVGPathData.cpp
@@ -21,12 +21,13 @@
#include "SVGPathData.h"
#if ENABLE(SVG)
+#include "Path.h"
#include "SVGCircleElement.h"
#include "SVGEllipseElement.h"
#include "SVGLineElement.h"
#include "SVGNames.h"
#include "SVGPathElement.h"
-#include "SVGPathParserFactory.h"
+#include "SVGPathUtilities.h"
#include "SVGPolygonElement.h"
#include "SVGPolylineElement.h"
#include "SVGRectElement.h"
@@ -73,7 +74,7 @@ static void updatePathFromLineElement(SVGElement* element, Path& path)
static void updatePathFromPathElement(SVGElement* element, Path& path)
{
ASSERT(element->hasTagName(SVGNames::pathTag));
- SVGPathParserFactory::self()->buildPathFromByteStream(static_cast<SVGPathElement*>(element)->pathByteStream(), path);
+ buildPathFromByteStream(static_cast<SVGPathElement*>(element)->pathByteStream(), path);
}
static void updatePathFromPolygonElement(SVGElement* element, Path& path)
@@ -133,7 +134,10 @@ static void updatePathFromRectElement(SVGElement* element, Path& path)
rx = ry;
else if (!hasRy)
ry = rx;
- path.addRoundedRect(FloatRect(x, y, width, height), FloatSize(rx, ry));
+ // FIXME: We currently enforce using beziers here, as at least on CoreGraphics/Lion, as
+ // the native method uses a different line dash origin, causing svg/custom/dashOrigin.svg to fail.
+ // See bug https://bugs.webkit.org/show_bug.cgi?id=79932 which tracks this issue.
+ path.addRoundedRect(FloatRect(x, y, width, height), FloatSize(rx, ry), Path::PreferBezierRoundedRect);
return;
}
diff --git a/Source/WebCore/rendering/svg/SVGRenderSupport.cpp b/Source/WebCore/rendering/svg/SVGRenderSupport.cpp
index e262422ad..b206cb6c2 100644
--- a/Source/WebCore/rendering/svg/SVGRenderSupport.cpp
+++ b/Source/WebCore/rendering/svg/SVGRenderSupport.cpp
@@ -73,35 +73,50 @@ void SVGRenderSupport::computeFloatRectForRepaint(const RenderObject* object, Re
void SVGRenderSupport::mapLocalToContainer(const RenderObject* object, RenderBoxModelObject* repaintContainer, TransformState& transformState, bool* wasFixed)
{
transformState.applyTransform(object->localToParentTransform());
- object->parent()->mapLocalToContainer(repaintContainer, false, true, transformState, wasFixed);
+
+ RenderObject* parent = object->parent();
+
+ // At the SVG/HTML boundary (aka RenderSVGRoot), we apply the localToBorderBoxTransform
+ // to map an element from SVG viewport coordinates to CSS box coordinates.
+ // RenderSVGRoot's mapLocalToContainer method expects CSS box coordinates.
+ if (parent->isSVGRoot())
+ transformState.applyTransform(toRenderSVGRoot(parent)->localToBorderBoxTransform());
+
+ parent->mapLocalToContainer(repaintContainer, false, true, transformState, RenderObject::DoNotApplyContainerFlip, wasFixed);
}
-void SVGRenderSupport::computeContainerBoundingBoxes(const RenderObject* container, FloatRect& objectBoundingBox, FloatRect& strokeBoundingBox, FloatRect& repaintBoundingBox)
+// Update a bounding box taking into account the validity of the other bounding box.
+static inline void updateObjectBoundingBox(FloatRect& objectBoundingBox, bool& objectBoundingBoxValid, RenderObject* other, FloatRect otherBoundingBox)
{
- bool isFirstChild = true;
+ bool otherValid = other->isSVGContainer() ? toRenderSVGContainer(other)->isObjectBoundingBoxValid() : true;
+ if (!otherValid)
+ return;
+
+ if (!objectBoundingBoxValid) {
+ objectBoundingBox = otherBoundingBox;
+ objectBoundingBoxValid = true;
+ return;
+ }
+ objectBoundingBox.uniteEvenIfEmpty(otherBoundingBox);
+}
+
+void SVGRenderSupport::computeContainerBoundingBoxes(const RenderObject* container, FloatRect& objectBoundingBox, bool& objectBoundingBoxValid, FloatRect& strokeBoundingBox, FloatRect& repaintBoundingBox)
+{
for (RenderObject* current = container->firstChild(); current; current = current->nextSibling()) {
if (current->isSVGHiddenContainer())
continue;
const AffineTransform& transform = current->localToParentTransform();
if (transform.isIdentity()) {
- if (isFirstChild)
- objectBoundingBox = current->objectBoundingBox();
- else
- objectBoundingBox.uniteEvenIfEmpty(current->objectBoundingBox());
+ updateObjectBoundingBox(objectBoundingBox, objectBoundingBoxValid, current, current->objectBoundingBox());
strokeBoundingBox.unite(current->strokeBoundingBox());
repaintBoundingBox.unite(current->repaintRectInLocalCoordinates());
} else {
- if (isFirstChild)
- objectBoundingBox = transform.mapRect(current->objectBoundingBox());
- else
- objectBoundingBox.uniteEvenIfEmpty(transform.mapRect(current->objectBoundingBox()));
+ updateObjectBoundingBox(objectBoundingBox, objectBoundingBoxValid, current, transform.mapRect(current->objectBoundingBox()));
strokeBoundingBox.unite(transform.mapRect(current->strokeBoundingBox()));
repaintBoundingBox.unite(transform.mapRect(current->repaintRectInLocalCoordinates()));
}
-
- isFirstChild = false;
}
}
@@ -191,7 +206,7 @@ void SVGRenderSupport::layoutChildren(RenderObject* start, bool selfNeedsLayout)
}
if (needsLayout) {
- child->setNeedsLayout(true, false);
+ child->setNeedsLayout(true, MarkOnlyThis);
child->layout();
} else {
if (child->needsLayout())
@@ -219,7 +234,7 @@ bool SVGRenderSupport::isOverflowHidden(const RenderObject* object)
// SVG doesn't support independent x/y overflow
ASSERT(object->style()->overflowX() == object->style()->overflowY());
- // OSCROLL is never set for SVG - see CSSStyleSelector::adjustRenderStyle
+ // OSCROLL is never set for SVG - see StyleResolver::adjustRenderStyle
ASSERT(object->style()->overflowX() != OSCROLL);
// RenderSVGRoot should never query for overflow state - it should always clip itself to the initial viewport size.
diff --git a/Source/WebCore/rendering/svg/SVGRenderSupport.h b/Source/WebCore/rendering/svg/SVGRenderSupport.h
index 51c9d1bc0..e25b12f06 100644
--- a/Source/WebCore/rendering/svg/SVGRenderSupport.h
+++ b/Source/WebCore/rendering/svg/SVGRenderSupport.h
@@ -57,7 +57,7 @@ public:
// Determines whether the passed point lies in a clipping area
static bool pointInClippingArea(RenderObject*, const FloatPoint&);
- static void computeContainerBoundingBoxes(const RenderObject* container, FloatRect& objectBoundingBox, FloatRect& strokeBoundingBox, FloatRect& repaintBoundingBox);
+ static void computeContainerBoundingBoxes(const RenderObject* container, FloatRect& objectBoundingBox, bool& objectBoundingBoxValid, FloatRect& strokeBoundingBox, FloatRect& repaintBoundingBox);
static bool paintInfoIntersectsRepaintRect(const FloatRect& localRepaintRect, const AffineTransform& localTransform, const PaintInfo&);
// Important functions used by nearly all SVG renderers centralizing coordinate transformations / repaint rect calculations
diff --git a/Source/WebCore/rendering/svg/SVGRenderTreeAsText.cpp b/Source/WebCore/rendering/svg/SVGRenderTreeAsText.cpp
index 8db295f38..966dd46b1 100755
--- a/Source/WebCore/rendering/svg/SVGRenderTreeAsText.cpp
+++ b/Source/WebCore/rendering/svg/SVGRenderTreeAsText.cpp
@@ -65,7 +65,7 @@
#include "SVGLinearGradientElement.h"
#include "SVGNames.h"
#include "SVGPathElement.h"
-#include "SVGPathParserFactory.h"
+#include "SVGPathUtilities.h"
#include "SVGPatternElement.h"
#include "SVGPointList.h"
#include "SVGPolyElement.h"
@@ -326,7 +326,7 @@ static void writeStyle(TextStream& ts, const RenderObject& object)
static TextStream& writePositionAndStyle(TextStream& ts, const RenderObject& object)
{
- ts << " " << const_cast<RenderObject&>(object).absoluteClippedOverflowRect();
+ ts << " " << enclosingIntRect(const_cast<RenderObject&>(object).absoluteClippedOverflowRect());
writeStyle(ts, object);
return ts;
}
@@ -369,7 +369,7 @@ static TextStream& operator<<(TextStream& ts, const RenderSVGShape& shape)
SVGPathElement* element = static_cast<SVGPathElement*>(svgElement);
String pathString;
// FIXME: We should switch to UnalteredParsing here - this will affect the path dumping output of dozens of tests.
- SVGPathParserFactory::self()->buildStringFromByteStream(element->pathByteStream(), pathString, NormalizedParsing);
+ buildStringFromByteStream(element->pathByteStream(), pathString, NormalizedParsing);
writeNameAndQuotedValue(ts, "data", pathString);
} else
ASSERT_NOT_REACHED();
@@ -443,9 +443,9 @@ static inline void writeSVGInlineTextBox(TextStream& ts, SVGInlineTextBox* textB
else
ts << " width " << fragment.width;
- if (!textBox->isLeftToRightDirection() || textBox->m_dirOverride) {
+ if (!textBox->isLeftToRightDirection() || textBox->dirOverride()) {
ts << (textBox->isLeftToRightDirection() ? " LTR" : " RTL");
- if (textBox->m_dirOverride)
+ if (textBox->dirOverride())
ts << " override";
}
diff --git a/Source/WebCore/rendering/svg/SVGRenderingContext.cpp b/Source/WebCore/rendering/svg/SVGRenderingContext.cpp
index 0f13dcf3a..80f53ef17 100644
--- a/Source/WebCore/rendering/svg/SVGRenderingContext.cpp
+++ b/Source/WebCore/rendering/svg/SVGRenderingContext.cpp
@@ -33,10 +33,11 @@
#include "RenderSVGResourceClipper.h"
#include "RenderSVGResourceFilter.h"
#include "RenderSVGResourceMasker.h"
-#include "SVGImageBufferTools.h"
#include "SVGResources.h"
#include "SVGResourcesCache.h"
+static int kMaxImageBufferSize = 4096;
+
namespace WebCore {
static inline bool isRenderingMaskImage(RenderObject* object)
@@ -160,6 +161,134 @@ void SVGRenderingContext::prepareToRenderSVGContent(RenderObject* object, PaintI
m_renderingFlags |= RenderingPrepared;
}
+static AffineTransform& currentContentTransformation()
+{
+ DEFINE_STATIC_LOCAL(AffineTransform, s_currentContentTransformation, ());
+ return s_currentContentTransformation;
+}
+
+void SVGRenderingContext::calculateTransformationToOutermostSVGCoordinateSystem(const RenderObject* renderer, AffineTransform& absoluteTransform)
+{
+ const RenderObject* current = renderer;
+ ASSERT(current);
+
+ absoluteTransform = currentContentTransformation();
+ while (current) {
+ absoluteTransform = current->localToParentTransform() * absoluteTransform;
+ if (current->isSVGRoot())
+ break;
+ current = current->parent();
+ }
+}
+
+bool SVGRenderingContext::createImageBuffer(const FloatRect& targetRect, const AffineTransform& absoluteTransform, OwnPtr<ImageBuffer>& imageBuffer, ColorSpace colorSpace, RenderingMode renderingMode)
+{
+ IntRect paintRect = calculateImageBufferRect(targetRect, absoluteTransform);
+ // Don't create empty ImageBuffers.
+ if (paintRect.isEmpty())
+ return false;
+
+ IntSize clampedSize = clampedAbsoluteSize(paintRect.size());
+ OwnPtr<ImageBuffer> image = ImageBuffer::create(clampedSize, 1, colorSpace, renderingMode);
+ if (!image)
+ return false;
+
+ GraphicsContext* imageContext = image->context();
+ ASSERT(imageContext);
+
+ // This is done in absolute coordinates.
+ imageContext->translate(-paintRect.x(), -paintRect.y());
+
+ imageContext->concatCTM(absoluteTransform);
+
+ // This happens in local coordinates.
+ imageContext->scale(FloatSize(static_cast<float>(clampedSize.width()) / paintRect.width(),
+ static_cast<float>(clampedSize.height()) / paintRect.height()));
+
+ imageBuffer = image.release();
+ return true;
+}
+
+bool SVGRenderingContext::createImageBufferForPattern(const FloatRect& absoluteTargetRect, const FloatRect& clampedAbsoluteTargetRect, OwnPtr<ImageBuffer>& imageBuffer, ColorSpace colorSpace, RenderingMode renderingMode)
+{
+ IntSize imageSize(roundedIntSize(clampedAbsoluteTargetRect.size()));
+ IntSize unclampedImageSize(roundedIntSize(absoluteTargetRect.size()));
+
+ // Don't create empty ImageBuffers.
+ if (imageSize.isEmpty())
+ return false;
+
+ OwnPtr<ImageBuffer> image = ImageBuffer::create(imageSize, 1, colorSpace, renderingMode);
+ if (!image)
+ return false;
+
+ GraphicsContext* imageContext = image->context();
+ ASSERT(imageContext);
+
+ // Compensate rounding effects, as the absolute target rect is using floating-point numbers and the image buffer size is integer.
+ imageContext->scale(FloatSize(unclampedImageSize.width() / absoluteTargetRect.width(), unclampedImageSize.height() / absoluteTargetRect.height()));
+
+ imageBuffer = image.release();
+ return true;
+}
+
+void SVGRenderingContext::renderSubtreeToImageBuffer(ImageBuffer* image, RenderObject* item, const AffineTransform& subtreeContentTransformation)
+{
+ ASSERT(item);
+ ASSERT(image);
+ ASSERT(image->context());
+
+ PaintInfo info(image->context(), PaintInfo::infiniteRect(), PaintPhaseForeground, 0, 0, 0, 0);
+
+ AffineTransform& contentTransformation = currentContentTransformation();
+ AffineTransform savedContentTransformation = contentTransformation;
+ contentTransformation = subtreeContentTransformation * contentTransformation;
+
+ ASSERT(!item->needsLayout());
+ item->paint(info, IntPoint());
+
+ contentTransformation = savedContentTransformation;
+}
+
+void SVGRenderingContext::clipToImageBuffer(GraphicsContext* context, const AffineTransform& absoluteTransform, const FloatRect& targetRect, OwnPtr<ImageBuffer>& imageBuffer, bool safeToClear)
+{
+ ASSERT(context);
+ ASSERT(imageBuffer);
+
+ FloatRect absoluteTargetRect = calculateImageBufferRect(targetRect, absoluteTransform);
+
+ // The mask image has been created in the absolute coordinate space, as the image should not be scaled.
+ // So the actual masking process has to be done in the absolute coordinate space as well.
+ context->concatCTM(absoluteTransform.inverse());
+ context->clipToImageBuffer(imageBuffer.get(), absoluteTargetRect);
+ context->concatCTM(absoluteTransform);
+
+ // When nesting resources, with objectBoundingBox as content unit types, there's no use in caching the
+ // resulting image buffer as the parent resource already caches the result.
+ if (safeToClear && !currentContentTransformation().isIdentity())
+ imageBuffer.clear();
+}
+
+FloatRect SVGRenderingContext::clampedAbsoluteTargetRect(const FloatRect& absoluteTargetRect)
+{
+ const FloatSize maxImageBufferSize(kMaxImageBufferSize, kMaxImageBufferSize);
+ return FloatRect(absoluteTargetRect.location(), absoluteTargetRect.size().shrunkTo(maxImageBufferSize));
+}
+
+IntSize SVGRenderingContext::clampedAbsoluteSize(const IntSize& absoluteSize)
+{
+ const IntSize maxImageBufferSize(kMaxImageBufferSize, kMaxImageBufferSize);
+ return absoluteSize.shrunkTo(maxImageBufferSize);
+}
+
+void SVGRenderingContext::clear2DRotation(AffineTransform& transform)
+{
+ AffineTransform::DecomposedType decomposition;
+ transform.decompose(decomposition);
+ decomposition.angle = 0;
+ transform.recompose(decomposition);
+}
+
}
#endif
diff --git a/Source/WebCore/rendering/svg/SVGRenderingContext.h b/Source/WebCore/rendering/svg/SVGRenderingContext.h
index 1dc3d6220..4649d9ab7 100644
--- a/Source/WebCore/rendering/svg/SVGRenderingContext.h
+++ b/Source/WebCore/rendering/svg/SVGRenderingContext.h
@@ -76,6 +76,23 @@ public:
void prepareToRenderSVGContent(RenderObject*, PaintInfo&, NeedsGraphicsContextSave = DontSaveGraphicsContext);
bool isRenderingPrepared() const { return m_renderingFlags & RenderingPrepared; }
+ static bool createImageBuffer(const FloatRect& paintRect, const AffineTransform& absoluteTransform, OwnPtr<ImageBuffer>&, ColorSpace, RenderingMode);
+ // Patterns need a different float-to-integer coordinate mapping.
+ static bool createImageBufferForPattern(const FloatRect& absoluteTargetRect, const FloatRect& clampedAbsoluteTargetRect, OwnPtr<ImageBuffer>&, ColorSpace, RenderingMode);
+
+ static void renderSubtreeToImageBuffer(ImageBuffer*, RenderObject*, const AffineTransform&);
+ static void clipToImageBuffer(GraphicsContext*, const AffineTransform& absoluteTransform, const FloatRect& targetRect, OwnPtr<ImageBuffer>&, bool safeToClear);
+
+ static void calculateTransformationToOutermostSVGCoordinateSystem(const RenderObject*, AffineTransform& absoluteTransform);
+ static IntSize clampedAbsoluteSize(const IntSize&);
+ static FloatRect clampedAbsoluteTargetRect(const FloatRect& absoluteTargetRect);
+ static void clear2DRotation(AffineTransform&);
+
+ static IntRect calculateImageBufferRect(const FloatRect& targetRect, const AffineTransform& absoluteTransform)
+ {
+ return enclosingIntRect(absoluteTransform.mapRect(targetRect));
+ }
+
private:
// To properly revert partially successful initializtions in the destructor, we record all successful steps.
enum RenderingFlags {